introduce VerifyBound::IfEq (presently unused)
This commit is contained in:
parent
58fd6fad24
commit
18b86e9406
3 changed files with 111 additions and 26 deletions
|
|
@ -25,11 +25,11 @@ use rustc_data_structures::graph::implementation::{
|
|||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use std::fmt;
|
||||
use std::u32;
|
||||
use ty::{self, TyCtxt};
|
||||
use ty::fold::TypeFoldable;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
|
||||
use ty::{ReLateBound, ReScope, ReSkolemized, ReVar};
|
||||
use ty::{Region, RegionVid};
|
||||
use ty::fold::TypeFoldable;
|
||||
|
||||
mod graphviz;
|
||||
|
||||
|
|
@ -421,7 +421,8 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
|
|||
continue;
|
||||
}
|
||||
|
||||
if self.bound_is_met(&verify.bound, var_data, sub) {
|
||||
let verify_kind_ty = verify.kind.to_ty(self.tcx());
|
||||
if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -713,9 +714,15 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
|
|||
&self,
|
||||
bound: &VerifyBound<'tcx>,
|
||||
var_values: &LexicalRegionResolutions<'tcx>,
|
||||
generic_ty: Ty<'tcx>,
|
||||
min: ty::Region<'tcx>,
|
||||
) -> bool {
|
||||
match bound {
|
||||
VerifyBound::IfEq(k, b) => {
|
||||
(var_values.normalize(self.region_rels.tcx, *k) == generic_ty)
|
||||
&& self.bound_is_met(b, var_values, generic_ty, min)
|
||||
}
|
||||
|
||||
VerifyBound::AnyRegion(rs) => rs.iter()
|
||||
.map(|&r| var_values.normalize(self.tcx(), r))
|
||||
.any(|r| self.region_rels.is_subregion_of(min, r)),
|
||||
|
|
@ -724,9 +731,11 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
|
|||
.map(|&r| var_values.normalize(self.tcx(), r))
|
||||
.all(|r| self.region_rels.is_subregion_of(min, r)),
|
||||
|
||||
VerifyBound::AnyBound(bs) => bs.iter().any(|b| self.bound_is_met(b, var_values, min)),
|
||||
VerifyBound::AnyBound(bs) => bs.iter()
|
||||
.any(|b| self.bound_is_met(b, var_values, generic_ty, min)),
|
||||
|
||||
VerifyBound::AllBounds(bs) => bs.iter().all(|b| self.bound_is_met(b, var_values, min)),
|
||||
VerifyBound::AllBounds(bs) => bs.iter()
|
||||
.all(|b| self.bound_is_met(b, var_values, generic_ty, min)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,29 +155,98 @@ pub enum GenericKind<'tcx> {
|
|||
Projection(ty::ProjectionTy<'tcx>),
|
||||
}
|
||||
|
||||
/// When we introduce a verification step, we wish to test that a
|
||||
/// particular region (let's call it `'min`) meets some bound.
|
||||
/// The bound is described the by the following grammar:
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for GenericKind<'tcx> {
|
||||
(GenericKind::Param)(a),
|
||||
(GenericKind::Projection)(a),
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the things that some `GenericKind` value G is known to
|
||||
/// outlive. Each variant of `VerifyBound` can be thought of as a
|
||||
/// function:
|
||||
///
|
||||
/// fn(min: Region) -> bool { .. }
|
||||
///
|
||||
/// where `true` means that the region `min` meets that `G: min`.
|
||||
/// (False means nothing.)
|
||||
///
|
||||
/// So, for example, if we have the type `T` and we have in scope that
|
||||
/// `T: 'a` and `T: 'b`, then the verify bound might be:
|
||||
///
|
||||
/// fn(min: Region) -> bool {
|
||||
/// ('a: min) || ('b: min)
|
||||
/// }
|
||||
///
|
||||
/// This is described with a `AnyRegion('a, 'b)` node.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum VerifyBound<'tcx> {
|
||||
/// B = exists {R} --> some 'r in {R} must outlive 'min
|
||||
/// Given a kind K and a bound B, expands to a function like the
|
||||
/// following, where `G` is the generic for which this verify
|
||||
/// bound was created:
|
||||
///
|
||||
/// Put another way, the subject value is known to outlive all
|
||||
/// regions in {R}, so if any of those outlives 'min, then the
|
||||
/// bound is met.
|
||||
/// fn(min) -> bool {
|
||||
/// if G == K {
|
||||
/// B(min)
|
||||
/// } else {
|
||||
/// false
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// In other words, if the generic `G` that we are checking is
|
||||
/// equal to `K`, then check the associated verify bound
|
||||
/// (otherwise, false).
|
||||
///
|
||||
/// This is used when we have something in the environment that
|
||||
/// may or may not be relevant, depending on the region inference
|
||||
/// results. For example, we may have `where <T as
|
||||
/// Trait<'a>>::Item: 'b` in our where clauses. If we are
|
||||
/// generating the verify-bound for `<T as Trait<'0>>::Item`, then
|
||||
/// this where-clause is only relevant if `'0` winds up inferred
|
||||
/// to `'a`.
|
||||
///
|
||||
/// So we would compile to a verify-bound like
|
||||
///
|
||||
/// IfEq(<T as Trait<'a>>::Item, AnyRegion('a))
|
||||
///
|
||||
/// meaning, if the subject G is equal to `<T as Trait<'a>>::Item`
|
||||
/// (after inference), and `'a: min`, then `G: min`.
|
||||
IfEq(Ty<'tcx>, Box<VerifyBound<'tcx>>),
|
||||
|
||||
/// Given a set of regions `R`, expands to the function:
|
||||
///
|
||||
/// fn(min) -> bool {
|
||||
/// exists (r in R) { r: min }
|
||||
/// }
|
||||
///
|
||||
/// In other words, if some r in R outlives min, then G outlives
|
||||
/// min. This is used when G is known to outlive all the regions
|
||||
/// in R.
|
||||
AnyRegion(Vec<Region<'tcx>>),
|
||||
|
||||
/// B = forall {R} --> all 'r in {R} must outlive 'min
|
||||
/// Given a set of regions `R`, expands to the function:
|
||||
///
|
||||
/// Put another way, the subject value is known to outlive some
|
||||
/// region in {R}, so if all of those outlives 'min, then the bound
|
||||
/// is met.
|
||||
/// fn(min) -> bool {
|
||||
/// forall (r in R) { r: min }
|
||||
/// }
|
||||
///
|
||||
/// In other words, if all r in R outlives min, then G outlives
|
||||
/// min. This is used when G is known to outlive some region in
|
||||
/// R, but we don't know which.
|
||||
AllRegions(Vec<Region<'tcx>>),
|
||||
|
||||
/// B = exists {B} --> 'min must meet some bound b in {B}
|
||||
/// Given a set of bounds `B`, expands to the function:
|
||||
///
|
||||
/// fn(min) -> bool {
|
||||
/// exists (b in B) { b(min) }
|
||||
/// }
|
||||
AnyBound(Vec<VerifyBound<'tcx>>),
|
||||
|
||||
/// B = forall {B} --> 'min must meet all bounds b in {B}
|
||||
/// Given a set of bounds `B`, expands to the function:
|
||||
///
|
||||
/// fn(min) -> bool {
|
||||
/// forall (b in B) { b(min) }
|
||||
/// }
|
||||
AllBounds(Vec<VerifyBound<'tcx>>),
|
||||
}
|
||||
|
||||
|
|
@ -884,19 +953,21 @@ impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
|
|||
impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
|
||||
pub fn must_hold(&self) -> bool {
|
||||
match self {
|
||||
&VerifyBound::AnyRegion(ref bs) => bs.contains(&&ty::ReStatic),
|
||||
&VerifyBound::AllRegions(ref bs) => bs.is_empty(),
|
||||
&VerifyBound::AnyBound(ref bs) => bs.iter().any(|b| b.must_hold()),
|
||||
&VerifyBound::AllBounds(ref bs) => bs.iter().all(|b| b.must_hold()),
|
||||
VerifyBound::IfEq(..) => false,
|
||||
VerifyBound::AnyRegion(bs) => bs.contains(&&ty::ReStatic),
|
||||
VerifyBound::AllRegions(bs) => bs.is_empty(),
|
||||
VerifyBound::AnyBound(bs) => bs.iter().any(|b| b.must_hold()),
|
||||
VerifyBound::AllBounds(bs) => bs.iter().all(|b| b.must_hold()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cannot_hold(&self) -> bool {
|
||||
match self {
|
||||
&VerifyBound::AnyRegion(ref bs) => bs.is_empty(),
|
||||
&VerifyBound::AllRegions(ref bs) => bs.contains(&&ty::ReEmpty),
|
||||
&VerifyBound::AnyBound(ref bs) => bs.iter().all(|b| b.cannot_hold()),
|
||||
&VerifyBound::AllBounds(ref bs) => bs.iter().any(|b| b.cannot_hold()),
|
||||
VerifyBound::IfEq(_, b) => b.cannot_hold(),
|
||||
VerifyBound::AnyRegion(bs) => bs.is_empty(),
|
||||
VerifyBound::AllRegions(bs) => bs.contains(&&ty::ReEmpty),
|
||||
VerifyBound::AnyBound(bs) => bs.iter().all(|b| b.cannot_hold()),
|
||||
VerifyBound::AllBounds(bs) => bs.iter().any(|b| b.cannot_hold()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,6 +156,11 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn verify_bound_to_region_test(&self, verify_bound: &VerifyBound<'tcx>) -> RegionTest {
|
||||
match verify_bound {
|
||||
VerifyBound::IfEq(..) => {
|
||||
// FIXME: always false right now
|
||||
RegionTest::IsOutlivedByAnyRegionIn(vec![])
|
||||
}
|
||||
|
||||
VerifyBound::AnyRegion(regions) => RegionTest::IsOutlivedByAnyRegionIn(
|
||||
regions.iter().map(|r| self.to_region_vid(r)).collect(),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue