Skip to content

Commit d201c81

Browse files
committed
Auto merge of #93803 - cjgillot:unify-bounds, r=oli-obk
Handle generic bounds in a uniform way in HIR Generic bounds in HIR used to be split between bounds in the parameter definition and bounds in a where clause. This PR attempts to store all of those as where predicates. This effectively desugars ```rust fn foo<T: Default, U>(x: impl Copy) where U: Clone ``` into ```rust fn foo<T, U, _V>(x: _V) where T: Default, U: Clone, _V: Copy ``` (where _V is actually hidden and called "impl Copy"). I managed to make compiler warnings more uniform. About rustdoc: is making this desugaring user-visible acceptable? About clippy: I don't understand the subtle logic in the `needless-lifetimes` lint. r? `@estebank`
2 parents 76d4862 + b4e3e62 commit d201c81

File tree

120 files changed

+1498
-1462
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+1498
-1462
lines changed

compiler/rustc_ast/src/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ pub struct GenericParam {
397397
pub bounds: GenericBounds,
398398
pub is_placeholder: bool,
399399
pub kind: GenericParamKind,
400+
pub colon_span: Option<Span>,
400401
}
401402

402403
impl GenericParam {

compiler/rustc_ast/src/mut_visit.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -867,9 +867,12 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
867867
mut param: GenericParam,
868868
vis: &mut T,
869869
) -> SmallVec<[GenericParam; 1]> {
870-
let GenericParam { id, ident, attrs, bounds, kind, is_placeholder: _ } = &mut param;
870+
let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param;
871871
vis.visit_id(id);
872872
vis.visit_ident(ident);
873+
if let Some(ref mut colon_span) = colon_span {
874+
vis.visit_span(colon_span);
875+
}
873876
visit_thin_attrs(attrs, vis);
874877
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
875878
match kind {

compiler/rustc_ast_lowering/src/item.rs

+108-28
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,
@@ -410,7 +415,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
410415
ImplPolarity::Positive => ImplPolarity::Positive,
411416
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
412417
};
413-
hir::ItemKind::Impl(hir::Impl {
418+
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
414419
unsafety: self.lower_unsafety(unsafety),
415420
polarity,
416421
defaultness,
@@ -420,7 +425,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
420425
of_trait: trait_ref,
421426
self_ty: lowered_ty,
422427
items: new_impl_items,
423-
})
428+
}))
424429
}
425430
ItemKind::Trait(box Trait {
426431
is_auto,
@@ -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),
@@ -1226,10 +1231,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
12261231
id: NodeId,
12271232
kind: FnDeclKind,
12281233
is_async: Option<NodeId>,
1229-
) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
1234+
) -> (&'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,9 +1343,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
13381343
}
13391344
}
13401345

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(
1352+
generics
1353+
.where_clause
1354+
.predicates
1355+
.iter()
1356+
.map(|predicate| self.lower_where_predicate(predicate)),
1357+
);
1358+
13411359
GenericsCtor {
1342-
params: self.lower_generic_params_mut(&generics.params, itctx).collect(),
1343-
where_clause: self.lower_where_clause(&generics.where_clause),
1360+
params: self.lower_generic_params_mut(&generics.params).collect(),
1361+
predicates,
1362+
has_where_clause: !generics.where_clause.predicates.is_empty(),
1363+
where_clause_span: self.lower_span(generics.where_clause.span),
13441364
span: self.lower_span(generics.span),
13451365
}
13461366
}
@@ -1349,17 +1369,74 @@ impl<'hir> LoweringContext<'_, 'hir> {
13491369
&mut self,
13501370
generics: &Generics,
13511371
itctx: ImplTraitContext<'_, 'hir>,
1352-
) -> hir::Generics<'hir> {
1372+
) -> &'hir hir::Generics<'hir> {
13531373
let generics_ctor = self.lower_generics_mut(generics, itctx);
13541374
generics_ctor.into_generics(self.arena)
13551375
}
13561376

1357-
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause<'hir> {
1358-
hir::WhereClause {
1359-
predicates: self.arena.alloc_from_iter(
1360-
wc.predicates.iter().map(|predicate| self.lower_where_predicate(predicate)),
1361-
),
1362-
span: self.lower_span(wc.span),
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+
}
13631440
}
13641441
}
13651442

@@ -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,16 +1490,20 @@ 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-
where_clause: hir::WhereClause<'hir>,
1493+
pub(super) predicates: SmallVec<[hir::WherePredicate<'hir>; 4]>,
1494+
has_where_clause: bool,
1495+
where_clause_span: Span,
14181496
span: Span,
14191497
}
14201498

14211499
impl<'hir> GenericsCtor<'hir> {
1422-
pub(super) fn into_generics(self, arena: &'hir Arena<'hir>) -> hir::Generics<'hir> {
1423-
hir::Generics {
1500+
pub(super) fn into_generics(self, arena: &'hir Arena<'hir>) -> &'hir hir::Generics<'hir> {
1501+
arena.alloc(hir::Generics {
14241502
params: arena.alloc_from_iter(self.params),
1425-
where_clause: self.where_clause,
1503+
predicates: arena.alloc_from_iter(self.predicates),
1504+
has_where_clause: self.has_where_clause,
1505+
where_clause_span: self.where_clause_span,
14261506
span: self.span,
1427-
}
1507+
})
14281508
}
14291509
}

0 commit comments

Comments
 (0)