about summary refs log tree commit diff
path: root/compiler/rustc_builtin_macros/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-06-06 04:17:26 +0200
committerGitHub <noreply@github.com>2024-06-06 04:17:26 +0200
commit55b76f4720ed2f230770c479f502904f1f31d5d1 (patch)
treec3c7a18ef321be743948a98e5716a753dbe0b980 /compiler/rustc_builtin_macros/src
parent8f04878deecba4e0ec36fb2ff06c58a45579f296 (diff)
parente7ad2da7f134c66779625a09b134b85ed1c7c7a9 (diff)
downloadrust-55b76f4720ed2f230770c479f502904f1f31d5d1.tar.gz
rust-55b76f4720ed2f230770c479f502904f1f31d5d1.zip
Rollup merge of #125987 - estebank:issue-122622, r=Nadrieril
When `derive`ing, account for HRTB on `BareFn` fields

When given

```rust
trait SomeTrait {
    type SomeType<'a>;
}

#[derive(Clone)]
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.

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->
Diffstat (limited to 'compiler/rustc_builtin_macros/src')
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs12
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.