move free_regions_map into infer::outlives

This commit is contained in:
Niko Matsakis 2017-11-10 14:59:17 -05:00
parent aa51603870
commit abd7d88139
11 changed files with 152 additions and 137 deletions

View file

@ -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;

View file

@ -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};

View 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 })
}
}

View file

@ -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;

View file

@ -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 })
}
}

View file

@ -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};

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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};

View file

@ -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;