Replace DisplayAsDisplay and PathAsDisplay with AsDisplay trait

Rather than having separate traits implementing as_display method,
replace DisplayAsDisplay and PathAsDisplay traits with a AsDisplay
trait.  The difference between those two traits is in the result
returned by the as_display method.  With AsDisplay trait this is
captured by an associated type.

The main motivation for the change is making it simpler to support
no_std builds in the future.  Previously, PathAsDisplay would have to
be handled specially in such builds on the side of macro expansion.
Now, thiserror-impl doesn’t need to be aware of any complications
around AsDisplay since they are all contained in thiserror crate.
This commit is contained in:
Michal Nazarewicz 2023-08-04 19:52:42 +02:00
parent 0495eaa802
commit 97eeb45b8b
4 changed files with 56 additions and 33 deletions

View file

@ -120,14 +120,7 @@ fn impl_struct(input: Struct) -> TokenStream {
})
} else if let Some(display) = &input.attrs.display {
display_implied_bounds = display.implied_bounds.clone();
let use_as_display = if display.has_bonus_display {
Some(quote! {
#[allow(unused_imports)]
use thiserror::__private::{DisplayAsDisplay, PathAsDisplay};
})
} else {
None
};
let use_as_display = impl_use_as_display(display.has_bonus_display);
let pat = fields_pat(&input.fields);
Some(quote! {
#use_as_display
@ -351,19 +344,13 @@ fn impl_enum(input: Enum) -> TokenStream {
let display_impl = if input.has_display() {
let mut display_inferred_bounds = InferredBounds::new();
let use_as_display = if input.variants.iter().any(|v| {
let use_as_display = input.variants.iter().any(|v| {
v.attrs
.display
.as_ref()
.map_or(false, |display| display.has_bonus_display)
}) {
Some(quote! {
#[allow(unused_imports)]
use thiserror::__private::{DisplayAsDisplay, PathAsDisplay};
})
} else {
None
};
});
let use_as_display = impl_use_as_display(use_as_display);
let void_deref = if input.variants.is_empty() {
Some(quote!(*))
} else {
@ -466,6 +453,17 @@ fn fields_pat(fields: &[Field]) -> TokenStream {
}
}
fn impl_use_as_display(needs_as_display: bool) -> Option<TokenStream> {
if needs_as_display {
Some(quote! {
#[allow(unused_imports)]
use thiserror::__private::AsDisplay as _;
})
} else {
None
}
}
fn from_initializer(from_field: &Field, backtrace_field: Option<&Field>) -> TokenStream {
let from_member = &from_field.member;
let some_source = if type_is_option(from_field.ty) {