From 136859154b88758e33a5cbe57d7bd70f1d31615f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 8 Jan 2025 11:34:40 -0800 Subject: [PATCH 1/2] Add regression test for issue 405 error[E0599]: the method `as_display` exists for reference `&::Err`, but its trait bounds were not satisfied --> tests/test_generics.rs:178:13 | 178 | #[error("couldn't parse entry: {0}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `&::Err` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `::Err: std::fmt::Display` which is required by `&::Err: AsDisplay<'_>` --- tests/test_generics.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_generics.rs b/tests/test_generics.rs index 36f1181..bcbfee0 100644 --- a/tests/test_generics.rs +++ b/tests/test_generics.rs @@ -1,6 +1,7 @@ #![allow(clippy::needless_late_init, clippy::uninlined_format_args)] use core::fmt::{self, Debug, Display}; +use core::str::FromStr; use thiserror::Error; pub struct NoFormat; @@ -160,6 +161,24 @@ pub struct StructFromGeneric { #[error(transparent)] pub struct StructTransparentGeneric(pub E); +// Should expand to: +// +// impl Display for AssociatedTypeError +// where +// T::Err: Display; +// +// impl Error for AssociatedTypeError +// where +// Self: Debug + Display; +// +#[derive(Error, Debug)] +pub enum AssociatedTypeError { + #[error("couldn't parse matrix")] + Other, + #[error("couldn't parse entry: {0}")] + EntryParseError(T::Err), +} + // Regression test for https://github.com/dtolnay/thiserror/issues/345 #[test] fn test_no_bound_on_named_fmt() { From 6b3e1e50b27d9f90fd4a4be098d4693e50609784 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 8 Jan 2025 11:41:16 -0800 Subject: [PATCH 2/2] Generate trait bounds on associated types --- impl/src/generics.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/impl/src/generics.rs b/impl/src/generics.rs index 254c2ed..26fe0a9 100644 --- a/impl/src/generics.rs +++ b/impl/src/generics.rs @@ -25,11 +25,12 @@ impl<'a> ParamsInScope<'a> { fn crawl(in_scope: &ParamsInScope, ty: &Type, found: &mut bool) { if let Type::Path(ty) = ty { - if ty.qself.is_none() { - if let Some(ident) = ty.path.get_ident() { - if in_scope.names.contains(ident) { - *found = true; - } + if let Some(qself) = &ty.qself { + crawl(in_scope, &qself.ty, found); + } else { + let front = ty.path.segments.first().unwrap(); + if front.arguments.is_none() && in_scope.names.contains(&front.ident) { + *found = true; } } for segment in &ty.path.segments {