Skip to content

Commit 8aeaa5f

Browse files
committed
Delegation refactoring: add builders for generics inheritance
1 parent fdf61d4 commit 8aeaa5f

File tree

3 files changed

+215
-110
lines changed

3 files changed

+215
-110
lines changed

compiler/rustc_hir_analysis/src/delegation.rs

+185-80
Original file line numberDiff line numberDiff line change
@@ -76,41 +76,154 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
7676
}
7777
}
7878

79+
struct GenericsBuilder<'tcx> {
80+
tcx: TyCtxt<'tcx>,
81+
sig_id: DefId,
82+
parent: Option<DefId>,
83+
}
84+
85+
impl<'tcx> GenericsBuilder<'tcx> {
86+
fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> {
87+
GenericsBuilder { tcx, sig_id, parent: None }
88+
}
89+
90+
fn build(self) -> ty::Generics {
91+
let mut own_params = vec![];
92+
93+
let sig_generics = self.tcx.generics_of(self.sig_id);
94+
if let Some(parent_def_id) = sig_generics.parent {
95+
let sig_parent_generics = self.tcx.generics_of(parent_def_id);
96+
own_params.append(&mut sig_parent_generics.own_params.clone());
97+
}
98+
own_params.append(&mut sig_generics.own_params.clone());
99+
100+
// Lifetime parameters must be declared before type and const parameters.
101+
// Therefore, When delegating from a free function to a associated function,
102+
// generic parameters need to be reordered:
103+
//
104+
// trait Trait<'a, A> {
105+
// fn foo<'b, B>(...) {...}
106+
// }
107+
//
108+
// reuse Trait::foo;
109+
// desugaring:
110+
// fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
111+
// Trait::foo(...)
112+
// }
113+
own_params.sort_by_key(|key| key.kind.is_ty_or_const());
114+
115+
let param_def_id_to_index =
116+
own_params.iter().map(|param| (param.def_id, param.index)).collect();
117+
118+
let (parent_count, has_self) = if let Some(def_id) = self.parent {
119+
let parent_generics = self.tcx.generics_of(def_id);
120+
let parent_kind = self.tcx.def_kind(def_id);
121+
(parent_generics.count(), parent_kind == DefKind::Trait)
122+
} else {
123+
(0, false)
124+
};
125+
126+
for (idx, param) in own_params.iter_mut().enumerate() {
127+
param.index = (idx + parent_count) as u32;
128+
// Default type parameters are not inherited: they are not allowed
129+
// in fn's.
130+
if let ty::GenericParamDefKind::Type { synthetic, .. } = param.kind {
131+
param.kind = ty::GenericParamDefKind::Type { has_default: false, synthetic }
132+
}
133+
}
134+
135+
ty::Generics {
136+
parent: self.parent,
137+
parent_count,
138+
own_params,
139+
param_def_id_to_index,
140+
has_self,
141+
has_late_bound_regions: sig_generics.has_late_bound_regions,
142+
host_effect_index: sig_generics.host_effect_index,
143+
}
144+
}
145+
}
146+
147+
struct PredicatesBuilder<'tcx> {
148+
tcx: TyCtxt<'tcx>,
149+
args: ty::GenericArgsRef<'tcx>,
150+
parent: Option<DefId>,
151+
sig_id: DefId,
152+
}
153+
154+
impl<'tcx> PredicatesBuilder<'tcx> {
155+
fn new(
156+
tcx: TyCtxt<'tcx>,
157+
args: ty::GenericArgsRef<'tcx>,
158+
sig_id: DefId,
159+
) -> PredicatesBuilder<'tcx> {
160+
PredicatesBuilder { tcx, args, parent: None, sig_id }
161+
}
162+
163+
fn build(self) -> ty::GenericPredicates<'tcx> {
164+
let mut preds = vec![];
165+
166+
let sig_predicates = self.tcx.predicates_of(self.sig_id);
167+
if let Some(parent) = sig_predicates.parent {
168+
let sig_parent_preds = self.tcx.predicates_of(parent);
169+
preds.extend(sig_parent_preds.instantiate_own(self.tcx, self.args));
170+
}
171+
preds.extend(sig_predicates.instantiate_own(self.tcx, self.args));
172+
173+
ty::GenericPredicates {
174+
parent: self.parent,
175+
predicates: self.tcx.arena.alloc_from_iter(preds),
176+
// FIXME(fn_delegation): Support effects.
177+
effects_min_tys: ty::List::empty(),
178+
}
179+
}
180+
}
181+
182+
struct GenericArgsBuilder<'tcx> {
183+
tcx: TyCtxt<'tcx>,
184+
remap_table: RemapTable,
185+
sig_id: DefId,
186+
def_id: LocalDefId,
187+
}
188+
189+
impl<'tcx> GenericArgsBuilder<'tcx> {
190+
fn new(tcx: TyCtxt<'tcx>, sig_id: DefId, def_id: LocalDefId) -> GenericArgsBuilder<'tcx> {
191+
GenericArgsBuilder { tcx, remap_table: FxHashMap::default(), sig_id, def_id }
192+
}
193+
194+
fn build_from_args(mut self, args: ty::GenericArgsRef<'tcx>) -> ty::GenericArgsRef<'tcx> {
195+
let caller_generics = self.tcx.generics_of(self.def_id);
196+
let callee_generics = self.tcx.generics_of(self.sig_id);
197+
198+
for caller_param in &caller_generics.own_params {
199+
let callee_index =
200+
callee_generics.param_def_id_to_index(self.tcx, caller_param.def_id).unwrap();
201+
self.remap_table.insert(callee_index, caller_param.index);
202+
}
203+
204+
let mut folder = ParamIndexRemapper { tcx: self.tcx, remap_table: self.remap_table };
205+
args.fold_with(&mut folder)
206+
}
207+
}
208+
79209
fn create_generic_args<'tcx>(
80210
tcx: TyCtxt<'tcx>,
81211
def_id: LocalDefId,
82212
sig_id: DefId,
83213
) -> ty::GenericArgsRef<'tcx> {
84-
let caller_generics = tcx.generics_of(def_id);
85-
let callee_generics = tcx.generics_of(sig_id);
214+
let builder = GenericArgsBuilder::new(tcx, sig_id, def_id);
86215

87216
let caller_kind = fn_kind(tcx, def_id.into());
88217
let callee_kind = fn_kind(tcx, sig_id);
89-
// FIXME(fn_delegation): Support generics on associated delegation items.
90-
// Error will be reported in `check_constraints`.
218+
91219
match (caller_kind, callee_kind) {
92-
(FnKind::Free, _) => {
93-
// Lifetime parameters must be declared before type and const parameters.
94-
// Therefore, When delegating from a free function to a associated function,
95-
// generic parameters need to be reordered:
96-
//
97-
// trait Trait<'a, A> {
98-
// fn foo<'b, B>(...) {...}
99-
// }
100-
//
101-
// reuse Trait::foo;
102-
// desugaring:
103-
// fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
104-
// Trait::foo(...)
105-
// }
106-
let mut remap_table = RemapTable::default();
107-
for caller_param in &caller_generics.own_params {
108-
let callee_index =
109-
callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap();
110-
remap_table.insert(callee_index, caller_param.index);
111-
}
112-
let mut folder = ParamIndexRemapper { tcx, remap_table };
113-
ty::GenericArgs::identity_for_item(tcx, sig_id).fold_with(&mut folder)
220+
(FnKind::Free, FnKind::Free)
221+
| (FnKind::Free, FnKind::AssocTrait)
222+
| (FnKind::AssocInherentImpl, FnKind::Free)
223+
| (FnKind::AssocTrait, FnKind::Free)
224+
| (FnKind::AssocTrait, FnKind::AssocTrait) => {
225+
let args = ty::GenericArgs::identity_for_item(tcx, sig_id);
226+
builder.build_from_args(args)
114227
}
115228
// FIXME(fn_delegation): Only `Self` param supported here.
116229
(FnKind::AssocTraitImpl, FnKind::AssocTrait)
@@ -120,7 +233,11 @@ fn create_generic_args<'tcx>(
120233
let generic_self_ty = ty::GenericArg::from(self_ty);
121234
tcx.mk_args_from_iter(std::iter::once(generic_self_ty))
122235
}
123-
_ => ty::GenericArgs::identity_for_item(tcx, sig_id),
236+
// For trait impl's `sig_id` is always equal to the corresponding trait method.
237+
(FnKind::AssocTraitImpl, _)
238+
| (_, FnKind::AssocTraitImpl)
239+
// Delegation to inherent methods is not yet supported.
240+
| (_, FnKind::AssocInherentImpl) => unreachable!(),
124241
}
125242
}
126243

@@ -129,74 +246,62 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
129246
def_id: LocalDefId,
130247
sig_id: DefId,
131248
) -> Option<ty::Generics> {
132-
// FIXME(fn_delegation): Support generics on associated delegation items.
133-
// Error will be reported in `check_constraints`.
134-
if fn_kind(tcx, def_id.into()) != FnKind::Free {
135-
return None;
136-
}
249+
let builder = GenericsBuilder::new(tcx, sig_id);
137250

138-
let mut own_params = vec![];
139-
140-
let callee_generics = tcx.generics_of(sig_id);
141-
if let Some(parent_sig_id) = callee_generics.parent {
142-
let parent_sig_generics = tcx.generics_of(parent_sig_id);
143-
own_params.append(&mut parent_sig_generics.own_params.clone());
144-
}
145-
own_params.append(&mut callee_generics.own_params.clone());
251+
let caller_kind = fn_kind(tcx, def_id.into());
252+
let callee_kind = fn_kind(tcx, sig_id);
146253

147-
// Lifetimes go first.
148-
own_params.sort_by_key(|key| key.kind.is_ty_or_const());
254+
// FIXME(fn_delegation): Support generics on associated delegation items.
255+
// Error will be reported in `check_constraints`.
256+
match (caller_kind, callee_kind) {
257+
(FnKind::Free, FnKind::Free)
258+
| (FnKind::Free, FnKind::AssocTrait) => Some(builder.build()),
149259

150-
for (idx, param) in own_params.iter_mut().enumerate() {
151-
param.index = idx as u32;
152-
// Default parameters are not inherited: they are not allowed
153-
// in fn's.
154-
if let ty::GenericParamDefKind::Type { has_default, .. }
155-
| ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
156-
{
157-
*has_default = false;
158-
}
260+
(FnKind::AssocTraitImpl, FnKind::AssocTrait)
261+
| (FnKind::AssocInherentImpl, FnKind::AssocTrait)
262+
| (FnKind::AssocTrait, FnKind::AssocTrait)
263+
| (FnKind::AssocInherentImpl, FnKind::Free)
264+
| (FnKind::AssocTrait, FnKind::Free) => None,
265+
266+
// For trait impl's `sig_id` is always equal to the corresponding trait method.
267+
(FnKind::AssocTraitImpl, _)
268+
| (_, FnKind::AssocTraitImpl)
269+
// Delegation to inherent methods is not yet supported.
270+
| (_, FnKind::AssocInherentImpl) => unreachable!(),
159271
}
160-
161-
let param_def_id_to_index =
162-
own_params.iter().map(|param| (param.def_id, param.index)).collect();
163-
164-
Some(ty::Generics {
165-
parent: None,
166-
parent_count: 0,
167-
own_params,
168-
param_def_id_to_index,
169-
has_self: false,
170-
has_late_bound_regions: callee_generics.has_late_bound_regions,
171-
host_effect_index: callee_generics.host_effect_index,
172-
})
173272
}
174273

175274
pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
176275
tcx: TyCtxt<'tcx>,
177276
def_id: LocalDefId,
178277
sig_id: DefId,
179278
) -> Option<ty::GenericPredicates<'tcx>> {
279+
let args = create_generic_args(tcx, def_id, sig_id);
280+
let builder = PredicatesBuilder::new(tcx, args, sig_id);
281+
282+
let caller_kind = fn_kind(tcx, def_id.into());
283+
let callee_kind = fn_kind(tcx, sig_id);
284+
180285
// FIXME(fn_delegation): Support generics on associated delegation items.
181286
// Error will be reported in `check_constraints`.
182-
if fn_kind(tcx, def_id.into()) != FnKind::Free {
183-
return None;
184-
}
185-
186-
let callee_predicates = tcx.predicates_of(sig_id);
187-
let args = create_generic_args(tcx, def_id, sig_id);
287+
match (caller_kind, callee_kind) {
288+
(FnKind::Free, FnKind::Free)
289+
| (FnKind::Free, FnKind::AssocTrait) => {
290+
Some(builder.build())
291+
}
188292

189-
let mut preds = vec![];
190-
if let Some(parent_id) = callee_predicates.parent {
191-
preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args));
293+
(FnKind::AssocTraitImpl, FnKind::AssocTrait)
294+
| (FnKind::AssocInherentImpl, FnKind::AssocTrait)
295+
| (FnKind::AssocTrait, FnKind::AssocTrait)
296+
| (FnKind::AssocInherentImpl, FnKind::Free)
297+
| (FnKind::AssocTrait, FnKind::Free) => None,
298+
299+
// For trait impl's `sig_id` is always equal to the corresponding trait method.
300+
(FnKind::AssocTraitImpl, _)
301+
| (_, FnKind::AssocTraitImpl)
302+
// Delegation to inherent methods is not yet supported.
303+
| (_, FnKind::AssocInherentImpl) => unreachable!(),
192304
}
193-
preds.extend(callee_predicates.instantiate_own(tcx, args));
194-
195-
Some(ty::GenericPredicates {
196-
parent: None,
197-
predicates: tcx.arena.alloc_from_iter(preds),
198-
effects_min_tys: ty::List::empty(),
199-
})
200305
}
201306

202307
fn check_constraints<'tcx>(

0 commit comments

Comments
 (0)