Skip to content

Commit 035d031

Browse files
committed
Rename Self generic param to This in recursive delegations
1 parent 1bfcb28 commit 035d031

7 files changed

Lines changed: 218 additions & 30 deletions

File tree

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
505505

506506
// FIXME(fn_delegation): proper support for parent generics propagation
507507
// in method call scenario.
508-
let segment = self.process_segment(span, &segment, &mut generics.child, false);
508+
let segment = self.process_segment(span, &segment, &mut generics.child);
509509
let segment = self.arena.alloc(segment);
510510

511511
self.arena.alloc(hir::Expr {
@@ -531,14 +531,10 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
531531

532532
new_path.segments = self.arena.alloc_from_iter(
533533
new_path.segments.iter().enumerate().map(|(idx, segment)| {
534-
let mut process_segment = |result, add_lifetimes| {
535-
self.process_segment(span, segment, result, add_lifetimes)
536-
};
537-
538534
if idx + 2 == len {
539-
process_segment(&mut generics.parent, true)
535+
self.process_segment(span, segment, &mut generics.parent)
540536
} else if idx + 1 == len {
541-
process_segment(&mut generics.child, false)
537+
self.process_segment(span, segment, &mut generics.child)
542538
} else {
543539
segment.clone()
544540
}
@@ -548,7 +544,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
548544
hir::QPath::Resolved(ty, self.arena.alloc(new_path))
549545
}
550546
hir::QPath::TypeRelative(ty, segment) => {
551-
let segment = self.process_segment(span, segment, &mut generics.child, false);
547+
let segment = self.process_segment(span, segment, &mut generics.child);
552548

553549
hir::QPath::TypeRelative(ty, self.arena.alloc(segment))
554550
}
@@ -575,13 +571,12 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
575571
span: Span,
576572
segment: &hir::PathSegment<'hir>,
577573
result: &mut GenericsGenerationResult<'hir>,
578-
add_lifetimes: bool,
579574
) -> hir::PathSegment<'hir> {
580575
let details = result.generics.args_propagation_details();
581576

582577
let segment = if details.should_propagate {
583578
let generics = result.generics.into_hir_generics(self, span);
584-
let args = generics.into_generic_args(self, add_lifetimes, span);
579+
let args = generics.into_generic_args(self, span);
585580

586581
// Needed for better error messages (`trait-impl-wrong-args-count.rs` test).
587582
let args = if args.is_empty() { None } else { Some(args) };

compiler/rustc_ast_lowering/src/delegation/generics.rs

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
66
use rustc_middle::ty::GenericParamDefKind;
77
use rustc_middle::{bug, ty};
88
use rustc_span::symbol::kw;
9-
use rustc_span::{Ident, Span};
9+
use rustc_span::{Ident, Span, Symbol};
1010

1111
use crate::{LoweringContext, ResolverAstLoweringExt};
1212

@@ -25,22 +25,37 @@ pub(super) enum DelegationGenericsKind {
2525
TraitImpl(bool /* Has user-specified args */),
2626
}
2727

28+
#[derive(Debug, Clone, Copy)]
29+
pub(super) enum GenericsPosition {
30+
Parent,
31+
Child,
32+
}
33+
2834
pub(super) struct DelegationGenerics<T> {
2935
generics: T,
3036
kind: DelegationGenericsKind,
37+
pos: GenericsPosition,
3138
}
3239

3340
impl<'hir> DelegationGenerics<&'hir [ty::GenericParamDef]> {
34-
fn default(generics: &'hir [ty::GenericParamDef]) -> Self {
35-
DelegationGenerics { generics, kind: DelegationGenericsKind::Default }
41+
fn default(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self {
42+
DelegationGenerics { generics, pos, kind: DelegationGenericsKind::Default }
3643
}
3744

38-
fn user_specified(generics: &'hir [ty::GenericParamDef]) -> Self {
39-
DelegationGenerics { generics, kind: DelegationGenericsKind::UserSpecified }
45+
fn user_specified(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self {
46+
DelegationGenerics { generics, pos, kind: DelegationGenericsKind::UserSpecified }
4047
}
4148

42-
fn trait_impl(generics: &'hir [ty::GenericParamDef], user_specified: bool) -> Self {
43-
DelegationGenerics { generics, kind: DelegationGenericsKind::TraitImpl(user_specified) }
49+
fn trait_impl(
50+
generics: &'hir [ty::GenericParamDef],
51+
user_specified: bool,
52+
pos: GenericsPosition,
53+
) -> Self {
54+
DelegationGenerics {
55+
generics,
56+
pos,
57+
kind: DelegationGenericsKind::TraitImpl(user_specified),
58+
}
4459
}
4560
}
4661

@@ -100,9 +115,16 @@ impl<'hir> HirOrTyGenerics<'hir> {
100115
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
101116
span: Span,
102117
) -> &mut HirOrTyGenerics<'hir> {
118+
let rename_self = matches!(self.position(), GenericsPosition::Child);
119+
103120
if let HirOrTyGenerics::Ty(ty) = self {
104-
let params = ctx.uplift_delegation_generic_params(span, ty.generics);
105-
*self = HirOrTyGenerics::Hir(DelegationGenerics { generics: params, kind: ty.kind });
121+
let params = ctx.uplift_delegation_generic_params(span, ty.generics, rename_self);
122+
123+
*self = HirOrTyGenerics::Hir(DelegationGenerics {
124+
generics: params,
125+
kind: ty.kind,
126+
pos: ty.pos,
127+
});
106128
}
107129

108130
self
@@ -118,14 +140,14 @@ impl<'hir> HirOrTyGenerics<'hir> {
118140
pub(super) fn into_generic_args(
119141
&self,
120142
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
121-
add_lifetimes: bool,
122143
span: Span,
123144
) -> &'hir hir::GenericArgs<'hir> {
124145
match self {
125146
HirOrTyGenerics::Ty(_) => {
126147
bug!("Attempting to get generic args before uplifting to HIR")
127148
}
128149
HirOrTyGenerics::Hir(hir) => {
150+
let add_lifetimes = matches!(self.position(), GenericsPosition::Parent);
129151
ctx.create_generics_args_from_params(hir.generics.params, add_lifetimes, span)
130152
}
131153
}
@@ -137,6 +159,13 @@ impl<'hir> HirOrTyGenerics<'hir> {
137159
HirOrTyGenerics::Hir(hir) => hir.kind.args_propagation_details(),
138160
}
139161
}
162+
163+
pub(super) fn position(&self) -> GenericsPosition {
164+
match self {
165+
HirOrTyGenerics::Ty(ty) => ty.pos,
166+
HirOrTyGenerics::Hir(hir) => hir.pos,
167+
}
168+
}
140169
}
141170

142171
impl<'hir> GenericsGenerationResult<'hir> {
@@ -224,10 +253,15 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
224253
if matches!(delegation_parent_kind, DefKind::Impl { of_trait: true }) {
225254
// Considering parent generics, during signature inheritance
226255
// we will take those args that are in trait impl header trait ref.
227-
let parent = DelegationGenerics::trait_impl(&[], true);
256+
let parent = DelegationGenerics::trait_impl(&[], true, GenericsPosition::Parent);
228257
let parent = GenericsGenerationResult::new(parent);
229258

230-
let child = DelegationGenerics::trait_impl(sig_params, child_user_specified);
259+
let child = DelegationGenerics::trait_impl(
260+
sig_params,
261+
child_user_specified,
262+
GenericsPosition::Child,
263+
);
264+
231265
let child = GenericsGenerationResult::new(child);
232266

233267
return GenericsGenerationResults { parent, child };
@@ -254,25 +288,32 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
254288
DelegationGenerics {
255289
kind: DelegationGenericsKind::SelfAndUserSpecified,
256290
generics: &sig_parent_params[..1],
291+
pos: GenericsPosition::Parent,
257292
}
258293
} else {
259-
DelegationGenerics::user_specified(&[])
294+
DelegationGenerics::user_specified(&[], GenericsPosition::Parent)
260295
}
261296
} else {
262297
let skip_self = usize::from(!generate_self);
263-
DelegationGenerics::default(&sig_parent_params[skip_self..])
298+
DelegationGenerics::default(
299+
&sig_parent_params[skip_self..],
300+
GenericsPosition::Parent,
301+
)
264302
}
265303
} else {
266-
DelegationGenerics::default(&[])
304+
DelegationGenerics::default(&[], GenericsPosition::Parent)
267305
};
268306

269307
let child_generics = if child_user_specified {
270308
let synth_params_index =
271309
sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len());
272310

273-
DelegationGenerics::user_specified(&sig_params[synth_params_index..])
311+
DelegationGenerics::user_specified(
312+
&sig_params[synth_params_index..],
313+
GenericsPosition::Child,
314+
)
274315
} else {
275-
DelegationGenerics::default(sig_params)
316+
DelegationGenerics::default(sig_params, GenericsPosition::Child)
276317
};
277318

278319
GenericsGenerationResults {
@@ -285,6 +326,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
285326
&mut self,
286327
span: Span,
287328
params: &'hir [ty::GenericParamDef],
329+
rename_self: bool,
288330
) -> &'hir hir::Generics<'hir> {
289331
let params = self.arena.alloc_from_iter(params.iter().map(|p| {
290332
let def_kind = match p.kind {
@@ -293,7 +335,22 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
293335
GenericParamDefKind::Const { .. } => DefKind::ConstParam,
294336
};
295337

296-
let param_ident = Ident::new(p.name, span);
338+
// Rename Self generic param to This so it is properly propagated.
339+
// If the user will create a function `fn foo<Self>() {}` with generic
340+
// param "Self" then it will not be generated in HIR, the same thing
341+
// applies to traits, `trait Trait<Self> {}` will be represented as
342+
// `trait Trait {}` in HIR and "unexpected keyword `Self` in generic parameters"
343+
// error will be emitted.
344+
// Note that we do not rename `Self` to `This` after first reuse from Trait,
345+
// in this case the Self should not be propagated
346+
// and it is OK to have Self generic param generated during lowering.
347+
let param_name = if rename_self && p.name == kw::SelfUpper {
348+
Symbol::intern(&format!("This"))
349+
} else {
350+
p.name
351+
};
352+
353+
let param_ident = Ident::new(param_name, span);
297354
let def_name = Some(param_ident.name);
298355
let node_id = self.next_node_id();
299356

tests/pretty/delegation-inherit-attributes.pp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
fn foo<Self>(self: _, arg1: _) -> _ { <X as T>::foo(self + 1, arg1) }
118118
#[attr = MustUse {reason: "some reason"}]
119119
#[attr = Inline(Hint)]
120-
fn bar<Self>(arg0: _, arg1: _) -> _ { foo(self + 1, arg1) }
120+
fn bar<This>(arg0: _, arg1: _) -> _ { foo::<This>(self + 1, arg1) }
121121
}
122122
}
123123
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#![attr = Feature([fn_delegation#0])]
2+
extern crate std;
3+
#[attr = PreludeImport]
4+
use ::std::prelude::rust_2015::*;
5+
//@ pretty-compare-only
6+
//@ pretty-mode:hir
7+
//@ pp-exact:delegation-self-rename.pp
8+
9+
10+
trait Trait<'a, A, const B: bool> {
11+
fn foo<'b, const B2: bool, T, U,
12+
impl FnOnce() -> usize>(&self, f: impl FnOnce() -> usize) -> usize
13+
where impl FnOnce() -> usize: FnOnce() -> usize { f() + 1 }
14+
}
15+
16+
struct X;
17+
impl <'a, A, const B: bool> Trait<'a, A, B> for X { }
18+
19+
#[attr = Inline(Hint)]
20+
fn foo<'a, Self, A, const B: _, const B2: _, T, U,
21+
impl FnOnce() -> usize>(self: _, arg1: _) -> _ where
22+
'a:'a { self.foo::<B2, T, U>(arg1) }
23+
#[attr = Inline(Hint)]
24+
fn bar<Self, impl FnOnce() -> usize>(self: _, arg1: _)
25+
-> _ { Trait::<'static, (), true>::foo::<true, (), ()>(self, arg1) }
26+
27+
#[attr = Inline(Hint)]
28+
fn foo2<'a, This, A, const B: _, const B2: _, T, U,
29+
impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
30+
'a:'a { foo::<This, A, B, B2, T, U>(arg0, arg1) }
31+
#[attr = Inline(Hint)]
32+
fn bar2<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
33+
-> _ { bar::<This>(arg0, arg1) }
34+
35+
trait Trait2 {
36+
#[attr = Inline(Hint)]
37+
fn foo3<'a, This, A, const B: _, const B2: _, T, U,
38+
impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
39+
'a:'a { foo2::<This, A, B, B2, T, U>(arg0, arg1) }
40+
#[attr = Inline(Hint)]
41+
fn bar3<This, impl FnOnce() -> usize>(arg0: _, arg1: _)
42+
-> _ { bar2::<This>(arg0, arg1) }
43+
}
44+
45+
impl Trait2 for () { }
46+
47+
// FIXME(fn_delegation): do not generate Self in static functions
48+
#[attr = Inline(Hint)]
49+
fn foo4<'a, Self, This, A, const B: _, const B2: _, T, U,
50+
impl FnOnce() -> usize>(arg0: _, arg1: _) -> _ where
51+
'a:'a { <() as Trait2>::foo3::<This, A, B, B2, T, U>(arg0, arg1) }
52+
#[attr = Inline(Hint)]
53+
fn bar4<Self, This, impl FnOnce() -> usize>(arg0: _, arg1: _)
54+
-> _ { <() as Trait2>::bar3::<This>(arg0, arg1) }
55+
56+
fn main() { }
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ pretty-compare-only
2+
//@ pretty-mode:hir
3+
//@ pp-exact:delegation-self-rename.pp
4+
5+
#![feature(fn_delegation)]
6+
7+
trait Trait<'a, A, const B: bool> {
8+
fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
9+
f() + 1
10+
}
11+
}
12+
13+
struct X;
14+
impl<'a, A, const B: bool> Trait<'a, A, B> for X {}
15+
16+
reuse Trait::foo;
17+
reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar;
18+
19+
reuse foo as foo2;
20+
reuse bar as bar2;
21+
22+
trait Trait2 {
23+
reuse foo2 as foo3;
24+
reuse bar2 as bar3;
25+
}
26+
27+
impl Trait2 for () {}
28+
29+
// FIXME(fn_delegation): do not generate Self in static functions
30+
reuse <() as Trait2>::foo3 as foo4;
31+
reuse <() as Trait2>::bar3 as bar4;
32+
33+
fn main() {}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//@ run-pass
2+
3+
#![feature(fn_delegation)]
4+
5+
trait Trait<'a, A, const B: bool> {
6+
fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize {
7+
f() + 1
8+
}
9+
}
10+
11+
struct X;
12+
impl<'a, A, const B: bool> Trait<'a, A, B> for X {}
13+
14+
reuse Trait::foo;
15+
reuse Trait::<'static, (), true>::foo::<true, (), ()> as bar;
16+
17+
reuse foo as foo2;
18+
reuse bar as bar2;
19+
20+
trait Trait2 {
21+
reuse foo2 as foo3;
22+
reuse bar2 as bar3;
23+
}
24+
25+
impl Trait2 for () {}
26+
27+
// FIXME(fn_delegation): do not generate Self in static functions
28+
reuse <() as Trait2>::foo3 as foo4;
29+
reuse <() as Trait2>::bar3 as bar4;
30+
31+
fn main() {
32+
assert_eq!(foo::<'static, X, (), true, false, (), ()>(&X, || 123), 124);
33+
assert_eq!(foo2::<'static, X, (), true, false, (), ()>(&X, || 123), 124);
34+
assert_eq!(<()>::foo3::<'static, X, (), true, false, (), ()>(&X, || 123), 124);
35+
assert_eq!(foo4::<'static, (), X, (), true, false, (), ()>(&X, || 123), 124);
36+
37+
assert_eq!(bar::<X>(&X, || 123), 124);
38+
assert_eq!(bar2::<X>(&X, || 123), 124);
39+
assert_eq!(<()>::bar3::<X>(&X, || 123), 124);
40+
assert_eq!(bar4::<(), X>(&X, || 123), 124);
41+
42+
assert_eq!(bar(&X, || 123), 124);
43+
assert_eq!(bar2(&X, || 123), 124);
44+
assert_eq!(<()>::bar3(&X, || 123), 124);
45+
assert_eq!(bar4::<(), X>(&X, || 123), 124);
46+
}

0 commit comments

Comments
 (0)