Skip to content

Commit d159977

Browse files
committed
Generalize the outlives rule for projections to handle the new cases;
also, generalize VerifyBounds to include OR conditions.
1 parent 75ee8f1 commit d159977

File tree

3 files changed

+541
-101
lines changed

3 files changed

+541
-101
lines changed

src/librustc/middle/infer/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use self::TypeOrigin::*;
1717
pub use self::ValuePairs::*;
1818
pub use middle::ty::IntVarValue;
1919
pub use self::freshen::TypeFreshener;
20-
pub use self::region_inference::GenericKind;
20+
pub use self::region_inference::{GenericKind, VerifyBound};
2121

2222
use middle::free_region::FreeRegionMap;
2323
use middle::mem_categorization as mc;
@@ -1416,13 +1416,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14161416
origin: SubregionOrigin<'tcx>,
14171417
kind: GenericKind<'tcx>,
14181418
a: ty::Region,
1419-
bs: Vec<ty::Region>) {
1419+
bound: VerifyBound) {
14201420
debug!("verify_generic_bound({:?}, {:?} <: {:?})",
14211421
kind,
14221422
a,
1423-
bs);
1423+
bound);
14241424

1425-
self.region_vars.verify_generic_bound(origin, kind, a, bs);
1425+
self.region_vars.verify_generic_bound(origin, kind, a, bound);
14261426
}
14271427

14281428
pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> UnitResult<'tcx>

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

Lines changed: 153 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,41 @@ pub enum Verify<'tcx> {
6464
// outlive `RS`. Therefore verify that `R <= RS[i]` for some
6565
// `i`. Inference variables may be involved (but this verification
6666
// step doesn't influence inference).
67-
VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, Vec<Region>),
67+
VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, VerifyBound),
6868
}
6969

70-
#[derive(Clone, PartialEq, Eq)]
70+
#[derive(Copy, Clone, PartialEq, Eq)]
7171
pub enum GenericKind<'tcx> {
7272
Param(ty::ParamTy),
7373
Projection(ty::ProjectionTy<'tcx>),
7474
}
7575

76+
// When we introduce a verification step, we wish to test that a
77+
// particular region (let's call it `'min`) meets some bound.
78+
// The bound is described the by the following grammar:
79+
#[derive(Debug)]
80+
pub enum VerifyBound {
81+
// B = exists {R} --> some 'r in {R} must outlive 'min
82+
//
83+
// Put another way, the subject value is known to outlive all
84+
// regions in {R}, so if any of those outlives 'min, then the
85+
// bound is met.
86+
AnyRegion(Vec<Region>),
87+
88+
// B = forall {R} --> all 'r in {R} must outlive 'min
89+
//
90+
// Put another way, the subject value is known to outlive some
91+
// region in {R}, so if all of those outlives 'min, then the bound
92+
// is met.
93+
AllRegions(Vec<Region>),
94+
95+
// B = exists {B} --> 'min must meet some bound b in {B}
96+
AnyBound(Vec<VerifyBound>),
97+
98+
// B = forall {B} --> 'min must meet all bounds b in {B}
99+
AllBounds(Vec<VerifyBound>),
100+
}
101+
76102
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
77103
pub struct TwoRegions {
78104
a: Region,
@@ -102,12 +128,11 @@ pub enum RegionResolutionError<'tcx> {
102128
/// `o` requires that `a <= b`, but this does not hold
103129
ConcreteFailure(SubregionOrigin<'tcx>, Region, Region),
104130

105-
/// `GenericBoundFailure(p, s, a, bs)
131+
/// `GenericBoundFailure(p, s, a)
106132
///
107133
/// The parameter/associated-type `p` must be known to outlive the lifetime
108-
/// `a`, but it is only known to outlive `bs` (and none of the
109-
/// regions in `bs` outlive `a`).
110-
GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region, Vec<Region>),
134+
/// `a` (but none of the known bounds are sufficient).
135+
GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region),
111136

112137
/// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`:
113138
///
@@ -408,6 +433,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
408433
debug!("RegionVarBindings: add_verify({:?})",
409434
verify);
410435

436+
// skip no-op cases known to be satisfied
437+
match verify {
438+
VerifyGenericBound(_, _, _, VerifyBound::AllBounds(ref bs)) if bs.len() == 0 => {
439+
return;
440+
}
441+
_ => { }
442+
}
443+
411444
let mut verifys = self.verifys.borrow_mut();
412445
let index = verifys.len();
413446
verifys.push(verify);
@@ -497,8 +530,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
497530
origin: SubregionOrigin<'tcx>,
498531
kind: GenericKind<'tcx>,
499532
sub: Region,
500-
sups: Vec<Region>) {
501-
self.add_verify(VerifyGenericBound(kind, origin, sub, sups));
533+
bound: VerifyBound) {
534+
self.add_verify(VerifyGenericBound(kind, origin, sub, bound));
502535
}
503536

504537
pub fn lub_regions(&self,
@@ -663,12 +696,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
663696
&mut result_set, r,
664697
a, b);
665698
}
666-
VerifyGenericBound(_, _, a, ref bs) => {
667-
for &b in bs {
668-
consider_adding_bidirectional_edges(
669-
&mut result_set, r,
670-
a, b);
671-
}
699+
VerifyGenericBound(_, _, a, ref bound) => {
700+
bound.for_each_region(&mut |b| {
701+
consider_adding_bidirectional_edges(&mut result_set, r,
702+
a, b)
703+
});
672704
}
673705
}
674706
}
@@ -1258,26 +1290,22 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
12581290
continue;
12591291
}
12601292

1261-
debug!("ConcreteFailure: !(sub <= sup): sub={:?}, sup={:?}",
1262-
sub,
1263-
sup);
1293+
debug!("region inference error at {:?}: {:?} <= {:?} is not true",
1294+
origin, sub, sup);
1295+
12641296
errors.push(ConcreteFailure((*origin).clone(), sub, sup));
12651297
}
12661298

1267-
VerifyGenericBound(ref kind, ref origin, sub, ref sups) => {
1299+
VerifyGenericBound(ref kind, ref origin, sub, ref bound) => {
12681300
let sub = normalize(values, sub);
1269-
if sups.iter()
1270-
.map(|&sup| normalize(values, sup))
1271-
.any(|sup| free_regions.is_subregion_of(self.tcx, sub, sup))
1272-
{
1301+
if bound.is_met(self.tcx, free_regions, values, sub) {
12731302
continue;
12741303
}
12751304

1276-
let sups = sups.iter().map(|&sup| normalize(values, sup))
1277-
.collect();
1278-
errors.push(
1279-
GenericBoundFailure(
1280-
(*origin).clone(), kind.clone(), sub, sups));
1305+
debug!("region inference error at {:?}: verifying {:?} <= {:?}",
1306+
origin, sub, bound);
1307+
1308+
errors.push(GenericBoundFailure((*origin).clone(), kind.clone(), sub));
12811309
}
12821310
}
12831311
}
@@ -1438,10 +1466,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
14381466
if !free_regions.is_subregion_of(self.tcx,
14391467
lower_bound.region,
14401468
upper_bound.region) {
1441-
debug!("pushing SubSupConflict sub: {:?} sup: {:?}",
1442-
lower_bound.region, upper_bound.region);
1469+
let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
1470+
debug!("region inference error at {:?} for {:?}: \
1471+
SubSupConflict sub: {:?} sup: {:?}",
1472+
origin, node_idx, lower_bound.region, upper_bound.region);
14431473
errors.push(SubSupConflict(
1444-
(*self.var_origins.borrow())[node_idx.index as usize].clone(),
1474+
origin,
14451475
lower_bound.origin.clone(),
14461476
lower_bound.region,
14471477
upper_bound.origin.clone(),
@@ -1484,16 +1514,20 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
14841514
match self.glb_concrete_regions(free_regions,
14851515
upper_bound_1.region,
14861516
upper_bound_2.region) {
1487-
Ok(_) => {}
1488-
Err(_) => {
1489-
errors.push(SupSupConflict(
1490-
(*self.var_origins.borrow())[node_idx.index as usize].clone(),
1491-
upper_bound_1.origin.clone(),
1492-
upper_bound_1.region,
1493-
upper_bound_2.origin.clone(),
1494-
upper_bound_2.region));
1495-
return;
1496-
}
1517+
Ok(_) => {}
1518+
Err(_) => {
1519+
let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
1520+
debug!("region inference error at {:?} for {:?}: \
1521+
SupSupConflict sub: {:?} sup: {:?}",
1522+
origin, node_idx, upper_bound_1.region, upper_bound_2.region);
1523+
errors.push(SupSupConflict(
1524+
origin,
1525+
upper_bound_1.origin.clone(),
1526+
upper_bound_1.region,
1527+
upper_bound_2.origin.clone(),
1528+
upper_bound_2.region));
1529+
return;
1530+
}
14971531
}
14981532
}
14991533
}
@@ -1676,3 +1710,82 @@ impl<'tcx> GenericKind<'tcx> {
16761710
}
16771711
}
16781712
}
1713+
1714+
impl VerifyBound {
1715+
fn for_each_region(&self, f: &mut FnMut(ty::Region)) {
1716+
match self {
1717+
&VerifyBound::AnyRegion(ref rs) |
1718+
&VerifyBound::AllRegions(ref rs) =>
1719+
for &r in rs { f(r); },
1720+
1721+
&VerifyBound::AnyBound(ref bs) |
1722+
&VerifyBound::AllBounds(ref bs) =>
1723+
for b in bs { b.for_each_region(f); },
1724+
}
1725+
}
1726+
1727+
pub fn must_hold(&self) -> bool {
1728+
match self {
1729+
&VerifyBound::AnyRegion(ref bs) => bs.contains(&ty::ReStatic),
1730+
&VerifyBound::AllRegions(ref bs) => bs.is_empty(),
1731+
&VerifyBound::AnyBound(ref bs) => bs.iter().any(|b| b.must_hold()),
1732+
&VerifyBound::AllBounds(ref bs) => bs.iter().all(|b| b.must_hold()),
1733+
}
1734+
}
1735+
1736+
pub fn cannot_hold(&self) -> bool {
1737+
match self {
1738+
&VerifyBound::AnyRegion(ref bs) => bs.is_empty(),
1739+
&VerifyBound::AllRegions(ref bs) => bs.contains(&ty::ReEmpty),
1740+
&VerifyBound::AnyBound(ref bs) => bs.iter().all(|b| b.cannot_hold()),
1741+
&VerifyBound::AllBounds(ref bs) => bs.iter().any(|b| b.cannot_hold()),
1742+
}
1743+
}
1744+
1745+
pub fn or(self, vb: VerifyBound) -> VerifyBound {
1746+
if self.must_hold() || vb.cannot_hold() {
1747+
self
1748+
} else if self.cannot_hold() || vb.must_hold() {
1749+
vb
1750+
} else {
1751+
VerifyBound::AnyBound(vec![self, vb])
1752+
}
1753+
}
1754+
1755+
pub fn and(self, vb: VerifyBound) -> VerifyBound {
1756+
if self.must_hold() && vb.must_hold() {
1757+
self
1758+
} else if self.cannot_hold() && vb.cannot_hold() {
1759+
self
1760+
} else {
1761+
VerifyBound::AllBounds(vec![self, vb])
1762+
}
1763+
}
1764+
1765+
fn is_met<'tcx>(&self,
1766+
tcx: &ty::ctxt<'tcx>,
1767+
free_regions: &FreeRegionMap,
1768+
var_values: &Vec<VarValue>,
1769+
min: ty::Region)
1770+
-> bool {
1771+
match self {
1772+
&VerifyBound::AnyRegion(ref rs) =>
1773+
rs.iter()
1774+
.map(|&r| normalize(var_values, r))
1775+
.any(|r| free_regions.is_subregion_of(tcx, min, r)),
1776+
1777+
&VerifyBound::AllRegions(ref rs) =>
1778+
rs.iter()
1779+
.map(|&r| normalize(var_values, r))
1780+
.all(|r| free_regions.is_subregion_of(tcx, min, r)),
1781+
1782+
&VerifyBound::AnyBound(ref bs) =>
1783+
bs.iter()
1784+
.any(|b| b.is_met(tcx, free_regions, var_values, min)),
1785+
1786+
&VerifyBound::AllBounds(ref bs) =>
1787+
bs.iter()
1788+
.all(|b| b.is_met(tcx, free_regions, var_values, min)),
1789+
}
1790+
}
1791+
}

0 commit comments

Comments
 (0)