move free_regions_map
into infer::outlives
This commit is contained in:
parent
aa51603870
commit
abd7d88139
@ -18,7 +18,7 @@ pub use ty::IntVarValue;
|
||||
pub use self::freshen::TypeFreshener;
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use middle::free_region::{FreeRegionMap, RegionRelations};
|
||||
use middle::free_region::RegionRelations;
|
||||
use middle::region;
|
||||
use middle::lang_items;
|
||||
use mir::tcx::PlaceTy;
|
||||
@ -44,6 +44,7 @@ use self::higher_ranked::HrMatchResult;
|
||||
use self::region_constraints::{RegionConstraintCollector, RegionSnapshot};
|
||||
use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarOrigins};
|
||||
use self::lexical_region_resolve::LexicalRegionResolutions;
|
||||
use self::outlives::free_region_map::FreeRegionMap;
|
||||
use self::type_variable::TypeVariableOrigin;
|
||||
use self::unify_key::ToType;
|
||||
|
||||
@ -58,7 +59,7 @@ pub mod lattice;
|
||||
mod lub;
|
||||
pub mod region_constraints;
|
||||
mod lexical_region_resolve;
|
||||
mod outlives;
|
||||
pub mod outlives;
|
||||
pub mod resolve;
|
||||
mod freshen;
|
||||
mod sub;
|
||||
|
@ -8,8 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use infer::{InferCtxt, GenericKind};
|
||||
use infer::outlives::free_region_map::FreeRegionMap;
|
||||
use infer::outlives::implied_bounds::ImpliedBound;
|
||||
use ty::{self, Ty};
|
||||
|
||||
|
138
src/librustc/infer/outlives/free_region_map.rs
Normal file
138
src/librustc/infer/outlives/free_region_map.rs
Normal file
@ -0,0 +1,138 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ty::{self, Lift, TyCtxt, Region};
|
||||
use rustc_data_structures::transitive_relation::TransitiveRelation;
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct FreeRegionMap<'tcx> {
|
||||
// Stores the relation `a < b`, where `a` and `b` are regions.
|
||||
//
|
||||
// Invariant: only free regions like `'x` or `'static` are stored
|
||||
// in this relation, not scopes.
|
||||
relation: TransitiveRelation<Region<'tcx>>
|
||||
}
|
||||
|
||||
impl<'tcx> FreeRegionMap<'tcx> {
|
||||
pub fn new() -> Self {
|
||||
FreeRegionMap { relation: TransitiveRelation::new() }
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.relation.is_empty()
|
||||
}
|
||||
|
||||
pub fn relate_free_regions_from_predicates(&mut self,
|
||||
predicates: &[ty::Predicate<'tcx>]) {
|
||||
debug!("relate_free_regions_from_predicates(predicates={:?})", predicates);
|
||||
for predicate in predicates {
|
||||
match *predicate {
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
ty::Predicate::ConstEvaluatable(..) => {
|
||||
// No region bounds here
|
||||
}
|
||||
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
|
||||
self.relate_regions(r_b, r_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
|
||||
/// (with the exception that `'static: 'x` is not notable)
|
||||
pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
|
||||
debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
|
||||
if is_free_or_static(sub) && is_free(sup) {
|
||||
self.relation.add(sub, sup)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether `r_a <= sup`. Both must be free regions or
|
||||
/// `'static`.
|
||||
pub fn sub_free_regions<'a, 'gcx>(&self,
|
||||
r_a: Region<'tcx>,
|
||||
r_b: Region<'tcx>)
|
||||
-> bool {
|
||||
assert!(is_free_or_static(r_a) && is_free_or_static(r_b));
|
||||
if let ty::ReStatic = r_b {
|
||||
true // `'a <= 'static` is just always true, and not stored in the relation explicitly
|
||||
} else {
|
||||
r_a == r_b || self.relation.contains(&r_a, &r_b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the least-upper-bound of two free regions. In some
|
||||
/// cases, this is more conservative than necessary, in order to
|
||||
/// avoid making arbitrary choices. See
|
||||
/// `TransitiveRelation::postdom_upper_bound` for more details.
|
||||
pub fn lub_free_regions<'a, 'gcx>(&self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
r_a: Region<'tcx>,
|
||||
r_b: Region<'tcx>)
|
||||
-> Region<'tcx> {
|
||||
debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b);
|
||||
assert!(is_free(r_a));
|
||||
assert!(is_free(r_b));
|
||||
let result = if r_a == r_b { r_a } else {
|
||||
match self.relation.postdom_upper_bound(&r_a, &r_b) {
|
||||
None => tcx.mk_region(ty::ReStatic),
|
||||
Some(r) => *r,
|
||||
}
|
||||
};
|
||||
debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
|
||||
result
|
||||
}
|
||||
|
||||
/// Returns all regions that are known to outlive `r_a`. For
|
||||
/// example, in a function:
|
||||
///
|
||||
/// ```
|
||||
/// fn foo<'a, 'b: 'a, 'c: 'b>() { .. }
|
||||
/// ```
|
||||
///
|
||||
/// if `r_a` represents `'a`, this function would return `{'b, 'c}`.
|
||||
pub fn regions_that_outlive<'a, 'gcx>(&self, r_a: Region<'tcx>) -> Vec<&Region<'tcx>> {
|
||||
assert!(is_free(r_a) || *r_a == ty::ReStatic);
|
||||
self.relation.greater_than(&r_a)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_free(r: Region) -> bool {
|
||||
match *r {
|
||||
ty::ReEarlyBound(_) | ty::ReFree(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_free_or_static(r: Region) -> bool {
|
||||
match *r {
|
||||
ty::ReStatic => true,
|
||||
_ => is_free(r),
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
|
||||
relation
|
||||
});
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> {
|
||||
type Lifted = FreeRegionMap<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<FreeRegionMap<'tcx>> {
|
||||
self.relation.maybe_map(|&fr| fr.lift_to_tcx(tcx))
|
||||
.map(|relation| FreeRegionMap { relation })
|
||||
}
|
||||
}
|
@ -11,5 +11,6 @@
|
||||
//! Various code related to computing outlives relations.
|
||||
|
||||
pub mod env;
|
||||
pub mod free_region_map;
|
||||
pub mod implied_bounds;
|
||||
mod obligations;
|
||||
|
@ -15,10 +15,10 @@
|
||||
//! `TransitiveRelation` type and use that to decide when one free
|
||||
//! region outlives another and so forth.
|
||||
|
||||
use infer::outlives::free_region_map::FreeRegionMap;
|
||||
use hir::def_id::DefId;
|
||||
use middle::region;
|
||||
use ty::{self, Lift, TyCtxt, Region};
|
||||
use rustc_data_structures::transitive_relation::TransitiveRelation;
|
||||
use ty::{self, TyCtxt, Region};
|
||||
|
||||
/// Combines a `region::ScopeTree` (which governs relationships between
|
||||
/// scopes) and a `FreeRegionMap` (which governs relationships between
|
||||
@ -103,7 +103,7 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> {
|
||||
ty::ReStatic => true,
|
||||
ty::ReEarlyBound(_) | ty::ReFree(_) => {
|
||||
let re_static = self.tcx.mk_region(ty::ReStatic);
|
||||
self.free_regions.relation.contains(&re_static, &super_region)
|
||||
self.free_regions.sub_free_regions(&re_static, &super_region)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
@ -117,128 +117,3 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct FreeRegionMap<'tcx> {
|
||||
// Stores the relation `a < b`, where `a` and `b` are regions.
|
||||
//
|
||||
// Invariant: only free regions like `'x` or `'static` are stored
|
||||
// in this relation, not scopes.
|
||||
relation: TransitiveRelation<Region<'tcx>>
|
||||
}
|
||||
|
||||
impl<'tcx> FreeRegionMap<'tcx> {
|
||||
pub fn new() -> Self {
|
||||
FreeRegionMap { relation: TransitiveRelation::new() }
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.relation.is_empty()
|
||||
}
|
||||
|
||||
pub fn relate_free_regions_from_predicates(&mut self,
|
||||
predicates: &[ty::Predicate<'tcx>]) {
|
||||
debug!("relate_free_regions_from_predicates(predicates={:?})", predicates);
|
||||
for predicate in predicates {
|
||||
match *predicate {
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
ty::Predicate::ConstEvaluatable(..) => {
|
||||
// No region bounds here
|
||||
}
|
||||
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
|
||||
self.relate_regions(r_b, r_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
|
||||
/// (with the exception that `'static: 'x` is not notable)
|
||||
pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
|
||||
debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
|
||||
if is_free_or_static(sub) && is_free(sup) {
|
||||
self.relation.add(sub, sup)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether `r_a <= sup`. Both must be free regions or
|
||||
/// `'static`.
|
||||
pub fn sub_free_regions<'a, 'gcx>(&self,
|
||||
r_a: Region<'tcx>,
|
||||
r_b: Region<'tcx>)
|
||||
-> bool {
|
||||
assert!(is_free_or_static(r_a) && is_free_or_static(r_b));
|
||||
if let ty::ReStatic = r_b {
|
||||
true // `'a <= 'static` is just always true, and not stored in the relation explicitly
|
||||
} else {
|
||||
r_a == r_b || self.relation.contains(&r_a, &r_b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the least-upper-bound of two free regions. In some
|
||||
/// cases, this is more conservative than necessary, in order to
|
||||
/// avoid making arbitrary choices. See
|
||||
/// `TransitiveRelation::postdom_upper_bound` for more details.
|
||||
pub fn lub_free_regions<'a, 'gcx>(&self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
r_a: Region<'tcx>,
|
||||
r_b: Region<'tcx>)
|
||||
-> Region<'tcx> {
|
||||
debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b);
|
||||
assert!(is_free(r_a));
|
||||
assert!(is_free(r_b));
|
||||
let result = if r_a == r_b { r_a } else {
|
||||
match self.relation.postdom_upper_bound(&r_a, &r_b) {
|
||||
None => tcx.mk_region(ty::ReStatic),
|
||||
Some(r) => *r,
|
||||
}
|
||||
};
|
||||
debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
|
||||
result
|
||||
}
|
||||
|
||||
/// Returns all regions that are known to outlive `r_a`. For
|
||||
/// example, in a function:
|
||||
///
|
||||
/// ```
|
||||
/// fn foo<'a, 'b: 'a, 'c: 'b>() { .. }
|
||||
/// ```
|
||||
///
|
||||
/// if `r_a` represents `'a`, this function would return `{'b, 'c}`.
|
||||
pub fn regions_that_outlive<'a, 'gcx>(&self, r_a: Region<'tcx>) -> Vec<&Region<'tcx>> {
|
||||
assert!(is_free(r_a) || *r_a == ty::ReStatic);
|
||||
self.relation.greater_than(&r_a)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_free(r: Region) -> bool {
|
||||
match *r {
|
||||
ty::ReEarlyBound(_) | ty::ReFree(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_free_or_static(r: Region) -> bool {
|
||||
match *r {
|
||||
ty::ReStatic => true,
|
||||
_ => is_free(r),
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
|
||||
relation
|
||||
});
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> {
|
||||
type Lifted = FreeRegionMap<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<FreeRegionMap<'tcx>> {
|
||||
self.relation.maybe_map(|&fr| fr.lift_to_tcx(tcx))
|
||||
.map(|relation| FreeRegionMap { relation })
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ pub use self::ObligationCauseCode::*;
|
||||
|
||||
use hir;
|
||||
use hir::def_id::DefId;
|
||||
use infer::outlives::free_region_map::FreeRegionMap;
|
||||
use middle::const_val::ConstEvalErr;
|
||||
use middle::region;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use ty::subst::Substs;
|
||||
use ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, ToPredicate};
|
||||
use ty::error::{ExpectedFound, TypeError};
|
||||
|
@ -23,10 +23,10 @@ use hir::map as hir_map;
|
||||
use hir::map::DefPathHash;
|
||||
use lint::{self, Lint};
|
||||
use ich::{StableHashingContext, NodeIdHashingMode};
|
||||
use infer::outlives::free_region_map::FreeRegionMap;
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::cstore::{CrateStore, LinkMeta};
|
||||
use middle::cstore::EncodedMetadata;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::lang_items;
|
||||
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
||||
use middle::stability;
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::middle::free_region::FreeRegionMap;
|
||||
use rustc::infer::outlives::free_region_map::FreeRegionMap;
|
||||
use rustc::ty::{self, RegionVid};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
@ -13,7 +13,7 @@ use rustc::infer::InferCtxt;
|
||||
use rustc::infer::RegionVariableOrigin;
|
||||
use rustc::infer::NLLRegionVariableOrigin;
|
||||
use rustc::infer::region_constraints::VarOrigins;
|
||||
use rustc::middle::free_region::FreeRegionMap;
|
||||
use rustc::infer::outlives::free_region_map::FreeRegionMap;
|
||||
use rustc::mir::{Location, Mir};
|
||||
use rustc::ty::{self, RegionVid};
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
|
@ -11,8 +11,8 @@
|
||||
use check::regionck::RegionCtxt;
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use rustc::infer::{self, InferOk};
|
||||
use rustc::infer::outlives::free_region_map::FreeRegionMap;
|
||||
use rustc::middle::region;
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
|
@ -11,7 +11,7 @@
|
||||
//! Check properties that are required by built-in traits and set
|
||||
//! up data structures required by type-checking/translation.
|
||||
|
||||
use rustc::middle::free_region::FreeRegionMap;
|
||||
use rustc::infer::outlives::free_region_map::FreeRegionMap;
|
||||
use rustc::middle::region;
|
||||
use rustc::middle::lang_items::UnsizeTraitLangItem;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user