From abd7d8813995337ff28c123db37011ceffcb3b26 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 10 Nov 2017 14:59:17 -0500 Subject: [PATCH] move `free_regions_map` into `infer::outlives` --- src/librustc/infer/mod.rs | 5 +- src/librustc/infer/outlives/env.rs | 2 +- .../infer/outlives/free_region_map.rs | 138 ++++++++++++++++++ src/librustc/infer/outlives/mod.rs | 1 + src/librustc/middle/free_region.rs | 131 +---------------- src/librustc/traits/mod.rs | 2 +- src/librustc/ty/context.rs | 2 +- .../borrow_check/nll/free_regions.rs | 2 +- .../borrow_check/nll/region_infer.rs | 2 +- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 2 +- 11 files changed, 152 insertions(+), 137 deletions(-) create mode 100644 src/librustc/infer/outlives/free_region_map.rs diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 05b131dc355..72d8077b4c5 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -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; diff --git a/src/librustc/infer/outlives/env.rs b/src/librustc/infer/outlives/env.rs index 409230ba79b..67f19b2c50d 100644 --- a/src/librustc/infer/outlives/env.rs +++ b/src/librustc/infer/outlives/env.rs @@ -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}; diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs new file mode 100644 index 00000000000..1d235eb244d --- /dev/null +++ b/src/librustc/infer/outlives/free_region_map.rs @@ -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 or the MIT license +// , 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> +} + +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> { + self.relation.maybe_map(|&fr| fr.lift_to_tcx(tcx)) + .map(|relation| FreeRegionMap { relation }) + } +} diff --git a/src/librustc/infer/outlives/mod.rs b/src/librustc/infer/outlives/mod.rs index 30d6799266e..b20f274f084 100644 --- a/src/librustc/infer/outlives/mod.rs +++ b/src/librustc/infer/outlives/mod.rs @@ -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; diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index 3f0e6e2c28d..ca6a5dd7f5b 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -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> -} - -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> { - self.relation.maybe_map(|&fr| fr.lift_to_tcx(tcx)) - .map(|relation| FreeRegionMap { relation }) - } -} diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8d1bba43322..ac08ff34518 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -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}; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0ab769d4fe3..ce05acb01b0 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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; diff --git a/src/librustc_mir/borrow_check/nll/free_regions.rs b/src/librustc_mir/borrow_check/nll/free_regions.rs index 92a8a714d52..7f984c72ee6 100644 --- a/src/librustc_mir/borrow_check/nll/free_regions.rs +++ b/src/librustc_mir/borrow_check/nll/free_regions.rs @@ -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; diff --git a/src/librustc_mir/borrow_check/nll/region_infer.rs b/src/librustc_mir/borrow_check/nll/region_infer.rs index aac341380a0..b304ea4f714 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer.rs @@ -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; diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 610d07efa35..f150c7db9b1 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -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}; diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index fedfa51d61d..01d0a7a3f85 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -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;