From 4f34524fcbd9672e2fd6bb27e657da2c26051fdf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 12 Dec 2014 14:55:07 -0500 Subject: [PATCH] Move `leak_check` into its own method, and ensure that all higher-ranked code is in `higher_ranked.rs`. --- .../middle/infer/higher_ranked/mod.rs | 53 ++++++++++++++++--- src/librustc/middle/infer/mod.rs | 23 ++++---- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index dcc365fad18ee..ca4a6b28c2a1c 100644 --- a/src/librustc/middle/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/infer/higher_ranked/mod.rs @@ -11,7 +11,7 @@ //! Helper routines for higher-ranked things. See the `doc` module at //! the end of the file for details. -use super::{CombinedSnapshot, cres, InferCtxt, HigherRankedType}; +use super::{CombinedSnapshot, cres, InferCtxt, HigherRankedType, SkolemizationMap}; use super::combine::{Combine, Combineable}; use middle::ty::{mod, Binder}; @@ -81,7 +81,7 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C // Presuming type comparison succeeds, we need to check // that the skolemized regions do not "leak". - match leak_check(self.infcx(), &skol_map, snapshot) { + match self.infcx().leak_check(&skol_map, snapshot) { Ok(()) => { } Err((skol_br, tainted_region)) => { if self.a_is_expected() { @@ -455,11 +455,47 @@ impl<'a,'tcx> InferCtxtExt<'tcx> for InferCtxt<'a,'tcx> { } } -fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, - skol_map: &FnvHashMap, - snapshot: &CombinedSnapshot) - -> Result<(),(ty::BoundRegion,ty::Region)> +pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, + binder: &ty::Binder, + snapshot: &CombinedSnapshot) + -> (T, SkolemizationMap) + where T : TypeFoldable<'tcx> + Repr<'tcx> { + /*! + * Replace all regions bound by `binder` with skolemized regions and + * return a map indicating which bound-region was replaced with what + * skolemized region. This is the first step of checking subtyping + * when higher-ranked things are involved. See `doc.rs` for more details. + */ + + let (result, map) = ty::replace_late_bound_regions(infcx.tcx, binder, |br, _| { + infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot) + }); + + debug!("skolemize_bound_regions(binder={}, result={}, map={})", + binder.repr(infcx.tcx), + result.repr(infcx.tcx), + map.repr(infcx.tcx)); + + (result, map) +} + +pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, + skol_map: &SkolemizationMap, + snapshot: &CombinedSnapshot) + -> Result<(),(ty::BoundRegion,ty::Region)> +{ + /*! + * Searches the region constriants created since `snapshot` was started + * and checks to determine whether any of the skolemized regions created + * in `skol_map` would "escape" -- meaning that they are related to + * other regions in some way. If so, the higher-ranked subtyping doesn't + * hold. See `doc.rs` for more details. + */ + + debug!("leak_check: skol_map={}", + skol_map.repr(infcx.tcx)); + let new_vars = infcx.region_vars_confined_to_snapshot(snapshot); for (&skol_br, &skol) in skol_map.iter() { let tainted = infcx.tainted_regions(snapshot, skol); @@ -475,6 +511,11 @@ fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, } }; + debug!("{} (which replaced {}) is tainted by {}", + skol.repr(infcx.tcx), + skol_br.repr(infcx.tcx), + tainted_region.repr(infcx.tcx)); + // A is not as polymorphic as B: return Err((skol_br, tainted_region)); } diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index edd5c8b854e1f..0dfae4b882b7f 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -52,7 +52,7 @@ pub mod doc; pub mod equate; pub mod error_reporting; pub mod glb; -pub mod higher_ranked; +mod higher_ranked; pub mod lattice; pub mod lub; pub mod region_inference; @@ -90,7 +90,7 @@ pub struct InferCtxt<'a, 'tcx: 'a> { RegionVarBindings<'a, 'tcx>, } -/// A map returned by `skolemize_bound_regions()` indicating the skolemized +/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized /// region that each late-bound region was replaced with. pub type SkolemizationMap = FnvHashMap; @@ -709,16 +709,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { -> (T, SkolemizationMap) where T : TypeFoldable<'tcx> + Repr<'tcx> { - let (result, map) = replace_late_bound_regions(self.tcx, value, |br, _| { - self.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot) - }); + /*! See `higher_ranked::skolemize_late_bound_regions` */ - debug!("skolemize_bound_regions(value={}, result={}, map={})", - value.repr(self.tcx), - result.repr(self.tcx), - map.repr(self.tcx)); + higher_ranked::skolemize_late_bound_regions(self, value, snapshot) + } + + pub fn leak_check(&self, + skol_map: &SkolemizationMap, + snapshot: &CombinedSnapshot) + -> Result<(),(ty::BoundRegion,ty::Region)> + { + /*! See `higher_ranked::leak_check` */ - (result, map) + higher_ranked::leak_check(self, skol_map, snapshot) } pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {