Skip to content

Commit 81831e1

Browse files
committed
add WellFormedConst predicate
1 parent cb2308d commit 81831e1

File tree

32 files changed

+296
-61
lines changed

32 files changed

+296
-61
lines changed

src/librustc_infer/infer/outlives/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ pub fn explicit_outlives_bounds<'tcx>(
2020
| ty::PredicateKind::ClosureKind(..)
2121
| ty::PredicateKind::TypeOutlives(..)
2222
| ty::PredicateKind::ConstEvaluatable(..)
23-
| ty::PredicateKind::ConstEquate(..) => None,
23+
| ty::PredicateKind::ConstEquate(..)
24+
| ty::PredicateKind::WellFormedConst(..) => None,
2425
ty::PredicateKind::RegionOutlives(ref data) => data
2526
.no_bound_vars()
2627
.map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),

src/librustc_infer/traits/util.rs

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub fn anonymize_predicate<'tcx>(
4545
}
4646

4747
ty::PredicateKind::ConstEquate(c1, c2) => ty::PredicateKind::ConstEquate(c1, c2),
48+
49+
ty::PredicateKind::WellFormedConst(ct) => ty::PredicateKind::WellFormedConst(ct),
4850
};
4951

5052
if new != *kind { new.to_predicate(tcx) } else { pred }
@@ -204,6 +206,9 @@ impl Elaborator<'tcx> {
204206
// Currently, we do not elaborate const-equate
205207
// predicates.
206208
}
209+
ty::PredicateKind::WellFormedConst(..) => {
210+
// Currently, we do not elaborate WF predicates.
211+
}
207212
ty::PredicateKind::RegionOutlives(..) => {
208213
// Nothing to elaborate from `'a: 'b`.
209214
}

src/librustc_lint/builtin.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
12181218
Projection(..) |
12191219
// Ignore bounds that a user can't type
12201220
WellFormed(..) |
1221+
WellFormedConst(..) |
12211222
ObjectSafe(..) |
12221223
ClosureKind(..) |
12231224
Subtype(..) |

src/librustc_middle/ty/mod.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,9 @@ pub enum PredicateKind<'tcx> {
10791079

10801080
/// Constants must be equal. The first component is the const that is expected.
10811081
ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
1082+
1083+
/// Constant must be well formed.
1084+
WellFormedConst(&'tcx Const<'tcx>),
10821085
}
10831086

10841087
/// The crate outlives map is computed during typeck and contains the
@@ -1195,6 +1198,9 @@ impl<'tcx> Predicate<'tcx> {
11951198
PredicateKind::ConstEquate(c1, c2) => {
11961199
PredicateKind::ConstEquate(c1.subst(tcx, substs), c2.subst(tcx, substs))
11971200
}
1201+
PredicateKind::WellFormedConst(c) => {
1202+
PredicateKind::WellFormedConst(c.subst(tcx, substs))
1203+
}
11981204
};
11991205

12001206
if new != *kind { new.to_predicate(tcx) } else { self }
@@ -1386,7 +1392,8 @@ impl<'tcx> Predicate<'tcx> {
13861392
| PredicateKind::ClosureKind(..)
13871393
| PredicateKind::TypeOutlives(..)
13881394
| PredicateKind::ConstEvaluatable(..)
1389-
| PredicateKind::ConstEquate(..) => None,
1395+
| PredicateKind::ConstEquate(..)
1396+
| PredicateKind::WellFormedConst(..) => None,
13901397
}
13911398
}
13921399

@@ -1401,7 +1408,8 @@ impl<'tcx> Predicate<'tcx> {
14011408
| PredicateKind::ObjectSafe(..)
14021409
| PredicateKind::ClosureKind(..)
14031410
| PredicateKind::ConstEvaluatable(..)
1404-
| PredicateKind::ConstEquate(..) => None,
1411+
| PredicateKind::ConstEquate(..)
1412+
| PredicateKind::WellFormedConst(..) => None,
14051413
}
14061414
}
14071415
}

src/librustc_middle/ty/print/pretty.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2054,6 +2054,9 @@ define_print_and_forward_display! {
20542054
print(c2),
20552055
write("`"))
20562056
}
2057+
ty::PredicateKind::WellFormedConst(c) => {
2058+
p!(print(c), write(" well-formed"))
2059+
}
20572060
}
20582061
}
20592062

src/librustc_middle/ty/structural_impls.rs

+4
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ impl fmt::Debug for ty::PredicateKind<'tcx> {
247247
write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
248248
}
249249
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
250+
ty::PredicateKind::WellFormedConst(c) => write!(f, "WellFormedConst({:?})", c),
250251
}
251252
}
252253
}
@@ -507,6 +508,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
507508
ty::PredicateKind::ConstEquate(c1, c2) => {
508509
tcx.lift(&(c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
509510
}
511+
ty::PredicateKind::WellFormedConst(c) => {
512+
tcx.lift(&c).map(ty::PredicateKind::WellFormedConst)
513+
}
510514
}
511515
}
512516
}

src/librustc_mir/transform/qualify_min_const_fn.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
2929
| ty::PredicateKind::WellFormed(_)
3030
| ty::PredicateKind::Projection(_)
3131
| ty::PredicateKind::ConstEvaluatable(..)
32-
| ty::PredicateKind::ConstEquate(..) => continue,
32+
| ty::PredicateKind::ConstEquate(..)
33+
| ty::PredicateKind::WellFormedConst(..) => continue,
3334
ty::PredicateKind::ObjectSafe(_) => {
3435
bug!("object safe predicate on function: {:#?}", predicate)
3536
}

src/librustc_trait_selection/opaque_types.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,8 @@ crate fn required_region_bounds(
12771277
| ty::PredicateKind::ClosureKind(..)
12781278
| ty::PredicateKind::RegionOutlives(..)
12791279
| ty::PredicateKind::ConstEvaluatable(..)
1280-
| ty::PredicateKind::ConstEquate(..) => None,
1280+
| ty::PredicateKind::ConstEquate(..)
1281+
| ty::PredicateKind::WellFormedConst(..) => None,
12811282
ty::PredicateKind::TypeOutlives(predicate) => {
12821283
// Search for a bound of the form `erased_self_ty
12831284
// : 'a`, but be wary of something like `for<'a>

src/librustc_trait_selection/traits/error_reporting/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
610610
}
611611
}
612612

613+
ty::PredicateKind::WellFormedConst(ct) => {
614+
// Const WF predicates cannot themselves make
615+
// errors. They can only block due to
616+
// ambiguity; otherwise, they always
617+
// degenerate into other obligations
618+
// (which may fail).
619+
span_bug!(span, "const WF predicate not satisfied for {:?}", ct);
620+
}
621+
613622
ty::PredicateKind::ConstEvaluatable(..) => {
614623
// Errors for `ConstEvaluatable` predicates show up as
615624
// `SelectionError::ConstEvalFailure`,
@@ -1540,6 +1549,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
15401549
self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
15411550
}
15421551

1552+
ty::PredicateKind::WellFormedConst(ct) => {
1553+
// Same hacky approach as above to avoid deluging user
1554+
// with error messages.
1555+
if ct.references_error() || self.tcx.sess.has_errors() {
1556+
return;
1557+
}
1558+
self.need_type_info_err_const(body_id, span, ct, ErrorCode::E0282)
1559+
}
1560+
15431561
ty::PredicateKind::Subtype(ref data) => {
15441562
if data.references_error() || self.tcx.sess.has_errors() {
15451563
// no need to overload user in such cases

src/librustc_trait_selection/traits/fulfill.rs

+15
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,21 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
476476
}
477477
}
478478

479+
ty::PredicateKind::WellFormedConst(constant) => match wf::const_obligations(
480+
self.selcx.infcx(),
481+
obligation.param_env,
482+
obligation.cause.body_id,
483+
constant,
484+
obligation.cause.span,
485+
) {
486+
Some(predicates) => ProcessResult::Changed(mk_pending(predicates)),
487+
None => {
488+
pending_obligation.stalled_on =
489+
vec![TyOrConstInferVar::maybe_from_const(constant).unwrap()];
490+
ProcessResult::Unchanged
491+
}
492+
},
493+
479494
&ty::PredicateKind::Subtype(subtype) => {
480495
match self.selcx.infcx().subtype_predicate(
481496
&obligation.cause,

src/librustc_trait_selection/traits/object_safety.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ fn predicates_reference_self(
283283
| ty::PredicateKind::ClosureKind(..)
284284
| ty::PredicateKind::Subtype(..)
285285
| ty::PredicateKind::ConstEvaluatable(..)
286-
| ty::PredicateKind::ConstEquate(..) => None,
286+
| ty::PredicateKind::ConstEquate(..)
287+
| ty::PredicateKind::WellFormedConst(..) => None,
287288
}
288289
})
289290
.collect()
@@ -318,7 +319,8 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
318319
| ty::PredicateKind::ClosureKind(..)
319320
| ty::PredicateKind::TypeOutlives(..)
320321
| ty::PredicateKind::ConstEvaluatable(..)
321-
| ty::PredicateKind::ConstEquate(..) => false,
322+
| ty::PredicateKind::ConstEquate(..)
323+
| ty::PredicateKind::WellFormedConst(..) => false,
322324
}
323325
})
324326
}

src/librustc_trait_selection/traits/select.rs

+14
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
450450
None => Ok(EvaluatedToAmbig),
451451
},
452452

453+
ty::PredicateKind::WellFormedConst(constant) => match wf::const_obligations(
454+
self.infcx,
455+
obligation.param_env,
456+
obligation.cause.body_id,
457+
constant,
458+
obligation.cause.span,
459+
) {
460+
Some(mut obligations) => {
461+
self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
462+
self.evaluate_predicates_recursively(previous_stack, obligations.into_iter())
463+
}
464+
None => Ok(EvaluatedToAmbig),
465+
},
466+
453467
ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::RegionOutlives(..) => {
454468
// We do not consider region relationships when evaluating trait matches.
455469
Ok(EvaluatedToOkModuloRegions)

src/librustc_trait_selection/traits/wf.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,15 @@ pub fn predicate_obligations<'a, 'tcx>(
128128
let obligations = wf.nominal_obligations(def_id, substs);
129129
wf.out.extend(obligations);
130130

131-
for subst in substs.iter().copied() {
131+
for subst in substs.iter() {
132132
wf.compute(subst);
133133
}
134134
}
135-
ty::PredicateKind::ConstEquate(c1, c2) => {
136-
wf.compute(c1.ty.into());
137-
wf.compute(c2.ty.into());
135+
&ty::PredicateKind::ConstEquate(c1, c2) => {
136+
wf.compute(c1.into());
137+
wf.compute(c2.into());
138138
}
139-
ty::Predicate::WellFormedConst(constant) => {
139+
&ty::PredicateKind::WellFormedConst(constant) => {
140140
wf.compute(constant.into());
141141
}
142142
}
@@ -368,7 +368,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
368368
let obligations = self.nominal_obligations(def_id, substs);
369369
self.out.extend(obligations);
370370

371-
let predicate = ty::PredicateKind::ConstEvaluatable(def_id, substs).to_predicate(self.tcx());
371+
let predicate = ty::PredicateKind::ConstEvaluatable(def_id, substs)
372+
.to_predicate(self.tcx());
372373
let cause = self.cause(traits::MiscObligation);
373374
self.out.push(traits::Obligation::new(
374375
cause,
@@ -389,11 +390,20 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
389390
self.out.push(traits::Obligation::new(
390391
cause,
391392
self.param_env,
392-
ty::PredicateKind::WellFormedConst(resolved_constant).to_predicate(self.tcx()),
393+
ty::PredicateKind::WellFormedConst(resolved_constant)
394+
.to_predicate(self.tcx()),
393395
));
394396
}
395397
}
396-
_ => (),
398+
ty::ConstKind::Error
399+
| ty::ConstKind::Param(_)
400+
| ty::ConstKind::Bound(..)
401+
| ty::ConstKind::Placeholder(..) => {
402+
// These variants are trivially WF, so nothing to do here.
403+
}
404+
ty::ConstKind::Value(..) => {
405+
// FIXME: Enforce that values are structually-matchable.
406+
}
397407
}
398408
continue;
399409
}

src/librustc_traits/chalk/lowering.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
7777
) -> chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>> {
7878
let clauses = self.environment.into_iter().filter_map(|clause| match clause {
7979
ChalkEnvironmentClause::Predicate(predicate) => {
80-
match &predicate.kind() {
80+
match predicate.kind() {
8181
ty::PredicateKind::Trait(predicate, _) => {
8282
let (predicate, binders, _named_regions) =
8383
collect_bound_vars(interner, interner.tcx, predicate);
@@ -126,7 +126,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
126126
| ty::PredicateKind::ClosureKind(..)
127127
| ty::PredicateKind::Subtype(..)
128128
| ty::PredicateKind::ConstEvaluatable(..)
129-
| ty::PredicateKind::ConstEquate(..) => {
129+
| ty::PredicateKind::ConstEquate(..)
130+
| ty::PredicateKind::WellFormedConst(..) => {
130131
bug!("unexpected predicate {}", predicate)
131132
}
132133
}
@@ -193,7 +194,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
193194
| ty::PredicateKind::ClosureKind(..)
194195
| ty::PredicateKind::Subtype(..)
195196
| ty::PredicateKind::ConstEvaluatable(..)
196-
| ty::PredicateKind::ConstEquate(..) => {
197+
| ty::PredicateKind::ConstEquate(..)
198+
| ty::PredicateKind::WellFormedConst(..) => {
197199
chalk_ir::GoalData::All(chalk_ir::Goals::new(interner))
198200
}
199201
}
@@ -460,7 +462,8 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
460462
| ty::PredicateKind::ClosureKind(..)
461463
| ty::PredicateKind::Subtype(..)
462464
| ty::PredicateKind::ConstEvaluatable(..)
463-
| ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", &self),
465+
| ty::PredicateKind::ConstEquate(..)
466+
| ty::PredicateKind::WellFormedConst(..) => bug!("unexpected predicate {}", &self),
464467
}
465468
}
466469
}

src/librustc_traits/implied_outlives_bounds.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ fn compute_implied_outlives_bounds<'tcx>(
101101
| ty::PredicateKind::ClosureKind(..)
102102
| ty::PredicateKind::ObjectSafe(..)
103103
| ty::PredicateKind::ConstEvaluatable(..)
104-
| ty::PredicateKind::ConstEquate(..) => vec![],
104+
| ty::PredicateKind::ConstEquate(..)
105+
| ty::PredicateKind::WellFormedConst(..) => vec![],
105106

106107
ty::PredicateKind::WellFormed(subty) => {
107108
wf_types.push(subty);

src/librustc_traits/normalize_erasing_regions.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ fn not_outlives_predicate(p: &ty::Predicate<'_>) -> bool {
4949
| ty::PredicateKind::ClosureKind(..)
5050
| ty::PredicateKind::Subtype(..)
5151
| ty::PredicateKind::ConstEvaluatable(..)
52-
| ty::PredicateKind::ConstEquate(..) => true,
52+
| ty::PredicateKind::ConstEquate(..)
53+
| ty::PredicateKind::WellFormedConst(..) => true,
5354
}
5455
}

src/librustc_typeck/check/method/probe.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
814814
| ty::PredicateKind::ClosureKind(..)
815815
| ty::PredicateKind::TypeOutlives(..)
816816
| ty::PredicateKind::ConstEvaluatable(..)
817-
| ty::PredicateKind::ConstEquate(..) => None,
817+
| ty::PredicateKind::ConstEquate(..)
818+
| ty::PredicateKind::WellFormedConst(..) => None,
818819
});
819820

820821
self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {

0 commit comments

Comments
 (0)