Skip to content

Commit c2ca1a4

Browse files
committed
Make all predicates higher-ranked, not just trait references.
1 parent 4f34524 commit c2ca1a4

File tree

12 files changed

+336
-133
lines changed

12 files changed

+336
-133
lines changed

src/librustc/metadata/tydecode.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub use self::DefIdSource::*;
2121
use middle::region;
2222
use middle::subst;
2323
use middle::subst::VecPerParamSpace;
24-
use middle::ty::{mod, Ty};
24+
use middle::ty::{mod, AsPredicate, Ty};
2525

2626
use std::rc::Rc;
2727
use std::str;
@@ -669,13 +669,13 @@ pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>,
669669
-> ty::Predicate<'tcx>
670670
{
671671
match next(st) {
672-
't' => ty::Predicate::Trait(Rc::new(ty::Binder(parse_trait_ref(st, conv)))),
673-
'e' => ty::Predicate::Equate(parse_ty(st, |x,y| conv(x,y)),
674-
parse_ty(st, |x,y| conv(x,y))),
675-
'r' => ty::Predicate::RegionOutlives(parse_region(st, |x,y| conv(x,y)),
676-
parse_region(st, |x,y| conv(x,y))),
677-
'o' => ty::Predicate::TypeOutlives(parse_ty(st, |x,y| conv(x,y)),
678-
parse_region(st, |x,y| conv(x,y))),
672+
't' => Rc::new(ty::Binder(parse_trait_ref(st, conv))).as_predicate(),
673+
'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)),
674+
parse_ty(st, |x,y| conv(x,y)))).as_predicate(),
675+
'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)),
676+
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
677+
'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st, |x,y| conv(x,y)),
678+
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
679679
c => panic!("Encountered invalid character in metadata: {}", c)
680680
}
681681
}

src/librustc/metadata/tyencode.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,17 +427,17 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
427427
mywrite!(w, "t");
428428
enc_trait_ref(w, cx, &trait_ref.0);
429429
}
430-
ty::Predicate::Equate(a, b) => {
430+
ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
431431
mywrite!(w, "e");
432432
enc_ty(w, cx, a);
433433
enc_ty(w, cx, b);
434434
}
435-
ty::Predicate::RegionOutlives(a, b) => {
435+
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
436436
mywrite!(w, "r");
437437
enc_region(w, cx, a);
438438
enc_region(w, cx, b);
439439
}
440-
ty::Predicate::TypeOutlives(a, b) => {
440+
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
441441
mywrite!(w, "o");
442442
enc_ty(w, cx, a);
443443
enc_region(w, cx, b);

src/librustc/middle/infer/higher_ranked/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C
8181

8282
// Presuming type comparison succeeds, we need to check
8383
// that the skolemized regions do not "leak".
84-
match self.infcx().leak_check(&skol_map, snapshot) {
84+
match leak_check(self.infcx(), &skol_map, snapshot) {
8585
Ok(()) => { }
8686
Err((skol_br, tainted_region)) => {
8787
if self.a_is_expected() {

src/librustc/middle/infer/mod.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -717,11 +717,40 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
717717
pub fn leak_check(&self,
718718
skol_map: &SkolemizationMap,
719719
snapshot: &CombinedSnapshot)
720-
-> Result<(),(ty::BoundRegion,ty::Region)>
720+
-> ures<'tcx>
721721
{
722722
/*! See `higher_ranked::leak_check` */
723723

724-
higher_ranked::leak_check(self, skol_map, snapshot)
724+
match higher_ranked::leak_check(self, skol_map, snapshot) {
725+
Ok(()) => Ok(()),
726+
Err((br, r)) => Err(ty::terr_regions_insufficiently_polymorphic(br, r))
727+
}
728+
}
729+
730+
pub fn equality_predicate(&self,
731+
span: Span,
732+
predicate: &ty::PolyEquatePredicate<'tcx>)
733+
-> ures<'tcx> {
734+
self.try(|snapshot| {
735+
let (ty::EquatePredicate(a, b), skol_map) =
736+
self.skolemize_late_bound_regions(predicate, snapshot);
737+
let origin = EquatePredicate(span);
738+
let () = try!(mk_eqty(self, false, origin, a, b));
739+
self.leak_check(&skol_map, snapshot)
740+
})
741+
}
742+
743+
pub fn region_outlives_predicate(&self,
744+
span: Span,
745+
predicate: &ty::PolyRegionOutlivesPredicate)
746+
-> ures<'tcx> {
747+
self.try(|snapshot| {
748+
let (ty::OutlivesPredicate(r_a, r_b), skol_map) =
749+
self.skolemize_late_bound_regions(predicate, snapshot);
750+
let origin = RelateRegionParamBound(span);
751+
let () = mk_subr(self, origin, r_b, r_a); // `b : a` ==> `a <= b`
752+
self.leak_check(&skol_map, snapshot)
753+
})
725754
}
726755

727756
pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {

src/librustc/middle/traits/fulfill.rs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use middle::infer::InferCtxt;
1112
use middle::mem_categorization::Typer;
1213
use middle::ty::{mod, Ty};
13-
use middle::infer::{mod, InferCtxt};
1414
use std::collections::HashSet;
1515
use std::collections::hash_map::{Occupied, Vacant};
1616
use std::default::Default;
@@ -329,30 +329,50 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
329329
}
330330
}
331331

332-
ty::Predicate::Equate(a, b) => {
333-
let origin = infer::EquatePredicate(predicate.cause.span);
334-
match infer::mk_eqty(selcx.infcx(), false, origin, a, b) {
335-
Ok(()) => {
336-
true
337-
}
332+
ty::Predicate::Equate(ref binder) => {
333+
match selcx.infcx().equality_predicate(predicate.cause.span, binder) {
334+
Ok(()) => { }
338335
Err(_) => {
339336
errors.push(
340337
FulfillmentError::new(
341338
predicate.clone(),
342339
CodeSelectionError(Unimplemented)));
343-
true
344340
}
345341
}
342+
true
346343
}
347344

348-
ty::Predicate::RegionOutlives(r_a, r_b) => {
349-
let origin = infer::RelateRegionParamBound(predicate.cause.span);
350-
let () = infer::mk_subr(selcx.infcx(), origin, r_b, r_a); // `b : a` ==> `a <= b`
345+
ty::Predicate::RegionOutlives(ref binder) => {
346+
match selcx.infcx().region_outlives_predicate(predicate.cause.span, binder) {
347+
Ok(()) => { }
348+
Err(_) => {
349+
errors.push(
350+
FulfillmentError::new(
351+
predicate.clone(),
352+
CodeSelectionError(Unimplemented)));
353+
}
354+
}
355+
351356
true
352357
}
353358

354-
ty::Predicate::TypeOutlives(t_a, r_b) => {
355-
register_region_obligation(tcx, t_a, r_b, predicate.cause, region_obligations);
359+
ty::Predicate::TypeOutlives(ref binder) => {
360+
// For now, we just check that there are no higher-ranked
361+
// regions. If there are, we will call this obligation an
362+
// error. Eventually we should be able to support some
363+
// cases here, I imagine (e.g., `for<'a> &'a int : 'a`).
364+
//
365+
// TODO This is overly conservative, but good enough for
366+
// now.
367+
if ty::count_late_bound_regions(selcx.tcx(), binder) != 0 {
368+
errors.push(
369+
FulfillmentError::new(
370+
predicate.clone(),
371+
CodeSelectionError(Unimplemented)));
372+
} else {
373+
let ty::OutlivesPredicate(t_a, r_b) = binder.0;
374+
register_region_obligation(tcx, t_a, r_b, predicate.cause, region_obligations);
375+
}
356376
true
357377
}
358378
}
@@ -385,3 +405,4 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
385405
}
386406

387407
}
408+

src/librustc/middle/traits/select.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use super::{util};
2828
use middle::fast_reject;
2929
use middle::mem_categorization::Typer;
3030
use middle::subst::{Subst, Substs, VecPerParamSpace};
31-
use middle::ty::{mod, Ty, RegionEscape};
31+
use middle::ty::{mod, AsPredicate, RegionEscape, Ty};
3232
use middle::infer;
3333
use middle::infer::{InferCtxt, TypeFreshener};
3434
use middle::ty_fold::TypeFoldable;
@@ -288,8 +288,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
288288
self.evaluate_obligation_recursively(previous_stack, &obligation)
289289
}
290290

291-
ty::Predicate::Equate(a, b) => {
292-
match infer::can_mk_eqty(self.infcx, a, b) {
291+
ty::Predicate::Equate(ref p) => {
292+
let result = self.infcx.probe(|| {
293+
self.infcx.equality_predicate(obligation.cause.span, p)
294+
});
295+
match result {
293296
Ok(()) => EvaluatedToOk,
294297
Err(_) => EvaluatedToErr(Unimplemented),
295298
}
@@ -1447,8 +1450,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14471450
obligations.push(Obligation {
14481451
cause: obligation.cause,
14491452
recursion_depth: obligation.recursion_depth+1,
1450-
trait_ref: ty::Predicate::TypeOutlives(obligation.self_ty(),
1451-
ty::ReStatic)
1453+
trait_ref: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(),
1454+
ty::ReStatic)).as_predicate(),
14521455
});
14531456
}
14541457

0 commit comments

Comments
 (0)