Move leak_check into its own method, and ensure that all higher-ranked code is in

`higher_ranked.rs`.
This commit is contained in:
Niko Matsakis 2014-12-12 14:55:07 -05:00
parent 1205fd88df
commit 4f34524fcb
2 changed files with 60 additions and 16 deletions

View file

@ -11,7 +11,7 @@
//! Helper routines for higher-ranked things. See the `doc` module at //! Helper routines for higher-ranked things. See the `doc` module at
//! the end of the file for details. //! 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 super::combine::{Combine, Combineable};
use middle::ty::{mod, Binder}; use middle::ty::{mod, Binder};
@ -81,7 +81,7 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C
// Presuming type comparison succeeds, we need to check // Presuming type comparison succeeds, we need to check
// that the skolemized regions do not "leak". // that the skolemized regions do not "leak".
match leak_check(self.infcx(), &skol_map, snapshot) { match self.infcx().leak_check(&skol_map, snapshot) {
Ok(()) => { } Ok(()) => { }
Err((skol_br, tainted_region)) => { Err((skol_br, tainted_region)) => {
if self.a_is_expected() { 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>, pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
skol_map: &FnvHashMap<ty::BoundRegion,ty::Region>, binder: &ty::Binder<T>,
snapshot: &CombinedSnapshot) snapshot: &CombinedSnapshot)
-> Result<(),(ty::BoundRegion,ty::Region)> -> (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); let new_vars = infcx.region_vars_confined_to_snapshot(snapshot);
for (&skol_br, &skol) in skol_map.iter() { for (&skol_br, &skol) in skol_map.iter() {
let tainted = infcx.tainted_regions(snapshot, skol); 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: // A is not as polymorphic as B:
return Err((skol_br, tainted_region)); return Err((skol_br, tainted_region));
} }

View file

@ -52,7 +52,7 @@ pub mod doc;
pub mod equate; pub mod equate;
pub mod error_reporting; pub mod error_reporting;
pub mod glb; pub mod glb;
pub mod higher_ranked; mod higher_ranked;
pub mod lattice; pub mod lattice;
pub mod lub; pub mod lub;
pub mod region_inference; pub mod region_inference;
@ -90,7 +90,7 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
RegionVarBindings<'a, 'tcx>, 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. /// region that each late-bound region was replaced with.
pub type SkolemizationMap = FnvHashMap<ty::BoundRegion,ty::Region>; pub type SkolemizationMap = FnvHashMap<ty::BoundRegion,ty::Region>;
@ -709,16 +709,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-> (T, SkolemizationMap) -> (T, SkolemizationMap)
where T : TypeFoldable<'tcx> + Repr<'tcx> where T : TypeFoldable<'tcx> + Repr<'tcx>
{ {
let (result, map) = replace_late_bound_regions(self.tcx, value, |br, _| { /*! See `higher_ranked::skolemize_late_bound_regions` */
self.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot)
});
debug!("skolemize_bound_regions(value={}, result={}, map={})", higher_ranked::skolemize_late_bound_regions(self, value, snapshot)
value.repr(self.tcx), }
result.repr(self.tcx),
map.repr(self.tcx));
(result, map) pub fn leak_check(&self,
skol_map: &SkolemizationMap,
snapshot: &CombinedSnapshot)
-> Result<(),(ty::BoundRegion,ty::Region)>
{
/*! See `higher_ranked::leak_check` */
higher_ranked::leak_check(self, skol_map, snapshot)
} }
pub fn next_ty_var_id(&self, diverging: bool) -> TyVid { pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {