Skip to content

Commit abe0bfa

Browse files
committed
Auto merge of rust-lang#115362 - compiler-errors:non-lifetime-binder-where-clauses, r=<try>
[WIP] Support param bounds on non-lifetime binders 👀 r? `@ghost`
2 parents 8536f20 + 513eeb3 commit abe0bfa

File tree

29 files changed

+577
-147
lines changed

29 files changed

+577
-147
lines changed

compiler/rustc_ast_lowering/src/item.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1753,6 +1753,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
17531753
bounded_ty: self.arena.alloc(bounded_ty),
17541754
bounds,
17551755
bound_generic_params: &[],
1756+
bound_assumptions: &[],
17561757
origin,
17571758
})
17581759
}
@@ -1782,6 +1783,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
17821783
}) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
17831784
bound_generic_params: self
17841785
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
1786+
bound_assumptions: self.arena.alloc_from_iter(
1787+
bound_generic_params.iter().filter_map(|param| {
1788+
self.lower_generic_bound_predicate(
1789+
param.ident,
1790+
param.id,
1791+
&param.kind,
1792+
&param.bounds,
1793+
param.colon_span,
1794+
span,
1795+
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1796+
PredicateOrigin::GenericParam,
1797+
)
1798+
}),
1799+
),
17851800
bounded_ty: self
17861801
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
17871802
bounds: self.lower_param_bounds(

compiler/rustc_ast_lowering/src/lib.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
5555
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
5656
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
5757
use rustc_hir::{
58-
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, TraitCandidate,
58+
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, PredicateOrigin,
59+
TraitCandidate,
5960
};
6061
use rustc_index::{Idx, IndexSlice, IndexVec};
6162
use rustc_macros::extension;
@@ -1734,6 +1735,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17341735

17351736
hir::GenericBound::Trait(hir::PolyTraitRef {
17361737
bound_generic_params: &[],
1738+
bound_assumptions: &[],
17371739
modifiers: hir::TraitBoundModifiers::NONE,
17381740
trait_ref: hir::TraitRef {
17391741
path: self.make_lang_item_path(trait_lang_item, opaque_ty_span, Some(bound_args)),
@@ -1947,12 +1949,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19471949
p: &PolyTraitRef,
19481950
itctx: ImplTraitContext,
19491951
) -> hir::PolyTraitRef<'hir> {
1952+
let bound_assumptions =
1953+
self.arena.alloc_from_iter(p.bound_generic_params.iter().filter_map(|param| {
1954+
self.lower_generic_bound_predicate(
1955+
param.ident,
1956+
param.id,
1957+
&param.kind,
1958+
&param.bounds,
1959+
param.colon_span,
1960+
p.span,
1961+
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1962+
PredicateOrigin::GenericParam,
1963+
)
1964+
}));
19501965
let bound_generic_params =
19511966
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
19521967
let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
19531968
let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
19541969
hir::PolyTraitRef {
19551970
bound_generic_params,
1971+
bound_assumptions,
19561972
modifiers,
19571973
trait_ref,
19581974
span: self.lower_span(p.span),
@@ -2361,6 +2377,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23612377
Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => {
23622378
let principal = hir::PolyTraitRef {
23632379
bound_generic_params: &[],
2380+
bound_assumptions: &[],
23642381
modifiers: hir::TraitBoundModifiers::NONE,
23652382
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
23662383
span: self.lower_span(span),

compiler/rustc_ast_passes/src/feature_gate.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,12 @@ impl<'a> PostExpansionVisitor<'a> {
133133
}
134134
}
135135

136-
for param in params {
137-
if !param.bounds.is_empty() {
138-
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
139-
self.sess.dcx().emit_err(errors::ForbiddenBound { spans });
136+
if !self.features.non_lifetime_binders() {
137+
for param in params {
138+
if !param.bounds.is_empty() {
139+
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
140+
self.sess.dcx().emit_err(errors::ForbiddenBound { spans });
141+
}
140142
}
141143
}
142144
}

compiler/rustc_hir/src/hir.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,8 @@ pub struct WhereBoundPredicate<'hir> {
951951
pub origin: PredicateOrigin,
952952
/// Any generics from a `for` binding.
953953
pub bound_generic_params: &'hir [GenericParam<'hir>],
954+
/// The `'a + Trait` in `for<T: 'a + Trait> ...`
955+
pub bound_assumptions: &'hir [WherePredicate<'hir>],
954956
/// The type being bounded.
955957
pub bounded_ty: &'hir Ty<'hir>,
956958
/// Trait and lifetime bounds (e.g., `Clone + Send + 'static`).
@@ -3793,6 +3795,9 @@ pub struct PolyTraitRef<'hir> {
37933795
/// The `'a` in `for<'a> Foo<&'a T>`.
37943796
pub bound_generic_params: &'hir [GenericParam<'hir>],
37953797

3798+
/// The `'a + Trait` in `for<T: 'a + Trait> ...`
3799+
pub bound_assumptions: &'hir [WherePredicate<'hir>],
3800+
37963801
/// The constness and polarity of the trait ref.
37973802
///
37983803
/// The `async` modifier is lowered directly into a different trait for now.
@@ -4758,7 +4763,7 @@ mod size_asserts {
47584763
static_assert_size!(ForeignItem<'_>, 88);
47594764
static_assert_size!(ForeignItemKind<'_>, 56);
47604765
static_assert_size!(GenericArg<'_>, 16);
4761-
static_assert_size!(GenericBound<'_>, 64);
4766+
static_assert_size!(GenericBound<'_>, 80);
47624767
static_assert_size!(Generics<'_>, 56);
47634768
static_assert_size!(Impl<'_>, 80);
47644769
static_assert_size!(ImplItem<'_>, 88);

compiler/rustc_hir/src/intravisit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1065,10 +1065,12 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
10651065
ref bounded_ty,
10661066
bounds,
10671067
bound_generic_params,
1068+
bound_assumptions,
10681069
origin: _,
10691070
}) => {
10701071
try_visit!(visitor.visit_ty_unambig(bounded_ty));
10711072
walk_list!(visitor, visit_param_bound, bounds);
1073+
walk_list!(visitor, visit_where_predicate, bound_assumptions);
10721074
walk_list!(visitor, visit_generic_param, bound_generic_params);
10731075
}
10741076
WherePredicateKind::RegionPredicate(WhereRegionPredicate {
@@ -1277,6 +1279,7 @@ pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
12771279
trait_ref: &'v PolyTraitRef<'v>,
12781280
) -> V::Result {
12791281
walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
1282+
walk_list!(visitor, visit_where_predicate, trait_ref.bound_assumptions);
12801283
visitor.visit_trait_ref(&trait_ref.trait_ref)
12811284
}
12821285

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,14 @@ fn associated_type_bounds<'tcx>(
3838

3939
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
4040
let mut bounds = Vec::new();
41-
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
41+
icx.lowerer().lower_bounds(
42+
item_ty,
43+
hir_bounds,
44+
&mut bounds,
45+
ty::List::empty(),
46+
ty::ListWithCachedTypeInfo::empty(),
47+
filter,
48+
);
4249
// Associated types are implicitly sized unless a `?Sized` bound is found
4350
match filter {
4451
PredicateFilter::All
@@ -327,7 +334,14 @@ fn opaque_type_bounds<'tcx>(
327334
ty::print::with_reduced_queries!({
328335
let icx = ItemCtxt::new(tcx, opaque_def_id);
329336
let mut bounds = Vec::new();
330-
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
337+
icx.lowerer().lower_bounds(
338+
item_ty,
339+
hir_bounds,
340+
&mut bounds,
341+
ty::List::empty(),
342+
ty::ListWithCachedTypeInfo::empty(),
343+
filter,
344+
);
331345
// Opaque types are implicitly sized unless a `?Sized` bound is found
332346
match filter {
333347
PredicateFilter::All

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+42-102
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ use rustc_middle::ty::{
1010
};
1111
use rustc_middle::{bug, span_bug};
1212
use rustc_span::{DUMMY_SP, Ident, Span};
13-
use tracing::{debug, instrument, trace};
13+
use tracing::{debug, instrument};
1414

1515
use super::item_bounds::explicit_item_bounds_with_filter;
1616
use crate::collect::ItemCtxt;
1717
use crate::constrained_generic_params as cgp;
1818
use crate::delegation::inherit_predicates_for_delegation_item;
19-
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter, RegionInferReason};
19+
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
2020

2121
/// Returns a list of all type predicates (explicit and implicit) for the definition with
2222
/// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus
@@ -183,6 +183,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
183183
self_bounds,
184184
&mut bounds,
185185
ty::List::empty(),
186+
ty::ListWithCachedTypeInfo::empty(),
186187
PredicateFilter::All,
187188
);
188189
predicates.extend(bounds);
@@ -200,105 +201,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
200201
predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id)));
201202
}
202203

203-
// Add implicit predicates that should be treated as if the user has written them,
204-
// including the implicit `T: Sized` for all generic parameters, and `ConstArgHasType`
205-
// for const params.
206-
for param in hir_generics.params {
207-
match param.kind {
208-
GenericParamKind::Lifetime { .. } => (),
209-
GenericParamKind::Type { .. } => {
210-
let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
211-
let mut bounds = Vec::new();
212-
// Params are implicitly sized unless a `?Sized` bound is found
213-
icx.lowerer().add_sized_bound(
214-
&mut bounds,
215-
param_ty,
216-
&[],
217-
Some((param.def_id, hir_generics.predicates)),
218-
param.span,
219-
);
220-
trace!(?bounds);
221-
predicates.extend(bounds);
222-
trace!(?predicates);
223-
}
224-
hir::GenericParamKind::Const { .. } => {
225-
let param_def_id = param.def_id.to_def_id();
226-
let ct_ty = tcx.type_of(param_def_id).instantiate_identity();
227-
let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
228-
predicates
229-
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
230-
}
231-
}
232-
}
233-
234-
trace!(?predicates);
235-
// Add inline `<T: Foo>` bounds and bounds in the where clause.
236-
for predicate in hir_generics.predicates {
237-
match predicate.kind {
238-
hir::WherePredicateKind::BoundPredicate(bound_pred) => {
239-
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
240-
241-
let bound_vars = tcx.late_bound_vars(predicate.hir_id);
242-
// Keep the type around in a dummy predicate, in case of no bounds.
243-
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
244-
// is still checked for WF.
245-
if bound_pred.bounds.is_empty() {
246-
if let ty::Param(_) = ty.kind() {
247-
// This is a `where T:`, which can be in the HIR from the
248-
// transformation that moves `?Sized` to `T`'s declaration.
249-
// We can skip the predicate because type parameters are
250-
// trivially WF, but also we *should*, to avoid exposing
251-
// users who never wrote `where Type:,` themselves, to
252-
// compiler/tooling bugs from not handling WF predicates.
253-
} else {
254-
let span = bound_pred.bounded_ty.span;
255-
let predicate = ty::Binder::bind_with_vars(
256-
ty::ClauseKind::WellFormed(ty.into()),
257-
bound_vars,
258-
);
259-
predicates.insert((predicate.upcast(tcx), span));
260-
}
261-
}
262-
263-
let mut bounds = Vec::new();
264-
icx.lowerer().lower_bounds(
265-
ty,
266-
bound_pred.bounds,
267-
&mut bounds,
268-
bound_vars,
269-
PredicateFilter::All,
270-
);
271-
predicates.extend(bounds);
272-
}
273-
274-
hir::WherePredicateKind::RegionPredicate(region_pred) => {
275-
let r1 = icx
276-
.lowerer()
277-
.lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
278-
predicates.extend(region_pred.bounds.iter().map(|bound| {
279-
let (r2, span) = match bound {
280-
hir::GenericBound::Outlives(lt) => (
281-
icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
282-
lt.ident.span,
283-
),
284-
bound => {
285-
span_bug!(
286-
bound.span(),
287-
"lifetime param bounds must be outlives, but found {bound:?}"
288-
)
289-
}
290-
};
291-
let pred =
292-
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx);
293-
(pred, span)
294-
}))
295-
}
296-
297-
hir::WherePredicateKind::EqPredicate(..) => {
298-
// FIXME(#20041)
299-
}
300-
}
301-
}
204+
icx.lowerer().lower_where_predicates(
205+
hir_generics.params,
206+
hir_generics.predicates,
207+
&mut predicates,
208+
);
302209

303210
if tcx.features().generic_const_exprs() {
304211
predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
@@ -623,7 +530,14 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
623530

624531
let self_param_ty = tcx.types.self_param;
625532
let mut bounds = Vec::new();
626-
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
533+
icx.lowerer().lower_bounds(
534+
self_param_ty,
535+
superbounds,
536+
&mut bounds,
537+
ty::List::empty(),
538+
ty::ListWithCachedTypeInfo::empty(),
539+
filter,
540+
);
627541

628542
let where_bounds_that_match =
629543
icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
@@ -923,12 +837,24 @@ impl<'tcx> ItemCtxt<'tcx> {
923837

924838
let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty);
925839

840+
let mut bound_assumptions = FxIndexSet::default();
841+
if self.tcx.features().non_lifetime_binders() {
842+
self.lowerer().lower_where_predicates(
843+
predicate.bound_generic_params,
844+
predicate.bound_assumptions,
845+
&mut bound_assumptions,
846+
);
847+
}
848+
let bound_assumptions =
849+
self.tcx().mk_clauses_from_iter(bound_assumptions.into_iter().map(|(c, _)| c));
850+
926851
let bound_vars = self.tcx.late_bound_vars(hir_id);
927852
self.lowerer().lower_bounds(
928853
bound_ty,
929854
predicate.bounds,
930855
&mut bounds,
931856
bound_vars,
857+
bound_assumptions,
932858
filter,
933859
);
934860
}
@@ -1002,12 +928,25 @@ pub(super) fn const_conditions<'tcx>(
1002928
match pred.kind {
1003929
hir::WherePredicateKind::BoundPredicate(bound_pred) => {
1004930
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
931+
932+
let mut bound_assumptions = FxIndexSet::default();
933+
if tcx.features().non_lifetime_binders() {
934+
icx.lowerer().lower_where_predicates(
935+
bound_pred.bound_generic_params,
936+
bound_pred.bound_assumptions,
937+
&mut bound_assumptions,
938+
);
939+
}
940+
let bound_assumptions =
941+
icx.tcx().mk_clauses_from_iter(bound_assumptions.into_iter().map(|(c, _)| c));
942+
1005943
let bound_vars = tcx.late_bound_vars(pred.hir_id);
1006944
icx.lowerer().lower_bounds(
1007945
ty,
1008946
bound_pred.bounds.iter(),
1009947
&mut bounds,
1010948
bound_vars,
949+
bound_assumptions,
1011950
PredicateFilter::ConstIfConst,
1012951
);
1013952
}
@@ -1028,6 +967,7 @@ pub(super) fn const_conditions<'tcx>(
1028967
supertraits,
1029968
&mut bounds,
1030969
ty::List::empty(),
970+
ty::ListWithCachedTypeInfo::empty(),
1031971
PredicateFilter::ConstIfConst,
1032972
);
1033973
}

0 commit comments

Comments
 (0)