From e7ad2da7f134c66779625a09b134b85ed1c7c7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 4 Jun 2024 19:09:15 +0000 Subject: [PATCH] When `derive`ing, account for HRTB on `BareFn` fields When given ```rust trait SomeTrait { type SomeType<'a>; } struct Foo { x: for<'a> fn(T::SomeType<'a>) } ``` expand to ```rust impl ::core::clone::Clone for Foo where for<'a> T::SomeType<'a>: ::core::clone::Clone { #[inline] fn clone(&self) -> Foo { Foo { x: ::core::clone::Clone::clone(&self.x) } } } ``` instead of the previous invalid ``` impl ::core::clone::Clone for Foo where T::SomeType<'a>: ::core::clone::Clone { #[inline] fn clone(&self) -> Foo { Foo { x: ::core::clone::Clone::clone(&self.x) } } } ``` Fix #122622. --- .../src/deriving/generic/mod.rs | 12 +++++++++++- .../derive-hrtb-for-bare-fn-field-with-lifetime.rs | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 217fa5ff9f1e5..ba289f9552e22 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -412,6 +412,15 @@ fn find_type_parameters( impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { fn visit_ty(&mut self, ty: &'a ast::Ty) { + let stack_len = self.bound_generic_params_stack.len(); + if let ast::TyKind::BareFn(bare_fn) = &ty.kind + && !bare_fn.generic_params.is_empty() + { + // Given a field `x: for<'a> fn(T::SomeType<'a>)`, we wan't to account for `'a` so + // that we generate `where for<'a> T::SomeType<'a>: ::core::clone::Clone`. #122622 + self.bound_generic_params_stack.extend(bare_fn.generic_params.iter().cloned()); + } + if let ast::TyKind::Path(_, path) = &ty.kind && let Some(segment) = path.segments.first() && self.ty_param_names.contains(&segment.ident.name) @@ -422,7 +431,8 @@ fn find_type_parameters( }); } - visit::walk_ty(self, ty) + visit::walk_ty(self, ty); + self.bound_generic_params_stack.truncate(stack_len); } // Place bound generic params on a stack, to extract them when a type is encountered. diff --git a/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs b/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs new file mode 100644 index 0000000000000..b8a42be6832d6 --- /dev/null +++ b/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs @@ -0,0 +1,13 @@ +//@ run-pass +// Issue #122622: `#[derive(Clone)]` should work for HRTB function type taking an associated type +#![allow(dead_code)] +trait SomeTrait { + type SomeType<'a>; +} + +#[derive(Clone)] +struct Foo { + x: for<'a> fn(T::SomeType<'a>) +} + +fn main() {}