Skip to content

Commit f03eb6b

Browse files
committed
Auto merge of #89341 - audunhalland:derive-type-params-with-bound-generic-params, r=jackh726
Deriving: Include bound generic params in type parameters for where clause Fixes #89188. The `derive` macro ignored the `for<'s>` needed with the `Fn` trait in that code example. edit: I'm unsure if this might cause regressions. I'm not an experienced compiler developer so I'm not used to thinking about unwanted side effects code changes like this might have.
2 parents d14731c + 87241e9 commit f03eb6b

File tree

2 files changed

+79
-10
lines changed

2 files changed

+79
-10
lines changed

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

+40-10
Original file line numberDiff line numberDiff line change
@@ -332,44 +332,74 @@ pub fn combine_substructure(
332332
RefCell::new(f)
333333
}
334334

335+
struct TypeParameter {
336+
bound_generic_params: Vec<ast::GenericParam>,
337+
ty: P<ast::Ty>,
338+
}
339+
335340
/// This method helps to extract all the type parameters referenced from a
336341
/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
337342
/// is not global and starts with `T`, or a `TyQPath`.
343+
/// Also include bound generic params from the input type.
338344
fn find_type_parameters(
339345
ty: &ast::Ty,
340346
ty_param_names: &[Symbol],
341347
cx: &ExtCtxt<'_>,
342-
) -> Vec<P<ast::Ty>> {
348+
) -> Vec<TypeParameter> {
343349
use rustc_ast::visit;
344350

345351
struct Visitor<'a, 'b> {
346352
cx: &'a ExtCtxt<'b>,
347353
ty_param_names: &'a [Symbol],
348-
types: Vec<P<ast::Ty>>,
354+
bound_generic_params_stack: Vec<ast::GenericParam>,
355+
type_params: Vec<TypeParameter>,
349356
}
350357

351358
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
352359
fn visit_ty(&mut self, ty: &'a ast::Ty) {
353360
if let ast::TyKind::Path(_, ref path) = ty.kind {
354361
if let Some(segment) = path.segments.first() {
355362
if self.ty_param_names.contains(&segment.ident.name) {
356-
self.types.push(P(ty.clone()));
363+
self.type_params.push(TypeParameter {
364+
bound_generic_params: self.bound_generic_params_stack.clone(),
365+
ty: P(ty.clone()),
366+
});
357367
}
358368
}
359369
}
360370

361371
visit::walk_ty(self, ty)
362372
}
363373

374+
// Place bound generic params on a stack, to extract them when a type is encountered.
375+
fn visit_poly_trait_ref(
376+
&mut self,
377+
trait_ref: &'a ast::PolyTraitRef,
378+
modifier: &'a ast::TraitBoundModifier,
379+
) {
380+
let stack_len = self.bound_generic_params_stack.len();
381+
self.bound_generic_params_stack
382+
.extend(trait_ref.bound_generic_params.clone().into_iter());
383+
384+
visit::walk_poly_trait_ref(self, trait_ref, modifier);
385+
386+
self.bound_generic_params_stack.truncate(stack_len);
387+
}
388+
364389
fn visit_mac_call(&mut self, mac: &ast::MacCall) {
365390
self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros");
366391
}
367392
}
368393

369-
let mut visitor = Visitor { cx, ty_param_names, types: Vec::new() };
394+
let mut visitor = Visitor {
395+
cx,
396+
ty_param_names,
397+
bound_generic_params_stack: Vec::new(),
398+
type_params: Vec::new(),
399+
};
370400
visit::Visitor::visit_ty(&mut visitor, ty);
371401

372-
visitor.types
402+
visitor.type_params
373403
}
374404

375405
impl<'a> TraitDef<'a> {
@@ -617,11 +647,11 @@ impl<'a> TraitDef<'a> {
617647
ty_params.map(|ty_param| ty_param.ident.name).collect();
618648

619649
for field_ty in field_tys {
620-
let tys = find_type_parameters(&field_ty, &ty_param_names, cx);
650+
let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
621651

622-
for ty in tys {
652+
for field_ty_param in field_ty_params {
623653
// if we have already handled this type, skip it
624-
if let ast::TyKind::Path(_, ref p) = ty.kind {
654+
if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind {
625655
if p.segments.len() == 1
626656
&& ty_param_names.contains(&p.segments[0].ident.name)
627657
{
@@ -639,8 +669,8 @@ impl<'a> TraitDef<'a> {
639669

640670
let predicate = ast::WhereBoundPredicate {
641671
span: self.span,
642-
bound_generic_params: Vec::new(),
643-
bounded_ty: ty,
672+
bound_generic_params: field_ty_param.bound_generic_params,
673+
bounded_ty: field_ty_param.ty,
644674
bounds,
645675
};
646676

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// check-pass
2+
3+
#![feature(generic_associated_types)]
4+
5+
trait CallWithShim: Sized {
6+
type Shim<'s>
7+
where
8+
Self: 's;
9+
}
10+
11+
#[derive(Clone)]
12+
struct ShimMethod<T: CallWithShim + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>));
13+
14+
trait CallWithShim2: Sized {
15+
type Shim<T>;
16+
}
17+
18+
struct S<'s>(&'s ());
19+
20+
#[derive(Clone)]
21+
struct ShimMethod2<T: CallWithShim2 + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::Shim<S<'s>>));
22+
23+
trait Trait<'s, 't, 'u> {}
24+
25+
#[derive(Clone)]
26+
struct ShimMethod3<T: CallWithShim2 + 'static>(
27+
pub &'static dyn for<'s> Fn(
28+
&'s mut T::Shim<dyn for<'t> Fn(&'s mut T::Shim<dyn for<'u> Trait<'s, 't, 'u>>)>,
29+
),
30+
);
31+
32+
trait Trait2 {
33+
type As;
34+
}
35+
36+
#[derive(Clone)]
37+
struct ShimMethod4<T: Trait2 + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::As));
38+
39+
pub fn main() {}

0 commit comments

Comments
 (0)