Skip to content

Commit 94449e6

Browse files
committed
Store all generic bounds as where predicates.
1 parent 05b29f9 commit 94449e6

File tree

30 files changed

+769
-952
lines changed

30 files changed

+769
-952
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 93 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
267267
this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
268268

269269
let (generics, decl) =
270-
this.add_implicit_generics(generics, id, |this, idty| {
270+
this.add_implicit_generics(generics, id, |this, idty, idpb| {
271271
let ret_id = asyncness.opt_return_id();
272-
this.lower_fn_decl(&decl, Some((id, idty)), FnDeclKind::Fn, ret_id)
272+
this.lower_fn_decl(
273+
&decl,
274+
Some((id, idty, idpb)),
275+
FnDeclKind::Fn,
276+
ret_id,
277+
)
273278
});
274279
let sig = hir::FnSig {
275280
decl,
@@ -384,7 +389,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
384389
// lifetime to be added, but rather a reference to a
385390
// parent lifetime.
386391
let (generics, (trait_ref, lowered_ty)) =
387-
self.add_implicit_generics(ast_generics, id, |this, _| {
392+
self.add_implicit_generics(ast_generics, id, |this, _, _| {
388393
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
389394
this.lower_trait_ref(
390395
trait_ref,
@@ -649,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
649654
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
650655
let fdec = &sig.decl;
651656
let (generics, (fn_dec, fn_args)) =
652-
self.add_implicit_generics(generics, i.id, |this, _| {
657+
self.add_implicit_generics(generics, i.id, |this, _, _| {
653658
(
654659
// Disallow `impl Trait` in foreign items.
655660
this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None),
@@ -1228,8 +1233,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
12281233
is_async: Option<NodeId>,
12291234
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
12301235
let header = self.lower_fn_header(sig.header);
1231-
let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty| {
1232-
this.lower_fn_decl(&sig.decl, Some((id, idty)), kind, is_async)
1236+
let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty, idpb| {
1237+
this.lower_fn_decl(&sig.decl, Some((id, idty, idpb)), kind, is_async)
12331238
});
12341239
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
12351240
}
@@ -1289,7 +1294,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12891294
pub(super) fn lower_generics_mut(
12901295
&mut self,
12911296
generics: &Generics,
1292-
itctx: ImplTraitContext<'_, 'hir>,
1297+
mut itctx: ImplTraitContext<'_, 'hir>,
12931298
) -> GenericsCtor<'hir> {
12941299
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
12951300
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
@@ -1338,7 +1343,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
13381343
}
13391344
}
13401345

1341-
let predicates = self.arena.alloc_from_iter(
1346+
let mut predicates = SmallVec::new();
1347+
predicates.extend(generics.params.iter().filter_map(|param| {
1348+
let bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow());
1349+
self.lower_generic_bound_predicate(param.ident, param.id, &param.kind, bounds)
1350+
}));
1351+
predicates.extend(
13421352
generics
13431353
.where_clause
13441354
.predicates
@@ -1347,8 +1357,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
13471357
);
13481358

13491359
GenericsCtor {
1350-
params: self.lower_generic_params_mut(&generics.params, itctx).collect(),
1360+
params: self.lower_generic_params_mut(&generics.params).collect(),
13511361
predicates,
1362+
has_where_clause: !generics.where_clause.predicates.is_empty(),
13521363
where_clause_span: self.lower_span(generics.where_clause.span),
13531364
span: self.lower_span(generics.span),
13541365
}
@@ -1363,6 +1374,72 @@ impl<'hir> LoweringContext<'_, 'hir> {
13631374
generics_ctor.into_generics(self.arena)
13641375
}
13651376

1377+
pub(super) fn lower_generic_bound_predicate(
1378+
&mut self,
1379+
ident: Ident,
1380+
id: NodeId,
1381+
kind: &GenericParamKind,
1382+
bounds: &'hir [hir::GenericBound<'hir>],
1383+
) -> Option<hir::WherePredicate<'hir>> {
1384+
// Do not create a clause if we do not have anything inside it.
1385+
if bounds.is_empty() {
1386+
return None;
1387+
}
1388+
let ident = self.lower_ident(ident);
1389+
let param_span = ident.span;
1390+
let span = bounds
1391+
.iter()
1392+
.fold(Some(param_span.shrink_to_hi()), |span: Option<Span>, bound| {
1393+
let bound_span = bound.span();
1394+
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
1395+
// as we use this method to get a span appropriate for suggestions.
1396+
if !bound_span.can_be_used_for_suggestions() {
1397+
None
1398+
} else if let Some(span) = span {
1399+
Some(span.to(bound_span))
1400+
} else {
1401+
Some(bound_span)
1402+
}
1403+
})
1404+
.unwrap_or(param_span.shrink_to_hi());
1405+
match kind {
1406+
GenericParamKind::Const { .. } => None,
1407+
GenericParamKind::Type { .. } => {
1408+
let def_id = self.resolver.local_def_id(id).to_def_id();
1409+
let ty_path = self.arena.alloc(hir::Path {
1410+
span: param_span,
1411+
res: Res::Def(DefKind::TyParam, def_id),
1412+
segments: self.arena.alloc_from_iter([hir::PathSegment::from_ident(ident)]),
1413+
});
1414+
let ty_id = self.next_id();
1415+
let bounded_ty =
1416+
self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
1417+
Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1418+
bounded_ty: self.arena.alloc(bounded_ty),
1419+
bounds,
1420+
span,
1421+
bound_generic_params: &[],
1422+
in_where_clause: false,
1423+
}))
1424+
}
1425+
GenericParamKind::Lifetime => {
1426+
let ident_span = self.lower_span(ident.span);
1427+
let ident = self.lower_ident(ident);
1428+
let res = self.resolver.get_lifetime_res(id).unwrap_or_else(|| {
1429+
panic!("Missing resolution for lifetime {:?} at {:?}", id, ident.span)
1430+
});
1431+
let lt_id = self.resolver.next_node_id();
1432+
let lifetime = self.new_named_lifetime_with_res(lt_id, ident_span, ident, res);
1433+
Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
1434+
lifetime,
1435+
span,
1436+
bounds,
1437+
in_where_clause: false,
1438+
}))
1439+
}
1440+
}
1441+
}
1442+
13661443
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
13671444
match *pred {
13681445
WherePredicate::BoundPredicate(WhereBoundPredicate {
@@ -1371,10 +1448,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13711448
ref bounds,
13721449
span,
13731450
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1374-
bound_generic_params: self.lower_generic_params(
1375-
bound_generic_params,
1376-
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1377-
),
1451+
bound_generic_params: self.lower_generic_params(bound_generic_params),
13781452
bounded_ty: self
13791453
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
13801454
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
@@ -1384,6 +1458,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13841458
)
13851459
})),
13861460
span: self.lower_span(span),
1461+
in_where_clause: true,
13871462
}),
13881463
WherePredicate::RegionPredicate(WhereRegionPredicate {
13891464
ref lifetime,
@@ -1396,6 +1471,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13961471
bounds,
13971472
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
13981473
),
1474+
in_where_clause: true,
13991475
}),
14001476
WherePredicate::EqPredicate(WhereEqPredicate { id, ref lhs_ty, ref rhs_ty, span }) => {
14011477
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
@@ -1414,7 +1490,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
14141490
/// Helper struct for delayed construction of Generics.
14151491
pub(super) struct GenericsCtor<'hir> {
14161492
pub(super) params: SmallVec<[hir::GenericParam<'hir>; 4]>,
1417-
predicates: &'hir [hir::WherePredicate<'hir>],
1493+
pub(super) predicates: SmallVec<[hir::WherePredicate<'hir>; 4]>,
1494+
has_where_clause: bool,
14181495
where_clause_span: Span,
14191496
span: Span,
14201497
}
@@ -1423,7 +1500,8 @@ impl<'hir> GenericsCtor<'hir> {
14231500
pub(super) fn into_generics(self, arena: &'hir Arena<'hir>) -> &'hir hir::Generics<'hir> {
14241501
arena.alloc(hir::Generics {
14251502
params: arena.alloc_from_iter(self.params),
1426-
predicates: self.predicates,
1503+
predicates: arena.alloc_from_iter(self.predicates),
1504+
has_where_clause: self.has_where_clause,
14271505
where_clause_span: self.where_clause_span,
14281506
span: self.span,
14291507
})

0 commit comments

Comments
 (0)