let state = State::with_attr_params(
input,
trait_name,
trait_name.to_lowercase(),
allowed_attr_params(),
)?;
let type_params: HashSet<_> = generics
.params
.iter()
.filter_map(|generic| match generic {
syn::GenericParam::Type(ty) => Some(ty.ident.clone()),
_ => None,
})
.collect();
let (bounds, source, provide) = match state.derive_type {
DeriveType::Named | DeriveType::Unnamed => render_struct(&type_params, &state)?,
DeriveType::Enum => render_enum(&type_params, &state)?,
};
let source = source.map(|source| { // Not using `#[inline]` here on purpose, since this is almost never part // of a hot codepath.
quote! { // TODO: Use `derive_more::core::error::Error` once `error_in_core` Rust feature is // stabilized. fn source(&self) -> Option<&(dyn derive_more::with_trait::Error + 'static)> { use derive_more::__private::AsDynError; #source
}
}
});
let provide = provide.map(|provide| { // Not using `#[inline]` here on purpose, since this is almost never part // of a hot codepath.
quote! { fn provide<'_request>(
&'_request self,
request: &mut derive_more::core::error::Request<'_request>,
) { #provide
}
}
});
letmut generics = generics.clone();
if !type_params.is_empty() { let (_, ty_generics, _) = generics.split_for_impl();
generics = utils::add_extra_where_clauses(
&generics,
quote! { where #ident#ty_generics: derive_more::core::fmt::Debug
+ derive_more::core::fmt::Display
},
);
}
if !bounds.is_empty() { let bounds = bounds.iter();
generics = utils::add_extra_where_clauses(
&generics,
quote! { where#( #bounds: derive_more::core::fmt::Debug
+ derive_more::core::fmt::Display // TODO: Use `derive_more::core::error::Error` once `error_in_core` // Rust feature is stabilized.
+ derive_more::with_trait::Error
+ 'static
),*
},
);
}
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let render = quote! { #[automatically_derived] // TODO: Use `derive_more::core::error::Error` once `error_in_core` Rust feature is // stabilized. impl#impl_generics derive_more::with_trait::Error for#ident#ty_generics#where_clause { #source #provide
}
};
/// Checks if `ty` is [`syn::Type::Path`] and ends with segment matching `tail` /// and doesn't contain any generic parameters. fn is_type_path_ends_with_segment(ty: &syn::Type, tail: &str) -> bool { let syn::Type::Path(ty) = ty else { returnfalse;
};
// Unwrapping is safe, cause 'syn::TypePath.path.segments' // have to have at least one segment let segment = ty.path.segments.last().unwrap();
if !matches!(segment.arguments, syn::PathArguments::None) { returnfalse;
}
segment.ident == tail
}
fn infer_source_field(
fields: &[&syn::Field],
parsed_fields: &ParsedFields,
) -> Option<usize> { // if we have exactly two fields if fields.len() != 2 { return None;
}
// no source field was specified/inferred if parsed_fields.source.is_some() { return None;
}
// but one of the fields was specified/inferred as backtrace field iflet Some(backtrace) = parsed_fields.backtrace { // then infer *other field* as source field let source = (backtrace + 1) % 2; // unless it was explicitly marked as non-source if parsed_fields.data.infos[source].info.source != Some(false) { return Some(source);
}
}
let inferred_fields = iter.filter(|(_, field, info)| match value(info) {
None => is_valid_default_field_for_attr(attr, field, len),
_ => false,
});
let field = assert_iter_contains_zero_or_one_item(
explicit_fields,
&format!( "Multiple `{attr}` attributes specified. \
Single attribute per struct/enum variant allowed.",
),
)?;
let field = match field {
field @ Some(_) => field,
None => assert_iter_contains_zero_or_one_item(
inferred_fields, "Conflicting fields found. Consider specifying some \
`#[error(...)]` attributes to resolve conflict.",
)?,
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.