Skip to content

Commit 18b86e9

Browse files
committed
introduce VerifyBound::IfEq (presently unused)
1 parent 58fd6fa commit 18b86e9

File tree

3 files changed

+111
-26
lines changed

3 files changed

+111
-26
lines changed

src/librustc/infer/lexical_region_resolve/mod.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ use rustc_data_structures::graph::implementation::{
2525
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
2626
use std::fmt;
2727
use std::u32;
28-
use ty::{self, TyCtxt};
28+
use ty::fold::TypeFoldable;
29+
use ty::{self, Ty, TyCtxt};
2930
use ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
3031
use ty::{ReLateBound, ReScope, ReSkolemized, ReVar};
3132
use ty::{Region, RegionVid};
32-
use ty::fold::TypeFoldable;
3333

3434
mod graphviz;
3535

@@ -421,7 +421,8 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
421421
continue;
422422
}
423423

424-
if self.bound_is_met(&verify.bound, var_data, sub) {
424+
let verify_kind_ty = verify.kind.to_ty(self.tcx());
425+
if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) {
425426
continue;
426427
}
427428

@@ -713,9 +714,15 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
713714
&self,
714715
bound: &VerifyBound<'tcx>,
715716
var_values: &LexicalRegionResolutions<'tcx>,
717+
generic_ty: Ty<'tcx>,
716718
min: ty::Region<'tcx>,
717719
) -> bool {
718720
match bound {
721+
VerifyBound::IfEq(k, b) => {
722+
(var_values.normalize(self.region_rels.tcx, *k) == generic_ty)
723+
&& self.bound_is_met(b, var_values, generic_ty, min)
724+
}
725+
719726
VerifyBound::AnyRegion(rs) => rs.iter()
720727
.map(|&r| var_values.normalize(self.tcx(), r))
721728
.any(|r| self.region_rels.is_subregion_of(min, r)),
@@ -724,9 +731,11 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
724731
.map(|&r| var_values.normalize(self.tcx(), r))
725732
.all(|r| self.region_rels.is_subregion_of(min, r)),
726733

727-
VerifyBound::AnyBound(bs) => bs.iter().any(|b| self.bound_is_met(b, var_values, min)),
734+
VerifyBound::AnyBound(bs) => bs.iter()
735+
.any(|b| self.bound_is_met(b, var_values, generic_ty, min)),
728736

729-
VerifyBound::AllBounds(bs) => bs.iter().all(|b| self.bound_is_met(b, var_values, min)),
737+
VerifyBound::AllBounds(bs) => bs.iter()
738+
.all(|b| self.bound_is_met(b, var_values, generic_ty, min)),
730739
}
731740
}
732741
}

src/librustc/infer/region_constraints/mod.rs

Lines changed: 92 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -155,29 +155,98 @@ pub enum GenericKind<'tcx> {
155155
Projection(ty::ProjectionTy<'tcx>),
156156
}
157157

158-
/// When we introduce a verification step, we wish to test that a
159-
/// particular region (let's call it `'min`) meets some bound.
160-
/// The bound is described the by the following grammar:
158+
EnumTypeFoldableImpl! {
159+
impl<'tcx> TypeFoldable<'tcx> for GenericKind<'tcx> {
160+
(GenericKind::Param)(a),
161+
(GenericKind::Projection)(a),
162+
}
163+
}
164+
165+
/// Describes the things that some `GenericKind` value G is known to
166+
/// outlive. Each variant of `VerifyBound` can be thought of as a
167+
/// function:
168+
///
169+
/// fn(min: Region) -> bool { .. }
170+
///
171+
/// where `true` means that the region `min` meets that `G: min`.
172+
/// (False means nothing.)
173+
///
174+
/// So, for example, if we have the type `T` and we have in scope that
175+
/// `T: 'a` and `T: 'b`, then the verify bound might be:
176+
///
177+
/// fn(min: Region) -> bool {
178+
/// ('a: min) || ('b: min)
179+
/// }
180+
///
181+
/// This is described with a `AnyRegion('a, 'b)` node.
161182
#[derive(Debug, Clone)]
162183
pub enum VerifyBound<'tcx> {
163-
/// B = exists {R} --> some 'r in {R} must outlive 'min
184+
/// Given a kind K and a bound B, expands to a function like the
185+
/// following, where `G` is the generic for which this verify
186+
/// bound was created:
187+
///
188+
/// fn(min) -> bool {
189+
/// if G == K {
190+
/// B(min)
191+
/// } else {
192+
/// false
193+
/// }
194+
/// }
195+
///
196+
/// In other words, if the generic `G` that we are checking is
197+
/// equal to `K`, then check the associated verify bound
198+
/// (otherwise, false).
199+
///
200+
/// This is used when we have something in the environment that
201+
/// may or may not be relevant, depending on the region inference
202+
/// results. For example, we may have `where <T as
203+
/// Trait<'a>>::Item: 'b` in our where clauses. If we are
204+
/// generating the verify-bound for `<T as Trait<'0>>::Item`, then
205+
/// this where-clause is only relevant if `'0` winds up inferred
206+
/// to `'a`.
207+
///
208+
/// So we would compile to a verify-bound like
164209
///
165-
/// Put another way, the subject value is known to outlive all
166-
/// regions in {R}, so if any of those outlives 'min, then the
167-
/// bound is met.
210+
/// IfEq(<T as Trait<'a>>::Item, AnyRegion('a))
211+
///
212+
/// meaning, if the subject G is equal to `<T as Trait<'a>>::Item`
213+
/// (after inference), and `'a: min`, then `G: min`.
214+
IfEq(Ty<'tcx>, Box<VerifyBound<'tcx>>),
215+
216+
/// Given a set of regions `R`, expands to the function:
217+
///
218+
/// fn(min) -> bool {
219+
/// exists (r in R) { r: min }
220+
/// }
221+
///
222+
/// In other words, if some r in R outlives min, then G outlives
223+
/// min. This is used when G is known to outlive all the regions
224+
/// in R.
168225
AnyRegion(Vec<Region<'tcx>>),
169226

170-
/// B = forall {R} --> all 'r in {R} must outlive 'min
227+
/// Given a set of regions `R`, expands to the function:
171228
///
172-
/// Put another way, the subject value is known to outlive some
173-
/// region in {R}, so if all of those outlives 'min, then the bound
174-
/// is met.
229+
/// fn(min) -> bool {
230+
/// forall (r in R) { r: min }
231+
/// }
232+
///
233+
/// In other words, if all r in R outlives min, then G outlives
234+
/// min. This is used when G is known to outlive some region in
235+
/// R, but we don't know which.
175236
AllRegions(Vec<Region<'tcx>>),
176237

177-
/// B = exists {B} --> 'min must meet some bound b in {B}
238+
/// Given a set of bounds `B`, expands to the function:
239+
///
240+
/// fn(min) -> bool {
241+
/// exists (b in B) { b(min) }
242+
/// }
178243
AnyBound(Vec<VerifyBound<'tcx>>),
179244

180-
/// B = forall {B} --> 'min must meet all bounds b in {B}
245+
/// Given a set of bounds `B`, expands to the function:
246+
///
247+
/// fn(min) -> bool {
248+
/// forall (b in B) { b(min) }
249+
/// }
181250
AllBounds(Vec<VerifyBound<'tcx>>),
182251
}
183252

@@ -884,19 +953,21 @@ impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
884953
impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
885954
pub fn must_hold(&self) -> bool {
886955
match self {
887-
&VerifyBound::AnyRegion(ref bs) => bs.contains(&&ty::ReStatic),
888-
&VerifyBound::AllRegions(ref bs) => bs.is_empty(),
889-
&VerifyBound::AnyBound(ref bs) => bs.iter().any(|b| b.must_hold()),
890-
&VerifyBound::AllBounds(ref bs) => bs.iter().all(|b| b.must_hold()),
956+
VerifyBound::IfEq(..) => false,
957+
VerifyBound::AnyRegion(bs) => bs.contains(&&ty::ReStatic),
958+
VerifyBound::AllRegions(bs) => bs.is_empty(),
959+
VerifyBound::AnyBound(bs) => bs.iter().any(|b| b.must_hold()),
960+
VerifyBound::AllBounds(bs) => bs.iter().all(|b| b.must_hold()),
891961
}
892962
}
893963

894964
pub fn cannot_hold(&self) -> bool {
895965
match self {
896-
&VerifyBound::AnyRegion(ref bs) => bs.is_empty(),
897-
&VerifyBound::AllRegions(ref bs) => bs.contains(&&ty::ReEmpty),
898-
&VerifyBound::AnyBound(ref bs) => bs.iter().all(|b| b.cannot_hold()),
899-
&VerifyBound::AllBounds(ref bs) => bs.iter().any(|b| b.cannot_hold()),
966+
VerifyBound::IfEq(_, b) => b.cannot_hold(),
967+
VerifyBound::AnyRegion(bs) => bs.is_empty(),
968+
VerifyBound::AllRegions(bs) => bs.contains(&&ty::ReEmpty),
969+
VerifyBound::AnyBound(bs) => bs.iter().all(|b| b.cannot_hold()),
970+
VerifyBound::AllBounds(bs) => bs.iter().any(|b| b.cannot_hold()),
900971
}
901972
}
902973

src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
156156

157157
fn verify_bound_to_region_test(&self, verify_bound: &VerifyBound<'tcx>) -> RegionTest {
158158
match verify_bound {
159+
VerifyBound::IfEq(..) => {
160+
// FIXME: always false right now
161+
RegionTest::IsOutlivedByAnyRegionIn(vec![])
162+
}
163+
159164
VerifyBound::AnyRegion(regions) => RegionTest::IsOutlivedByAnyRegionIn(
160165
regions.iter().map(|r| self.to_region_vid(r)).collect(),
161166
),

0 commit comments

Comments
 (0)