diff --git a/impl/src/fmt.rs b/impl/src/fmt.rs index 5c0ff50..1da28c1 100644 --- a/impl/src/fmt.rs +++ b/impl/src/fmt.rs @@ -107,12 +107,14 @@ impl Display<'_> { } }; infinite_recursive |= member == *"self" && bound == Trait::Display; - if let Some(&field) = member_index.get(&member) { - implied_bounds.insert((field, bound)); - } else { - out += &member.to_string(); - continue; - } + let field = match member_index.get(&member) { + Some(&field) => field, + None => { + out += &member.to_string(); + continue; + } + }; + implied_bounds.insert((field, bound)); let formatvar_prefix = if bonus_display { "__display" } else if bound == Trait::Pointer { @@ -129,15 +131,17 @@ impl Display<'_> { while user_named_args.contains(&formatvar) { formatvar = IdentUnraw::new(format_ident!("_{}", formatvar.to_string())); } + formatvar.set_span(span); out += &formatvar.to_string(); if !macro_named_args.insert(formatvar.clone()) { // Already added to bindings by a previous use. continue; } - let binding_value = match &member { + let mut binding_value = match &member { MemberUnraw::Unnamed(index) => format_ident!("_{}", index), MemberUnraw::Named(ident) => ident.to_local(), }; + binding_value.set_span(span.resolved_at(fields[field].member.span())); let wrapped_binding_value = if bonus_display { quote_spanned!(span=> #binding_value.as_display()) } else if bound == Trait::Pointer { diff --git a/impl/src/unraw.rs b/impl/src/unraw.rs index a232621..73b9970 100644 --- a/impl/src/unraw.rs +++ b/impl/src/unraw.rs @@ -28,6 +28,10 @@ impl IdentUnraw { } unraw } + + pub fn set_span(&mut self, span: Span) { + self.0.set_span(span); + } } impl Display for IdentUnraw { diff --git a/tests/test_display.rs b/tests/test_display.rs index 5ee6e36..71c4a4a 100644 --- a/tests/test_display.rs +++ b/tests/test_display.rs @@ -266,7 +266,7 @@ fn test_pointer() { } #[test] -fn test_macro_rules() { +fn test_macro_rules_variant_from_call_site() { // Regression test for https://github.com/dtolnay/thiserror/issues/86 macro_rules! decl_error { @@ -291,6 +291,30 @@ fn test_macro_rules() { assert("0", Error1::Repro(0)); } +#[test] +fn test_macro_rules_message_from_call_site() { + // Regression test for https://github.com/dtolnay/thiserror/issues/398 + + macro_rules! decl_error { + ($($errors:tt)*) => { + #[derive(Error, Debug)] + pub enum Error { + $($errors)* + } + }; + } + + decl_error! { + #[error("{0}")] + Unnamed(u8), + #[error("{x}")] + Named { x: u8 }, + } + + assert("0", Error::Unnamed(0)); + assert("0", Error::Named { x: 0 }); +} + #[test] fn test_raw() { #[derive(Error, Debug)]