From f0e99827f8408cecb3bd00d45a4ed30b4ab1d145 Mon Sep 17 00:00:00 2001 From: Audun Halland Date: Wed, 29 Sep 2021 00:46:29 +0200 Subject: [PATCH 1/4] Deriving: Include bound generic params for extracted type parameters in where clause --- .../src/deriving/generic/mod.rs | 50 +++++++++++++++---- src/test/ui/deriving/issue-89188-gat-hrtb.rs | 14 ++++++ 2 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/deriving/issue-89188-gat-hrtb.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 59f933d422d01..cd013107a0151 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -332,20 +332,27 @@ pub fn combine_substructure( RefCell::new(f) } +struct TypeParameter { + bound_generic_params: Vec, + ty: P, +} + /// This method helps to extract all the type parameters referenced from a /// type. For a type parameter ``, it looks for either a `TyPath` that /// is not global and starts with `T`, or a `TyQPath`. +/// Also include bound generic params from the input type. fn find_type_parameters( ty: &ast::Ty, ty_param_names: &[Symbol], cx: &ExtCtxt<'_>, -) -> Vec> { +) -> Vec { use rustc_ast::visit; struct Visitor<'a, 'b> { cx: &'a ExtCtxt<'b>, ty_param_names: &'a [Symbol], - types: Vec>, + bound_generic_params_stack: Vec, + type_params: Vec, } impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { @@ -353,7 +360,10 @@ fn find_type_parameters( if let ast::TyKind::Path(_, ref path) = ty.kind { if let Some(segment) = path.segments.first() { if self.ty_param_names.contains(&segment.ident.name) { - self.types.push(P(ty.clone())); + self.type_params.push(TypeParameter { + bound_generic_params: self.bound_generic_params_stack.clone(), + ty: P(ty.clone()), + }); } } } @@ -361,15 +371,35 @@ fn find_type_parameters( visit::walk_ty(self, ty) } + // Place bound generic params on a stack, to extract them when a type is encountered. + fn visit_poly_trait_ref( + &mut self, + trait_ref: &'a ast::PolyTraitRef, + modifier: &'a ast::TraitBoundModifier, + ) { + let stack_len = trait_ref.bound_generic_params.len(); + self.bound_generic_params_stack + .extend(trait_ref.bound_generic_params.clone().into_iter()); + + visit::walk_poly_trait_ref(self, trait_ref, modifier); + + self.bound_generic_params_stack.truncate(stack_len); + } + fn visit_mac_call(&mut self, mac: &ast::MacCall) { self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros"); } } - let mut visitor = Visitor { cx, ty_param_names, types: Vec::new() }; + let mut visitor = Visitor { + cx, + ty_param_names, + bound_generic_params_stack: Vec::new(), + type_params: Vec::new(), + }; visit::Visitor::visit_ty(&mut visitor, ty); - visitor.types + visitor.type_params } impl<'a> TraitDef<'a> { @@ -617,11 +647,11 @@ impl<'a> TraitDef<'a> { ty_params.map(|ty_param| ty_param.ident.name).collect(); for field_ty in field_tys { - let tys = find_type_parameters(&field_ty, &ty_param_names, cx); + let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx); - for ty in tys { + for field_ty_param in field_ty_params { // if we have already handled this type, skip it - if let ast::TyKind::Path(_, ref p) = ty.kind { + if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind { if p.segments.len() == 1 && ty_param_names.contains(&p.segments[0].ident.name) { @@ -639,8 +669,8 @@ impl<'a> TraitDef<'a> { let predicate = ast::WhereBoundPredicate { span: self.span, - bound_generic_params: Vec::new(), - bounded_ty: ty, + bound_generic_params: field_ty_param.bound_generic_params, + bounded_ty: field_ty_param.ty, bounds, }; diff --git a/src/test/ui/deriving/issue-89188-gat-hrtb.rs b/src/test/ui/deriving/issue-89188-gat-hrtb.rs new file mode 100644 index 0000000000000..32954914fb7ed --- /dev/null +++ b/src/test/ui/deriving/issue-89188-gat-hrtb.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait CallWithShim: Sized { + type Shim<'s> + where + Self: 's; +} + +#[derive(Clone)] +struct ShimMethod(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>)); + +pub fn main() {} From e559867d8622bf2f9c09e66d384157a3b836043f Mon Sep 17 00:00:00 2001 From: Audun Halland Date: Wed, 29 Sep 2021 03:18:56 +0200 Subject: [PATCH 2/4] Fix truncate of 'bound params stack' by using the correct length --- compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index cd013107a0151..0f88995846cc1 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -377,7 +377,7 @@ fn find_type_parameters( trait_ref: &'a ast::PolyTraitRef, modifier: &'a ast::TraitBoundModifier, ) { - let stack_len = trait_ref.bound_generic_params.len(); + let stack_len = self.bound_generic_params_stack.len(); self.bound_generic_params_stack .extend(trait_ref.bound_generic_params.clone().into_iter()); From 34d95d9090c300b5ad8612b732ed947a67c6666b Mon Sep 17 00:00:00 2001 From: Audun Halland Date: Wed, 29 Sep 2021 20:17:33 +0200 Subject: [PATCH 3/4] Additional tests (from jackh726) --- src/test/ui/deriving/issue-89188-gat-hrtb.rs | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/ui/deriving/issue-89188-gat-hrtb.rs b/src/test/ui/deriving/issue-89188-gat-hrtb.rs index 32954914fb7ed..e26848758facd 100644 --- a/src/test/ui/deriving/issue-89188-gat-hrtb.rs +++ b/src/test/ui/deriving/issue-89188-gat-hrtb.rs @@ -11,4 +11,27 @@ trait CallWithShim: Sized { #[derive(Clone)] struct ShimMethod(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>)); +trait CallWithShim2: Sized { + type Shim; +} + +struct S<'s>(&'s ()); + +#[derive(Clone)] +struct ShimMethod2(pub &'static dyn for<'s> Fn(&'s mut T::Shim>)); + +trait Trait<'s, 't> {} + +#[derive(Clone)] +struct ShimMethod3( + pub &'static dyn for<'s> Fn(&'s mut T::Shim Trait<'s, 't>>), +); + +trait Trait2 { + type As; +} + +#[derive(Clone)] +struct ShimMethod4(pub &'static dyn for<'s> Fn(&'s mut T::As)); + pub fn main() {} From 87241e909933b30bb31af4edf58d1a331589df3c Mon Sep 17 00:00:00 2001 From: Audun Halland Date: Sat, 2 Oct 2021 11:26:10 +0200 Subject: [PATCH 4/4] Expand one test (from jackh726) --- src/test/ui/deriving/issue-89188-gat-hrtb.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/ui/deriving/issue-89188-gat-hrtb.rs b/src/test/ui/deriving/issue-89188-gat-hrtb.rs index e26848758facd..abd85a616a4ad 100644 --- a/src/test/ui/deriving/issue-89188-gat-hrtb.rs +++ b/src/test/ui/deriving/issue-89188-gat-hrtb.rs @@ -20,11 +20,13 @@ struct S<'s>(&'s ()); #[derive(Clone)] struct ShimMethod2(pub &'static dyn for<'s> Fn(&'s mut T::Shim>)); -trait Trait<'s, 't> {} +trait Trait<'s, 't, 'u> {} #[derive(Clone)] struct ShimMethod3( - pub &'static dyn for<'s> Fn(&'s mut T::Shim Trait<'s, 't>>), + pub &'static dyn for<'s> Fn( + &'s mut T::Shim Fn(&'s mut T::Shim Trait<'s, 't, 'u>>)>, + ), ); trait Trait2 {