Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 6426fba

Browse files
committed
Fix derive bounds for fully-qualified field types
Builtin traits like `Clone`, `Debug`, and `PartialEq` which can be derived look for uses of generics when adding type bounds. However, the procedure for adding these trait bounds did not account for fully-qualified type paths. This causes code which does not fully-qualify paths to generate correct derive bounds, while fully-qualified paths do not receive correct bounds. For example: ``` struct Foo<T: MyTrait>(T::MyType); ``` Will receive the correct `T::MyType: Clone` bound, but: ``` struct Foo<T: MyTrait>(<T>::MyType); ``` Does not. This change modifies generic parameter detection to walk up the chain of `QSelf`s in path types when looking for type parameters, rather than only looking at the outermost type.
1 parent ae9173d commit 6426fba

File tree

2 files changed

+127
-9
lines changed

2 files changed

+127
-9
lines changed

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

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ pub(crate) use SubstructureFields::*;
183183
use rustc_ast::ptr::P;
184184
use rustc_ast::{
185185
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
186-
Generics, Mutability, PatKind, VariantData,
186+
Generics, Mutability, PatKind, QSelf, VariantData,
187187
};
188188
use rustc_attr_parsing::{AttributeKind, AttributeParser, ReprPacked};
189189
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -409,6 +409,22 @@ fn find_type_parameters(
409409
type_params: Vec<TypeParameter>,
410410
}
411411

412+
impl Visitor<'_, '_> {
413+
fn is_path_from_ty_param(&self, qself: &Option<P<QSelf>>, path: &ast::Path) -> bool {
414+
if let Some(qself) = qself
415+
&& let ast::TyKind::Path(qself, path) = &qself.ty.kind
416+
{
417+
self.is_path_from_ty_param(&qself, &path)
418+
} else if let Some(segment) = path.segments.first()
419+
&& self.ty_param_names.contains(&segment.ident.name)
420+
{
421+
true
422+
} else {
423+
false
424+
}
425+
}
426+
}
427+
412428
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
413429
fn visit_ty(&mut self, ty: &'a ast::Ty) {
414430
let stack_len = self.bound_generic_params_stack.len();
@@ -420,14 +436,13 @@ fn find_type_parameters(
420436
self.bound_generic_params_stack.extend(bare_fn.generic_params.iter().cloned());
421437
}
422438

423-
if let ast::TyKind::Path(_, path) = &ty.kind
424-
&& let Some(segment) = path.segments.first()
425-
&& self.ty_param_names.contains(&segment.ident.name)
426-
{
427-
self.type_params.push(TypeParameter {
428-
bound_generic_params: self.bound_generic_params_stack.clone(),
429-
ty: P(ty.clone()),
430-
});
439+
if let ast::TyKind::Path(qself, path) = &ty.kind {
440+
if self.is_path_from_ty_param(qself, path) {
441+
self.type_params.push(TypeParameter {
442+
bound_generic_params: self.bound_generic_params_stack.clone(),
443+
ty: P(ty.clone()),
444+
});
445+
}
431446
}
432447

433448
visit::walk_ty(self, ty);

tests/ui/deriving/deriving-associated-types.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ struct TupleStruct<A, B: DeclaredTrait, C>(
4343
<i32 as DeclaredTrait>::Type,
4444
) where C: WhereTrait;
4545

46+
#[derive(PartialEq, Debug)]
47+
struct TupleStructJustQSelf<B: DeclaredTrait, C>(
48+
<B>::Type,
49+
<B as DeclaredTrait>::Type,
50+
Option<<B as DeclaredTrait>::Type>,
51+
<C as WhereTrait>::Type,
52+
Option<<C as WhereTrait>::Type>,
53+
<i32 as DeclaredTrait>::Type,
54+
) where C: WhereTrait;
55+
4656
#[derive(PartialEq, Debug)]
4757
pub struct Struct<A, B: DeclaredTrait, C> where C: WhereTrait {
4858
m1: module::Type,
@@ -62,6 +72,16 @@ pub struct Struct<A, B: DeclaredTrait, C> where C: WhereTrait {
6272
d: <i32 as DeclaredTrait>::Type,
6373
}
6474

75+
#[derive(PartialEq, Debug)]
76+
pub struct StructJustQSelf<B: DeclaredTrait, C> where C: WhereTrait {
77+
b1: <B>::Type,
78+
b3: <B as DeclaredTrait>::Type,
79+
b4: Option<<B as DeclaredTrait>::Type>,
80+
c3: <C as WhereTrait>::Type,
81+
c4: Option<<C as WhereTrait>::Type>,
82+
d: <i32 as DeclaredTrait>::Type,
83+
}
84+
6585
#[derive(PartialEq, Debug)]
6686
enum Enum<A, B: DeclaredTrait, C> where C: WhereTrait {
6787
Unit,
@@ -101,6 +121,29 @@ enum Enum<A, B: DeclaredTrait, C> where C: WhereTrait {
101121
},
102122
}
103123

124+
#[derive(PartialEq, Debug)]
125+
enum EnumJustQSelf<B: DeclaredTrait, C> where C: WhereTrait {
126+
Unit,
127+
Seq(
128+
<B>::Type,
129+
<B as DeclaredTrait>::Type,
130+
Option<<B as DeclaredTrait>::Type>,
131+
<C>::Type,
132+
<C as WhereTrait>::Type,
133+
Option<<C as WhereTrait>::Type>,
134+
<i32 as DeclaredTrait>::Type,
135+
),
136+
Map {
137+
b1: <B>::Type,
138+
b3: <B as DeclaredTrait>::Type,
139+
b4: Option<<B as DeclaredTrait>::Type>,
140+
c1: <C>::Type,
141+
c3: <C as WhereTrait>::Type,
142+
c4: Option<<C as WhereTrait>::Type>,
143+
d: <i32 as DeclaredTrait>::Type,
144+
},
145+
}
146+
104147
fn main() {
105148
let e: TupleStruct<
106149
i32,
@@ -125,6 +168,19 @@ fn main() {
125168
);
126169
assert_eq!(e, e);
127170

171+
let e: TupleStructJustQSelf<
172+
i32,
173+
i32,
174+
> = TupleStructJustQSelf(
175+
0,
176+
0,
177+
None,
178+
0,
179+
None,
180+
0,
181+
);
182+
assert_eq!(e, e);
183+
128184
let e: Struct<
129185
i32,
130186
i32,
@@ -148,6 +204,19 @@ fn main() {
148204
};
149205
assert_eq!(e, e);
150206

207+
let e: StructJustQSelf<
208+
i32,
209+
i32,
210+
> = StructJustQSelf {
211+
b1: 0,
212+
b3: 0,
213+
b4: None,
214+
c3: 0,
215+
c4: None,
216+
d: 0,
217+
};
218+
assert_eq!(e, e);
219+
151220
let e = Enum::Unit::<i32, i32, i32>;
152221
assert_eq!(e, e);
153222

@@ -196,4 +265,38 @@ fn main() {
196265
d: 0,
197266
};
198267
assert_eq!(e, e);
268+
269+
let e: EnumJustQSelf<
270+
i32,
271+
i32,
272+
> = EnumJustQSelf::Unit;
273+
assert_eq!(e, e);
274+
275+
let e: EnumJustQSelf<
276+
i32,
277+
i32,
278+
> = EnumJustQSelf::Seq(
279+
0,
280+
0,
281+
None,
282+
0,
283+
0,
284+
None,
285+
0,
286+
);
287+
assert_eq!(e, e);
288+
289+
let e: EnumJustQSelf<
290+
i32,
291+
i32,
292+
> = EnumJustQSelf::Map {
293+
b1: 0,
294+
b3: 0,
295+
b4: None,
296+
c1: 0,
297+
c3: 0,
298+
c4: None,
299+
d: 0,
300+
};
301+
assert_eq!(e, e);
199302
}

0 commit comments

Comments
 (0)