Skip to content

Commit 76e8333

Browse files
committed
Auto merge of #73503 - lcnr:forall-predicate-what-and-why-2, r=nikomatsakis
convert higher ranked `Predicate`s to `PredicateKind::ForAll` implements step 2 of rust-lang/compiler-team#285 r? @nikomatsakis
2 parents efc02b0 + 602ef6b commit 76e8333

Some content is hidden

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

61 files changed

+1268
-1150
lines changed

Diff for: src/librustc_infer/infer/canonical/query_response.rs

+20-25
Original file line numberDiff line numberDiff line change
@@ -525,28 +525,25 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
525525
result_subst: &'a CanonicalVarValues<'tcx>,
526526
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> {
527527
unsubstituted_region_constraints.iter().map(move |constraint| {
528-
let constraint = substitute_value(self.tcx, result_subst, constraint);
529-
let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
528+
let ty::OutlivesPredicate(k1, r2) =
529+
substitute_value(self.tcx, result_subst, constraint).skip_binder();
530530

531-
Obligation::new(
532-
cause.clone(),
533-
param_env,
534-
match k1.unpack() {
535-
GenericArgKind::Lifetime(r1) => ty::PredicateKind::RegionOutlives(
536-
ty::Binder::bind(ty::OutlivesPredicate(r1, r2)),
537-
)
538-
.to_predicate(self.tcx),
539-
GenericArgKind::Type(t1) => ty::PredicateKind::TypeOutlives(ty::Binder::bind(
540-
ty::OutlivesPredicate(t1, r2),
541-
))
542-
.to_predicate(self.tcx),
543-
GenericArgKind::Const(..) => {
544-
// Consts cannot outlive one another, so we don't expect to
545-
// ecounter this branch.
546-
span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
547-
}
548-
},
549-
)
531+
let predicate = match k1.unpack() {
532+
GenericArgKind::Lifetime(r1) => {
533+
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r1, r2))
534+
}
535+
GenericArgKind::Type(t1) => {
536+
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(t1, r2))
537+
}
538+
GenericArgKind::Const(..) => {
539+
// Consts cannot outlive one another, so we don't expect to
540+
// encounter this branch.
541+
span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
542+
}
543+
}
544+
.potentially_quantified(self.tcx, ty::PredicateKind::ForAll);
545+
546+
Obligation::new(cause.clone(), param_env, predicate)
550547
})
551548
}
552549

@@ -666,10 +663,8 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
666663
self.obligations.push(Obligation {
667664
cause: self.cause.clone(),
668665
param_env: self.param_env,
669-
predicate: ty::PredicateKind::RegionOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
670-
sup, sub,
671-
)))
672-
.to_predicate(self.infcx.tcx),
666+
predicate: ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(sup, sub))
667+
.to_predicate(self.infcx.tcx),
673668
recursion_depth: 0,
674669
});
675670
}

Diff for: src/librustc_infer/infer/combine.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
308308
self.obligations.push(Obligation::new(
309309
self.trace.cause.clone(),
310310
self.param_env,
311-
ty::PredicateKind::WellFormed(b_ty.into()).to_predicate(self.infcx.tcx),
311+
ty::PredicateAtom::WellFormed(b_ty.into()).to_predicate(self.infcx.tcx),
312312
));
313313
}
314314

@@ -400,9 +400,9 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
400400
b: &'tcx ty::Const<'tcx>,
401401
) {
402402
let predicate = if a_is_expected {
403-
ty::PredicateKind::ConstEquate(a, b)
403+
ty::PredicateAtom::ConstEquate(a, b)
404404
} else {
405-
ty::PredicateKind::ConstEquate(b, a)
405+
ty::PredicateAtom::ConstEquate(b, a)
406406
};
407407
self.obligations.push(Obligation::new(
408408
self.trace.cause.clone(),

Diff for: src/librustc_infer/infer/outlives/mod.rs

+20-14
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,29 @@ pub mod verify;
66

77
use rustc_middle::traits::query::OutlivesBound;
88
use rustc_middle::ty;
9+
use rustc_middle::ty::fold::TypeFoldable;
910

1011
pub fn explicit_outlives_bounds<'tcx>(
1112
param_env: ty::ParamEnv<'tcx>,
1213
) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
1314
debug!("explicit_outlives_bounds()");
14-
param_env.caller_bounds().into_iter().filter_map(move |predicate| match predicate.kind() {
15-
ty::PredicateKind::Projection(..)
16-
| ty::PredicateKind::Trait(..)
17-
| ty::PredicateKind::Subtype(..)
18-
| ty::PredicateKind::WellFormed(..)
19-
| ty::PredicateKind::ObjectSafe(..)
20-
| ty::PredicateKind::ClosureKind(..)
21-
| ty::PredicateKind::TypeOutlives(..)
22-
| ty::PredicateKind::ConstEvaluatable(..)
23-
| ty::PredicateKind::ConstEquate(..) => None,
24-
ty::PredicateKind::RegionOutlives(ref data) => data
25-
.no_bound_vars()
26-
.map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
27-
})
15+
param_env
16+
.caller_bounds()
17+
.into_iter()
18+
.map(ty::Predicate::skip_binders)
19+
.filter(|atom| !atom.has_escaping_bound_vars())
20+
.filter_map(move |atom| match atom {
21+
ty::PredicateAtom::Projection(..)
22+
| ty::PredicateAtom::Trait(..)
23+
| ty::PredicateAtom::Subtype(..)
24+
| ty::PredicateAtom::WellFormed(..)
25+
| ty::PredicateAtom::ObjectSafe(..)
26+
| ty::PredicateAtom::ClosureKind(..)
27+
| ty::PredicateAtom::TypeOutlives(..)
28+
| ty::PredicateAtom::ConstEvaluatable(..)
29+
| ty::PredicateAtom::ConstEquate(..) => None,
30+
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
31+
Some(OutlivesBound::RegionSubRegion(r_b, r_a))
32+
}
33+
})
2834
}

Diff for: src/librustc_infer/infer/sub.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,11 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
100100
self.fields.obligations.push(Obligation::new(
101101
self.fields.trace.cause.clone(),
102102
self.fields.param_env,
103-
ty::PredicateKind::Subtype(ty::Binder::dummy(ty::SubtypePredicate {
103+
ty::PredicateAtom::Subtype(ty::SubtypePredicate {
104104
a_is_expected: self.a_is_expected,
105105
a,
106106
b,
107-
}))
107+
})
108108
.to_predicate(self.tcx()),
109109
));
110110

Diff for: src/librustc_infer/traits/util.rs

+28-60
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,20 @@ use smallvec::smallvec;
33
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_middle::ty::outlives::Component;
6-
use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, TyCtxt, WithConstness};
6+
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
77
use rustc_span::Span;
88

99
pub fn anonymize_predicate<'tcx>(
1010
tcx: TyCtxt<'tcx>,
1111
pred: ty::Predicate<'tcx>,
1212
) -> ty::Predicate<'tcx> {
13-
let kind = pred.kind();
14-
let new = match kind {
15-
&ty::PredicateKind::Trait(ref data, constness) => {
16-
ty::PredicateKind::Trait(tcx.anonymize_late_bound_regions(data), constness)
13+
match pred.kind() {
14+
ty::PredicateKind::ForAll(binder) => {
15+
let new = ty::PredicateKind::ForAll(tcx.anonymize_late_bound_regions(binder));
16+
tcx.reuse_or_mk_predicate(pred, new)
1717
}
18-
19-
ty::PredicateKind::RegionOutlives(data) => {
20-
ty::PredicateKind::RegionOutlives(tcx.anonymize_late_bound_regions(data))
21-
}
22-
23-
ty::PredicateKind::TypeOutlives(data) => {
24-
ty::PredicateKind::TypeOutlives(tcx.anonymize_late_bound_regions(data))
25-
}
26-
27-
ty::PredicateKind::Projection(data) => {
28-
ty::PredicateKind::Projection(tcx.anonymize_late_bound_regions(data))
29-
}
30-
31-
&ty::PredicateKind::WellFormed(data) => ty::PredicateKind::WellFormed(data),
32-
33-
&ty::PredicateKind::ObjectSafe(data) => ty::PredicateKind::ObjectSafe(data),
34-
35-
&ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
36-
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind)
37-
}
38-
39-
ty::PredicateKind::Subtype(data) => {
40-
ty::PredicateKind::Subtype(tcx.anonymize_late_bound_regions(data))
41-
}
42-
43-
&ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
44-
ty::PredicateKind::ConstEvaluatable(def_id, substs)
45-
}
46-
47-
ty::PredicateKind::ConstEquate(c1, c2) => ty::PredicateKind::ConstEquate(c1, c2),
48-
};
49-
50-
if new != *kind { new.to_predicate(tcx) } else { pred }
18+
ty::PredicateKind::Atom(_) => pred,
19+
}
5120
}
5221

5322
struct PredicateSet<'tcx> {
@@ -158,15 +127,16 @@ impl Elaborator<'tcx> {
158127

159128
fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
160129
let tcx = self.visited.tcx;
161-
match obligation.predicate.kind() {
162-
ty::PredicateKind::Trait(ref data, _) => {
130+
131+
match obligation.predicate.skip_binders() {
132+
ty::PredicateAtom::Trait(data, _) => {
163133
// Get predicates declared on the trait.
164134
let predicates = tcx.super_predicates_of(data.def_id());
165135

166-
let obligations = predicates.predicates.iter().map(|(pred, span)| {
136+
let obligations = predicates.predicates.iter().map(|&(pred, span)| {
167137
predicate_obligation(
168-
pred.subst_supertrait(tcx, &data.to_poly_trait_ref()),
169-
Some(*span),
138+
pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)),
139+
Some(span),
170140
)
171141
});
172142
debug!("super_predicates: data={:?}", data);
@@ -180,36 +150,36 @@ impl Elaborator<'tcx> {
180150

181151
self.stack.extend(obligations);
182152
}
183-
ty::PredicateKind::WellFormed(..) => {
153+
ty::PredicateAtom::WellFormed(..) => {
184154
// Currently, we do not elaborate WF predicates,
185155
// although we easily could.
186156
}
187-
ty::PredicateKind::ObjectSafe(..) => {
157+
ty::PredicateAtom::ObjectSafe(..) => {
188158
// Currently, we do not elaborate object-safe
189159
// predicates.
190160
}
191-
ty::PredicateKind::Subtype(..) => {
161+
ty::PredicateAtom::Subtype(..) => {
192162
// Currently, we do not "elaborate" predicates like `X <: Y`,
193163
// though conceivably we might.
194164
}
195-
ty::PredicateKind::Projection(..) => {
165+
ty::PredicateAtom::Projection(..) => {
196166
// Nothing to elaborate in a projection predicate.
197167
}
198-
ty::PredicateKind::ClosureKind(..) => {
168+
ty::PredicateAtom::ClosureKind(..) => {
199169
// Nothing to elaborate when waiting for a closure's kind to be inferred.
200170
}
201-
ty::PredicateKind::ConstEvaluatable(..) => {
171+
ty::PredicateAtom::ConstEvaluatable(..) => {
202172
// Currently, we do not elaborate const-evaluatable
203173
// predicates.
204174
}
205-
ty::PredicateKind::ConstEquate(..) => {
175+
ty::PredicateAtom::ConstEquate(..) => {
206176
// Currently, we do not elaborate const-equate
207177
// predicates.
208178
}
209-
ty::PredicateKind::RegionOutlives(..) => {
179+
ty::PredicateAtom::RegionOutlives(..) => {
210180
// Nothing to elaborate from `'a: 'b`.
211181
}
212-
ty::PredicateKind::TypeOutlives(ref data) => {
182+
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
213183
// We know that `T: 'a` for some type `T`. We can
214184
// often elaborate this. For example, if we know that
215185
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
@@ -224,8 +194,6 @@ impl Elaborator<'tcx> {
224194
// consider this as evidence that `T: 'static`, but
225195
// I'm a bit wary of such constructions and so for now
226196
// I want to be conservative. --nmatsakis
227-
let ty_max = data.skip_binder().0;
228-
let r_min = data.skip_binder().1;
229197
if r_min.is_late_bound() {
230198
return;
231199
}
@@ -241,16 +209,16 @@ impl Elaborator<'tcx> {
241209
if r.is_late_bound() {
242210
None
243211
} else {
244-
Some(ty::PredicateKind::RegionOutlives(ty::Binder::dummy(
245-
ty::OutlivesPredicate(r, r_min),
212+
Some(ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
213+
r, r_min,
246214
)))
247215
}
248216
}
249217

250218
Component::Param(p) => {
251219
let ty = tcx.mk_ty_param(p.index, p.name);
252-
Some(ty::PredicateKind::TypeOutlives(ty::Binder::dummy(
253-
ty::OutlivesPredicate(ty, r_min),
220+
Some(ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(
221+
ty, r_min,
254222
)))
255223
}
256224

@@ -331,8 +299,8 @@ impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToT
331299

332300
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
333301
while let Some(obligation) = self.base_iterator.next() {
334-
if let ty::PredicateKind::Trait(data, _) = obligation.predicate.kind() {
335-
return Some(data.to_poly_trait_ref());
302+
if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() {
303+
return Some(data);
336304
}
337305
}
338306
None

Diff for: src/librustc_lint/builtin.rs

+10-14
Original file line numberDiff line numberDiff line change
@@ -1202,13 +1202,13 @@ declare_lint_pass!(
12021202
impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
12031203
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
12041204
use rustc_middle::ty::fold::TypeFoldable;
1205-
use rustc_middle::ty::PredicateKind::*;
1205+
use rustc_middle::ty::PredicateAtom::*;
12061206

12071207
if cx.tcx.features().trivial_bounds {
12081208
let def_id = cx.tcx.hir().local_def_id(item.hir_id);
12091209
let predicates = cx.tcx.predicates_of(def_id);
12101210
for &(predicate, span) in predicates.predicates {
1211-
let predicate_kind_name = match predicate.kind() {
1211+
let predicate_kind_name = match predicate.skip_binders() {
12121212
Trait(..) => "Trait",
12131213
TypeOutlives(..) |
12141214
RegionOutlives(..) => "Lifetime",
@@ -1497,14 +1497,11 @@ impl ExplicitOutlivesRequirements {
14971497
) -> Vec<ty::Region<'tcx>> {
14981498
inferred_outlives
14991499
.iter()
1500-
.filter_map(|(pred, _)| match pred.kind() {
1501-
ty::PredicateKind::RegionOutlives(outlives) => {
1502-
let outlives = outlives.skip_binder();
1503-
match outlives.0 {
1504-
ty::ReEarlyBound(ebr) if ebr.index == index => Some(outlives.1),
1505-
_ => None,
1506-
}
1507-
}
1500+
.filter_map(|(pred, _)| match pred.skip_binders() {
1501+
ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(a, b)) => match a {
1502+
ty::ReEarlyBound(ebr) if ebr.index == index => Some(b),
1503+
_ => None,
1504+
},
15081505
_ => None,
15091506
})
15101507
.collect()
@@ -1516,10 +1513,9 @@ impl ExplicitOutlivesRequirements {
15161513
) -> Vec<ty::Region<'tcx>> {
15171514
inferred_outlives
15181515
.iter()
1519-
.filter_map(|(pred, _)| match pred.kind() {
1520-
ty::PredicateKind::TypeOutlives(outlives) => {
1521-
let outlives = outlives.skip_binder();
1522-
outlives.0.is_param(index).then_some(outlives.1)
1516+
.filter_map(|(pred, _)| match pred.skip_binders() {
1517+
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
1518+
a.is_param(index).then_some(b)
15231519
}
15241520
_ => None,
15251521
})

Diff for: src/librustc_lint/unused.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
146146
ty::Opaque(def, _) => {
147147
let mut has_emitted = false;
148148
for (predicate, _) in cx.tcx.predicates_of(def).predicates {
149-
if let ty::PredicateKind::Trait(ref poly_trait_predicate, _) =
150-
predicate.kind()
149+
// We only look at the `DefId`, so it is safe to skip the binder here.
150+
if let ty::PredicateAtom::Trait(ref poly_trait_predicate, _) =
151+
predicate.skip_binders()
151152
{
152-
let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
153-
let def_id = trait_ref.def_id;
153+
let def_id = poly_trait_predicate.trait_ref.def_id;
154154
let descr_pre =
155155
&format!("{}implementer{} of ", descr_pre, plural_suffix,);
156156
if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {

0 commit comments

Comments
 (0)