Skip to content

Commit

Permalink
Merge pull request #380 from dtolnay/var
Browse files Browse the repository at this point in the history
Print field's address instead of local's address for Pointer
  • Loading branch information
dtolnay authored Nov 8, 2024
2 parents 5dfd2cc + 16f8dc1 commit 8956be2
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 5 deletions.
13 changes: 8 additions & 5 deletions impl/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::attr::{Display, Trait};
use crate::scan_expr::scan_expr;
use crate::unraw::{IdentUnraw, MemberUnraw};
use proc_macro2::{Delimiter, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens};
use quote::{format_ident, quote, quote_spanned};
use std::collections::{BTreeSet, HashMap, HashSet};
use std::iter;
use syn::ext::IdentExt;
Expand Down Expand Up @@ -85,10 +85,11 @@ impl Display<'_> {
}
_ => continue,
};
let mut binding_value = ToTokens::into_token_stream(match &member {
let binding_value = match &member {
MemberUnraw::Unnamed(index) => format_ident!("_{}", index),
MemberUnraw::Named(ident) => ident.to_local(),
});
};
let mut wrapped_binding_value = quote!(::thiserror::__private::Var(#binding_value));
let end_spec = match read.find('}') {
Some(end_spec) => end_spec,
None => return Ok(()),
Expand All @@ -105,7 +106,9 @@ impl Display<'_> {
Some(_) => Trait::Display,
None => {
has_bonus_display = true;
binding_value.extend(quote_spanned!(span=> .as_display()));
wrapped_binding_value = quote_spanned! {span=>
#binding_value.as_display()
};
Trait::Display
}
};
Expand All @@ -126,7 +129,7 @@ impl Display<'_> {
out += &formatvar.to_string();
let local = formatvar.to_local();
if macro_named_args.insert(member) {
bindings.push((local, binding_value));
bindings.push((local, wrapped_binding_value));
} else {
// Already added to bindings by a previous use.
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ mod aserror;
mod display;
#[cfg(error_generic_member_access)]
mod provide;
mod var;

pub use thiserror_impl::*;

Expand All @@ -294,6 +295,8 @@ pub mod __private {
#[doc(hidden)]
pub use crate::provide::ThiserrorProvide;
#[doc(hidden)]
pub use crate::var::Var;
#[doc(hidden)]
pub use core::error::Error;
#[cfg(all(feature = "std", not(thiserror_no_backtrace_type)))]
#[doc(hidden)]
Expand Down
61 changes: 61 additions & 0 deletions src/var.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use core::fmt::{
self, Binary, Debug, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex,
};

pub struct Var<'a, T: ?Sized>(pub &'a T);

/// Pointer is the only one for which there is a difference in behavior between
/// `Var<'a, T>` vs `&'a T`.
impl<'a, T: Pointer + ?Sized> Pointer for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Pointer::fmt(self.0, formatter)
}
}

impl<'a, T: Binary + ?Sized> Binary for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Binary::fmt(self.0, formatter)
}
}

impl<'a, T: Debug + ?Sized> Debug for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(self.0, formatter)
}
}

impl<'a, T: Display + ?Sized> Display for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(self.0, formatter)
}
}

impl<'a, T: LowerExp + ?Sized> LowerExp for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
LowerExp::fmt(self.0, formatter)
}
}

impl<'a, T: LowerHex + ?Sized> LowerHex for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
LowerHex::fmt(self.0, formatter)
}
}

impl<'a, T: Octal + ?Sized> Octal for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Octal::fmt(self.0, formatter)
}
}

impl<'a, T: UpperExp + ?Sized> UpperExp for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
UpperExp::fmt(self.0, formatter)
}
}

impl<'a, T: UpperHex + ?Sized> UpperHex for Var<'a, T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
UpperHex::fmt(self.0, formatter)
}
}
14 changes: 14 additions & 0 deletions tests/test_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,20 @@ fn test_nested_tuple_field() {
assert("0", Error(Inner(0)));
}

#[test]
fn test_pointer() {
#[derive(Error, Debug)]
#[error("{field:p}")]
pub struct Struct {
field: Box<i32>,
}

let s = Struct {
field: Box::new(-1),
};
assert_eq!(s.to_string(), format!("{:p}", s.field));
}

#[test]
fn test_macro_rules() {
// Regression test for https://github.com/dtolnay/thiserror/issues/86
Expand Down

0 comments on commit 8956be2

Please sign in to comment.