Skip to content

Commit 59885f5

Browse files
committed
Delegation refactoring: add builders for generics inheritance
1 parent fdf61d4 commit 59885f5

3 files changed

Lines changed: 214 additions & 110 deletions

File tree

‎compiler/rustc_hir_analysis/src/delegation.rs‎

Lines changed: 184 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -76,41 +76,153 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
7676
}
7777
}
7878

79+
structGenericsBuilder<'tcx>{
80+
tcx:TyCtxt<'tcx>,
81+
sig_id:DefId,
82+
parent:Option<DefId>,
83+
}
84+
85+
impl<'tcx>GenericsBuilder<'tcx>{
86+
fnnew(tcx:TyCtxt<'tcx>,sig_id:DefId) -> GenericsBuilder<'tcx>{
87+
GenericsBuilder{ tcx, sig_id,parent:None}
88+
}
89+
90+
fnbuild(self) -> ty::Generics{
91+
letmut own_params = vec![];
92+
93+
let sig_generics = self.tcx.generics_of(self.sig_id);
94+
ifletSome(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+
for(idx, param)in own_params.iter_mut().enumerate(){
119+
param.index = idx asu32;
120+
// FIXME(fn_delegation): Default parameters are not inherited, because they are
121+
// not permitted in functions. Therefore, there are 2 options here:
122+
//
123+
// - We can create non-default generic parameters.
124+
// - We can substitute default parameters into the signature.
125+
//
126+
// At the moment, first option has been selected as the most general.
127+
iflet ty::GenericParamDefKind::Type{ has_default, .. }
128+
| ty::GenericParamDefKind::Const{ has_default, .. } = &mut param.kind
129+
{
130+
*has_default = false;
131+
}
132+
}
133+
134+
ty::Generics{
135+
parent:self.parent,
136+
parent_count:0,
137+
own_params,
138+
param_def_id_to_index,
139+
has_self:false,
140+
has_late_bound_regions: sig_generics.has_late_bound_regions,
141+
host_effect_index: sig_generics.host_effect_index,
142+
}
143+
}
144+
}
145+
146+
structPredicatesBuilder<'tcx>{
147+
tcx:TyCtxt<'tcx>,
148+
args: ty::GenericArgsRef<'tcx>,
149+
parent:Option<DefId>,
150+
sig_id:DefId,
151+
}
152+
153+
impl<'tcx>PredicatesBuilder<'tcx>{
154+
fnnew(
155+
tcx:TyCtxt<'tcx>,
156+
args: ty::GenericArgsRef<'tcx>,
157+
sig_id:DefId,
158+
) -> PredicatesBuilder<'tcx>{
159+
PredicatesBuilder{ tcx, args,parent:None, sig_id }
160+
}
161+
162+
fnbuild(self) -> ty::GenericPredicates<'tcx>{
163+
letmut preds = vec![];
164+
165+
let sig_predicates = self.tcx.predicates_of(self.sig_id);
166+
ifletSome(parent) = sig_predicates.parent{
167+
let sig_parent_preds = self.tcx.predicates_of(parent);
168+
preds.extend(sig_parent_preds.instantiate_own(self.tcx,self.args));
169+
}
170+
preds.extend(sig_predicates.instantiate_own(self.tcx,self.args));
171+
172+
ty::GenericPredicates{
173+
parent:self.parent,
174+
predicates:self.tcx.arena.alloc_from_iter(preds),
175+
// FIXME(fn_delegation): Support effects.
176+
effects_min_tys: ty::List::empty(),
177+
}
178+
}
179+
}
180+
181+
structGenericArgsBuilder<'tcx>{
182+
tcx:TyCtxt<'tcx>,
183+
remap_table:RemapTable,
184+
sig_id:DefId,
185+
def_id:LocalDefId,
186+
}
187+
188+
impl<'tcx>GenericArgsBuilder<'tcx>{
189+
fnnew(tcx:TyCtxt<'tcx>,sig_id:DefId,def_id:LocalDefId) -> GenericArgsBuilder<'tcx>{
190+
GenericArgsBuilder{ tcx,remap_table:FxHashMap::default(), sig_id, def_id }
191+
}
192+
193+
fnbuild_from_args(mutself,args: ty::GenericArgsRef<'tcx>) -> ty::GenericArgsRef<'tcx>{
194+
let caller_generics = self.tcx.generics_of(self.def_id);
195+
let callee_generics = self.tcx.generics_of(self.sig_id);
196+
197+
for caller_param in&caller_generics.own_params{
198+
let callee_index =
199+
callee_generics.param_def_id_to_index(self.tcx, caller_param.def_id).unwrap();
200+
self.remap_table.insert(callee_index, caller_param.index);
201+
}
202+
203+
letmut folder = ParamIndexRemapper{tcx:self.tcx,remap_table:self.remap_table};
204+
args.fold_with(&mut folder)
205+
}
206+
}
207+
79208
fncreate_generic_args<'tcx>(
80209
tcx:TyCtxt<'tcx>,
81210
def_id:LocalDefId,
82211
sig_id:DefId,
83212
) -> ty::GenericArgsRef<'tcx>{
84-
let caller_generics = tcx.generics_of(def_id);
85-
let callee_generics = tcx.generics_of(sig_id);
213+
let builder = GenericArgsBuilder::new(tcx, sig_id, def_id);
86214

87215
let caller_kind = fn_kind(tcx, def_id.into());
88216
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`.
217+
91218
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-
letmut 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-
letmut folder = ParamIndexRemapper{ tcx, remap_table };
113-
ty::GenericArgs::identity_for_item(tcx, sig_id).fold_with(&mut folder)
219+
(FnKind::Free,FnKind::Free)
220+
| (FnKind::Free,FnKind::AssocTrait)
221+
| (FnKind::AssocInherentImpl,FnKind::Free)
222+
| (FnKind::AssocTrait,FnKind::Free)
223+
| (FnKind::AssocTrait,FnKind::AssocTrait) => {
224+
let args = ty::GenericArgs::identity_for_item(tcx, sig_id);
225+
builder.build_from_args(args)
114226
}
115227
// FIXME(fn_delegation): Only `Self` param supported here.
116228
(FnKind::AssocTraitImpl,FnKind::AssocTrait)
@@ -120,7 +232,11 @@ fn create_generic_args<'tcx>(
120232
let generic_self_ty = ty::GenericArg::from(self_ty);
121233
tcx.mk_args_from_iter(std::iter::once(generic_self_ty))
122234
}
123-
_ => ty::GenericArgs::identity_for_item(tcx, sig_id),
235+
// For trait impl's `sig_id` is always equal to the corresponding trait method.
236+
(FnKind::AssocTraitImpl, _)
237+
| (_,FnKind::AssocTraitImpl)
238+
// Delegation to inherent methods is not yet supported.
239+
| (_,FnKind::AssocInherentImpl) => unreachable!(),
124240
}
125241
}
126242

@@ -129,74 +245,62 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
129245
def_id:LocalDefId,
130246
sig_id:DefId,
131247
) -> Option<ty::Generics>{
132-
// FIXME(fn_delegation): Support generics on associated delegation items.
133-
// Error will be reported in `check_constraints`.
134-
iffn_kind(tcx, def_id.into()) != FnKind::Free{
135-
returnNone;
136-
}
248+
let builder = GenericsBuilder::new(tcx, sig_id);
137249

138-
letmut own_params = vec![];
139-
140-
let callee_generics = tcx.generics_of(sig_id);
141-
ifletSome(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());
250+
let caller_kind = fn_kind(tcx, def_id.into());
251+
let callee_kind = fn_kind(tcx, sig_id);
146252

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

150-
for(idx, param)in own_params.iter_mut().enumerate(){
151-
param.index = idx asu32;
152-
// Default parameters are not inherited: they are not allowed
153-
// in fn's.
154-
iflet ty::GenericParamDefKind::Type{ has_default, .. }
155-
| ty::GenericParamDefKind::Const{ has_default, .. } = &mut param.kind
156-
{
157-
*has_default = false;
158-
}
259+
(FnKind::AssocTraitImpl,FnKind::AssocTrait)
260+
| (FnKind::AssocInherentImpl,FnKind::AssocTrait)
261+
| (FnKind::AssocTrait,FnKind::AssocTrait)
262+
| (FnKind::AssocInherentImpl,FnKind::Free)
263+
| (FnKind::AssocTrait,FnKind::Free) => None,
264+
265+
// For trait impl's `sig_id` is always equal to the corresponding trait method.
266+
(FnKind::AssocTraitImpl, _)
267+
| (_,FnKind::AssocTraitImpl)
268+
// Delegation to inherent methods is not yet supported.
269+
| (_,FnKind::AssocInherentImpl) => unreachable!(),
159270
}
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-
})
173271
}
174272

175273
pub(crate)fninherit_predicates_for_delegation_item<'tcx>(
176274
tcx:TyCtxt<'tcx>,
177275
def_id:LocalDefId,
178276
sig_id:DefId,
179277
) -> Option<ty::GenericPredicates<'tcx>>{
278+
let args = create_generic_args(tcx, def_id, sig_id);
279+
let builder = PredicatesBuilder::new(tcx, args, sig_id);
280+
281+
let caller_kind = fn_kind(tcx, def_id.into());
282+
let callee_kind = fn_kind(tcx, sig_id);
283+
180284
// FIXME(fn_delegation): Support generics on associated delegation items.
181285
// Error will be reported in `check_constraints`.
182-
iffn_kind(tcx, def_id.into()) != FnKind::Free{
183-
returnNone;
184-
}
185-
186-
let callee_predicates = tcx.predicates_of(sig_id);
187-
let args = create_generic_args(tcx, def_id, sig_id);
286+
match(caller_kind, callee_kind){
287+
(FnKind::Free,FnKind::Free)
288+
| (FnKind::Free,FnKind::AssocTrait) => {
289+
Some(builder.build())
290+
}
188291

189-
letmut preds = vec![];
190-
ifletSome(parent_id) = callee_predicates.parent{
191-
preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args));
292+
(FnKind::AssocTraitImpl,FnKind::AssocTrait)
293+
| (FnKind::AssocInherentImpl,FnKind::AssocTrait)
294+
| (FnKind::AssocTrait,FnKind::AssocTrait)
295+
| (FnKind::AssocInherentImpl,FnKind::Free)
296+
| (FnKind::AssocTrait,FnKind::Free) => None,
297+
298+
// For trait impl's `sig_id` is always equal to the corresponding trait method.
299+
(FnKind::AssocTraitImpl, _)
300+
| (_,FnKind::AssocTraitImpl)
301+
// Delegation to inherent methods is not yet supported.
302+
| (_,FnKind::AssocInherentImpl) => unreachable!(),
192303
}
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-
})
200304
}
201305

202306
fncheck_constraints<'tcx>(

0 commit comments

Comments
 (0)