Skip to content

Commit 4c66496

Browse files
committed
When deriveing, 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.
1 parent 8c4db85 commit 4c66496

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

compiler/rustc_builtin_macros/src/deriving/generic/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,15 @@ fn find_type_parameters(
412412

413413
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
414414
fn visit_ty(&mut self, ty: &'a ast::Ty) {
415+
let stack_len = self.bound_generic_params_stack.len();
416+
if let ast::TyKind::BareFn(bare_fn) = &ty.kind
417+
&& !bare_fn.generic_params.is_empty()
418+
{
419+
// Given a field `x: for<'a> fn(T::SomeType<'a>)`, we wan't to account for `'a` so
420+
// that we generate `where for<'a> T::SomeType<'a>: ::core::clone::Clone`. #122622
421+
self.bound_generic_params_stack.extend(bare_fn.generic_params.iter().cloned());
422+
}
423+
415424
if let ast::TyKind::Path(_, path) = &ty.kind
416425
&& let Some(segment) = path.segments.first()
417426
&& self.ty_param_names.contains(&segment.ident.name)
@@ -422,7 +431,8 @@ fn find_type_parameters(
422431
});
423432
}
424433

425-
visit::walk_ty(self, ty)
434+
visit::walk_ty(self, ty);
435+
self.bound_generic_params_stack.truncate(stack_len);
426436
}
427437

428438
// Place bound generic params on a stack, to extract them when a type is encountered.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ run-pass
2+
// Issue #122622: `#[derive(Clone)]` should work for HRTB function type taking an associated type
3+
#122622
4+
#![allow(dead_code)]
5+
trait SomeTrait {
6+
type SomeType<'a>;
7+
}
8+
9+
#[derive(Clone)]
10+
struct Foo<T: SomeTrait> {
11+
x: for<'a> fn(T::SomeType<'a>)
12+
}
13+
14+
fn main() {}

0 commit comments

Comments
 (0)