diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2024-06-04 19:09:15 +0000 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2024-06-04 20:46:03 +0000 |
| commit | e7ad2da7f134c66779625a09b134b85ed1c7c7a9 (patch) | |
| tree | 4d06db8b1a550cd547e0e97bcb2b7e7c6c02ce25 /compiler/rustc_builtin_macros/src | |
| parent | 8c4db851a7bb64173832e6602638204ebbd373a8 (diff) | |
| download | rust-e7ad2da7f134c66779625a09b134b85ed1c7c7a9.tar.gz rust-e7ad2da7f134c66779625a09b134b85ed1c7c7a9.zip | |
When `derive`ing, account for HRTB on `BareFn` fields
When given
```rust
trait SomeTrait {
type SomeType<'a>;
}
struct Foo<T: SomeTrait> {
x: for<'a> fn(T::SomeType<'a>)
}
```
expand to
```rust
impl<T: ::core::clone::Clone + SomeTrait> ::core::clone::Clone for Foo<T>
where for<'a> T::SomeType<'a>: ::core::clone::Clone {
#[inline]
fn clone(&self) -> Foo<T> {
Foo { x: ::core::clone::Clone::clone(&self.x) }
}
}
```
instead of the previous invalid
```
impl<T: ::core::clone::Clone + SomeTrait> ::core::clone::Clone for Foo<T>
where T::SomeType<'a>: ::core::clone::Clone {
#[inline]
fn clone(&self) -> Foo<T> {
Foo { x: ::core::clone::Clone::clone(&self.x) }
}
}
```
Fix #122622.
Diffstat (limited to 'compiler/rustc_builtin_macros/src')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 217fa5ff9f1..ba289f9552e 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. |
