Skip to content

Commit

Permalink
Merge branch 'refs/heads/master' into outer-level-enum-formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
tyranron committed Jul 19, 2024
2 parents b877940 + 162535e commit 256c041
Show file tree
Hide file tree
Showing 20 changed files with 584 additions and 143 deletions.
16 changes: 1 addition & 15 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,16 @@ Related to <!-- paste issues/PRs references -->

<!-- Remove the lines above if there are no related issues/PRs -->




## Synopsis

<!-- Give a brief overview of the problem -->




## Solution

<!-- Describe how exactly the problem is (or will be) resolved -->




## Checklist

- [ ] Documentation is updated (if required)
- [ ] Tests are added/updated (if required)
- [ ] [CHANGELOG entry][l:1] is added (if required)




[l:1]: /CHANGELOG.md
- [ ] [CHANGELOG entry](/CHANGELOG.md) is added (if required)
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
([#300](https://github.com/JelteF/derive_more/pull/300))
- `#[inline]` attributes to `IsVariant` and `Debug` implementations.
([#334](https://github.com/JelteF/derive_more/pull/334)
- Add `#[track_caller]` to `Add`, `Mul`, `AddAssign` and `MulAssign` derives
([#378](https://github.com/JelteF/derive_more/pull/378)


### Changed

Expand All @@ -84,8 +87,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
should prevent code style linters from attempting to modify the generated
code.
- Upgrade to `syn` 2.0.
- The `Error` derive now works in nightly `no_std` environments when enabling
`#![feature(error_in_core)]`.
- The `Error` derive now works in nightly `no_std` environments

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion ci/test_all_features.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ fi
set -euxo pipefail

for feature in $(tomljson Cargo.toml | jq --raw-output '.features | keys[]' | grep -v 'default\|std\|full\|testing-helpers'); do
cargo +nightly test -p derive_more --tests --no-default-features --features "$feature$std,testing-helpers"
RUSTFLAGS='-D warnings' cargo +nightly test -p derive_more --tests --no-default-features --features "$feature$std,testing-helpers"
done
2 changes: 1 addition & 1 deletion impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ features = ["full"]
rustdoc-args = ["--cfg", "docsrs"]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(ci)", "cfg(nighthly)"] }
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(ci)", "cfg(nightly)"] }

[features]
default = []
Expand Down
14 changes: 6 additions & 8 deletions impl/doc/error.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,9 @@ ignored for one of these methods by using `#[error(not(backtrace))]` or

### What works in `no_std`?

If you want to use the `Error` derive on `no_std` environments, then you need to
compile with nightly and enable this feature:
```ignore
#![feature(error_in_core)]
```
If you want to use the `Error` derive on `no_std` environments, then
you need to compile with nightly, or wait until Rust 1.81 when `Error`
in `core` is expected to be stabilized.

Backtraces don't work though, because the `Backtrace` type is only available in
`std`.
Expand All @@ -59,9 +57,9 @@ Backtraces don't work though, because the `Backtrace` type is only available in
## Example usage

```rust
# #![cfg_attr(nightly, feature(error_generic_member_access, error_in_core))]
// Nightly requires enabling these features:
// #![feature(error_generic_member_access, error_in_core)]
# #![cfg_attr(nightly, feature(error_generic_member_access))]
// Nightly requires enabling this feature:
// #![feature(error_generic_member_access)]
# #[cfg(not(nightly))] fn main() {}
# #[cfg(nightly)] fn main() {
# use core::error::{request_ref, request_value, Error as __};
Expand Down
1 change: 1 addition & 0 deletions impl/src/add_assign_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
#[automatically_derived]
impl #impl_generics derive_more::#trait_ident for #input_type #ty_generics #where_clause {
#[inline]
#[track_caller]
fn #method_ident(&mut self, rhs: #input_type #ty_generics) {
#( #exprs; )*
}
Expand Down
1 change: 1 addition & 0 deletions impl/src/add_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
type Output = #output_type;

#[inline]
#[track_caller]
fn #method_ident(self, rhs: #input_type #ty_generics) -> #output_type {
#block
}
Expand Down
149 changes: 140 additions & 9 deletions impl/src/fmt/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,21 @@ pub fn expand(input: &syn::DeriveInput, _: &str) -> syn::Result<TokenStream> {
.unwrap_or_default();
let ident = &input.ident;

let type_params: Vec<_> = input
.generics
.params
.iter()
.filter_map(|p| match p {
syn::GenericParam::Type(t) => Some(&t.ident),
syn::GenericParam::Const(..) | syn::GenericParam::Lifetime(..) => None,
})
.collect();

let (bounds, body) = match &input.data {
syn::Data::Struct(s) => expand_struct(attrs, ident, s, &attr_name),
syn::Data::Enum(e) => expand_enum(attrs, e, &attr_name),
syn::Data::Struct(s) => {
expand_struct(attrs, ident, s, &type_params, &attr_name)
}
syn::Data::Enum(e) => expand_enum(attrs, e, &type_params, &attr_name),
syn::Data::Union(_) => {
return Err(syn::Error::new(
input.span(),
Expand Down Expand Up @@ -64,11 +76,13 @@ fn expand_struct(
attrs: ContainerAttributes,
ident: &Ident,
s: &syn::DataStruct,
type_params: &[&syn::Ident],
attr_name: &syn::Ident,
) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> {
let s = Expansion {
attr: &attrs,
fields: &s.fields,
type_params,
ident,
attr_name,
};
Expand All @@ -82,7 +96,7 @@ fn expand_struct(
.ident
.clone()
.map_or_else(|| syn::Member::Unnamed(i.into()), syn::Member::Named);
quote! { let #var = &&self.#member; }
quote! { let #var = &self.#member; }
});

let body = quote! {
Expand All @@ -99,6 +113,7 @@ fn expand_struct(
fn expand_enum(
mut attrs: ContainerAttributes,
e: &syn::DataEnum,
type_params: &[&syn::Ident],
attr_name: &syn::Ident,
) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> {
if let Some(enum_fmt) = attrs.fmt.as_ref() {
Expand Down Expand Up @@ -136,6 +151,7 @@ fn expand_enum(
let v = Expansion {
attr: &attrs,
fields: &variant.fields,
type_params,
ident,
attr_name,
};
Expand Down Expand Up @@ -195,6 +211,9 @@ struct Expansion<'a> {
/// Struct or enum [`syn::Fields`].
fields: &'a syn::Fields,

/// Type parameters in this struct or enum.
type_params: &'a [&'a syn::Ident],

/// Name of the attributes, considered by this macro.
attr_name: &'a syn::Ident,
}
Expand Down Expand Up @@ -275,7 +294,7 @@ impl<'a> Expansion<'a> {
None => {
let ident = format_ident!("_{i}");
Ok(quote! {
derive_more::__private::DebugTuple::field(#out, #ident)
derive_more::__private::DebugTuple::field(#out, &#ident)
})
}
},
Expand Down Expand Up @@ -316,7 +335,7 @@ impl<'a> Expansion<'a> {
)
}),
None => Ok(quote! {
derive_more::core::fmt::DebugStruct::field(#out, #field_str, #field_ident)
derive_more::core::fmt::DebugStruct::field(#out, #field_str, &#field_ident)
}),
}
})?;
Expand All @@ -334,15 +353,26 @@ impl<'a> Expansion<'a> {
let mut out = self.attr.bounds.0.clone().into_iter().collect::<Vec<_>>();

if let Some(fmt) = self.attr.fmt.as_ref() {
out.extend(fmt.bounded_types(self.fields).map(|(ty, trait_name)| {
let trait_ident = format_ident!("{trait_name}");
out.extend(fmt.bounded_types(self.fields).filter_map(
|(ty, trait_name)| {
if !self.contains_generic_param(ty) {
return None;
}

let trait_ident = format_ident!("{trait_name}");

parse_quote! { #ty: derive_more::core::fmt::#trait_ident }
}));
Some(parse_quote! { #ty: derive_more::core::fmt::#trait_ident })
},
));
Ok(out)
} else {
self.fields.iter().try_fold(out, |mut out, field| {
let ty = &field.ty;

if !self.contains_generic_param(ty) {
return Ok(out);
}

match FieldAttribute::parse_attrs(&field.attrs, self.attr_name)?
.map(Spanning::into_inner)
{
Expand All @@ -362,4 +392,105 @@ impl<'a> Expansion<'a> {
})
}
}

/// Checks whether the provided [`syn::Path`] contains any of these [`Expansion::type_params`].
fn path_contains_generic_param(&self, path: &syn::Path) -> bool {
path.segments
.iter()
.any(|segment| match &segment.arguments {
syn::PathArguments::None => false,
syn::PathArguments::AngleBracketed(
syn::AngleBracketedGenericArguments { args, .. },
) => args.iter().any(|generic| match generic {
syn::GenericArgument::Type(ty)
| syn::GenericArgument::AssocType(syn::AssocType { ty, .. }) => {
self.contains_generic_param(ty)
}

syn::GenericArgument::Lifetime(_)
| syn::GenericArgument::Const(_)
| syn::GenericArgument::AssocConst(_)
| syn::GenericArgument::Constraint(_) => false,
_ => unimplemented!(
"syntax is not supported by `derive_more`, please report a bug",
),
}),
syn::PathArguments::Parenthesized(
syn::ParenthesizedGenericArguments { inputs, output, .. },
) => {
inputs.iter().any(|ty| self.contains_generic_param(ty))
|| match output {
syn::ReturnType::Default => false,
syn::ReturnType::Type(_, ty) => {
self.contains_generic_param(ty)
}
}
}
})
}

/// Checks whether the provided [`syn::Type`] contains any of these [`Expansion::type_params`].
fn contains_generic_param(&self, ty: &syn::Type) -> bool {
if self.type_params.is_empty() {
return false;
}
match ty {
syn::Type::Path(syn::TypePath { qself, path }) => {
if let Some(qself) = qself {
if self.contains_generic_param(&qself.ty) {
return true;
}
}

if let Some(ident) = path.get_ident() {
self.type_params.iter().any(|param| *param == ident)
} else {
self.path_contains_generic_param(path)
}
}

syn::Type::Array(syn::TypeArray { elem, .. })
| syn::Type::Group(syn::TypeGroup { elem, .. })
| syn::Type::Paren(syn::TypeParen { elem, .. })
| syn::Type::Ptr(syn::TypePtr { elem, .. })
| syn::Type::Reference(syn::TypeReference { elem, .. })
| syn::Type::Slice(syn::TypeSlice { elem, .. }) => {
self.contains_generic_param(elem)
}

syn::Type::BareFn(syn::TypeBareFn { inputs, output, .. }) => {
inputs
.iter()
.any(|arg| self.contains_generic_param(&arg.ty))
|| match output {
syn::ReturnType::Default => false,
syn::ReturnType::Type(_, ty) => self.contains_generic_param(ty),
}
}
syn::Type::Tuple(syn::TypeTuple { elems, .. }) => {
elems.iter().any(|ty| self.contains_generic_param(ty))
}

syn::Type::ImplTrait(_) => false,
syn::Type::Infer(_) => false,
syn::Type::Macro(_) => false,
syn::Type::Never(_) => false,
syn::Type::TraitObject(syn::TypeTraitObject { bounds, .. }) => {
bounds.iter().any(|bound| match bound {
syn::TypeParamBound::Trait(syn::TraitBound { path, .. }) => {
self.path_contains_generic_param(path)
}
syn::TypeParamBound::Lifetime(_) => false,
syn::TypeParamBound::Verbatim(_) => false,
_ => unimplemented!(
"syntax is not supported by `derive_more`, please report a bug",
),
})
}
syn::Type::Verbatim(_) => false,
_ => unimplemented!(
"syntax is not supported by `derive_more`, please report a bug",
),
}
}
}
1 change: 1 addition & 0 deletions impl/src/mul_assign_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
#[automatically_derived]
impl #impl_generics #trait_path<#scalar_ident> for #input_type #ty_generics #where_clause {
#[inline]
#[track_caller]
fn #method_ident(&mut self, rhs: #scalar_ident) {
#( #exprs; )*
}
Expand Down
1 change: 1 addition & 0 deletions impl/src/mul_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
type Output = #input_type #ty_generics;

#[inline]
#[track_caller]
fn #method_ident(self, rhs: #scalar_ident) -> #input_type #ty_generics {
#body
}
Expand Down
2 changes: 1 addition & 1 deletion impl/src/try_into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
impl #impl_generics derive_more::core::convert::TryFrom<
#reference_with_lifetime #input_type #ty_generics
> for (#(#reference_with_lifetime #original_types),*) #where_clause {
type Error = derive_more::TryIntoError<#reference_with_lifetime #input_type>;
type Error = derive_more::TryIntoError<#reference_with_lifetime #input_type #ty_generics>;

#[inline]
fn try_from(
Expand Down
Loading

0 comments on commit 256c041

Please sign in to comment.