Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace DisplayAsDisplay and PathAsDisplay with AsDisplay trait #251

Merged
merged 1 commit into from Sep 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 15 additions & 17 deletions impl/src/expand.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down
53 changes: 39 additions & 14 deletions src/display.rs
@@ -1,30 +1,55 @@
use std::fmt::Display;
use std::path::{self, Path, PathBuf};
use std::path::{Path, PathBuf};

#[doc(hidden)]
pub trait DisplayAsDisplay {
fn as_display(&self) -> Self;
pub trait AsDisplay {
type Target: Display + ?Sized;

fn as_display(&self) -> &Self::Target;
}

impl<T: Display> DisplayAsDisplay for &T {
fn as_display(&self) -> Self {
impl<T: Display> AsDisplay for &T {
type Target = T;

fn as_display(&self) -> &Self::Target {
self
}
}

#[doc(hidden)]
pub trait PathAsDisplay {
fn as_display(&self) -> path::Display<'_>;
impl AsDisplay for Path {
type Target = PathDisplay;

#[inline]
fn as_display(&self) -> &Self::Target {
PathDisplay::new(self)
}
}

impl PathAsDisplay for Path {
fn as_display(&self) -> path::Display<'_> {
self.display()
impl AsDisplay for PathBuf {
type Target = PathDisplay;

#[inline]
fn as_display(&self) -> &Self::Target {
PathDisplay::new(self.as_path())
}
}

#[doc(hidden)]
#[repr(transparent)]
pub struct PathDisplay(Path);

impl PathDisplay {
#[inline]
fn new(path: &Path) -> &Self {
// SAFETY: PathDisplay is repr(transparent) so casting pointers between
// it and its payload is safe.
unsafe { &*(path as *const Path as *const Self) }
}
}

impl PathAsDisplay for PathBuf {
fn as_display(&self) -> path::Display<'_> {
self.display()
impl Display for PathDisplay {
#[inline]
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
self.0.display().fmt(fmtr)
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -251,7 +251,7 @@ pub mod __private {
#[doc(hidden)]
pub use crate::aserror::AsDynError;
#[doc(hidden)]
pub use crate::display::{DisplayAsDisplay, PathAsDisplay};
pub use crate::display::AsDisplay;
#[cfg(error_generic_member_access)]
#[doc(hidden)]
pub use crate::provide::ThiserrorProvide;
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/no-display.stderr
Expand Up @@ -9,7 +9,7 @@ error[E0599]: the method `as_display` exists for reference `&NoDisplay`, but its
|
= note: the following trait bounds were not satisfied:
`NoDisplay: std::fmt::Display`
which is required by `&NoDisplay: DisplayAsDisplay`
which is required by `&NoDisplay: AsDisplay`
note: the trait `std::fmt::Display` must be implemented
--> $RUST/core/src/fmt/mod.rs
|
Expand Down