Generalize the replace-late-bound-regions function to operate

over anything that is foldable, not just fn signatures.
This commit is contained in:
Niko Matsakis 2014-10-17 08:56:27 -04:00
parent 5c505b75b1
commit 1562d8cbd8
5 changed files with 35 additions and 31 deletions

View File

@ -97,11 +97,8 @@ use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
use middle::typeck::astconv;
use middle::typeck::check::_match::pat_ctxt;
use middle::typeck::check::method::{AutoderefReceiver};
use middle::typeck::check::method::{AutoderefReceiverFlag};
use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
use middle::typeck::check::method::{DontAutoderefReceiver};
use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
use middle::typeck::check::regionmanip::replace_late_bound_regions;
use middle::typeck::CrateCtxt;
use middle::typeck::infer::{resolve_type, force_tvar};
use middle::typeck::infer;
@ -529,7 +526,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
// First, we have to replace any bound regions in the fn type with free ones.
// The free region references will be bound the node_id of the body block.
let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
let (_, fn_sig) = replace_late_bound_regions(tcx, fn_sig.binder_id, fn_sig, |br| {
ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
});
@ -1531,6 +1528,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self.inh.infcx
}
pub fn sess(&self) -> &Session {
&self.tcx().sess
}
pub fn err_count_since_creation(&self) -> uint {
self.ccx.tcx.sess.err_count() - self.err_count_on_creation
}
@ -2890,7 +2891,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
// Replace any bound regions that appear in the function
// signature with region variables
let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
let (_, fn_sig) = replace_late_bound_regions(fcx.tcx(), fn_sig.binder_id, fn_sig, |br| {
fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
});
@ -3346,8 +3347,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
match expected_sty {
Some(ty::ty_closure(ref cenv)) => {
let (_, sig) =
replace_late_bound_regions_in_fn_sig(
tcx, &cenv.sig,
replace_late_bound_regions(
tcx, cenv.sig.binder_id, &cenv.sig,
|_| fcx.inh.infcx.fresh_bound_region(expr.id));
let onceness = match (&store, &cenv.store) {
// As the closure type and onceness go, only three

View File

@ -13,7 +13,7 @@
use middle::subst::{ParamSpace, Subst, Substs};
use middle::ty;
use middle::ty_fold;
use middle::ty_fold::TypeFolder;
use middle::ty_fold::{TypeFolder, TypeFoldable};
use syntax::ast;
@ -23,31 +23,34 @@ use util::ppaux::Repr;
// Helper functions related to manipulating region types.
pub fn replace_late_bound_regions_in_fn_sig(
tcx: &ty::ctxt,
fn_sig: &ty::FnSig,
mapf: |ty::BoundRegion| -> ty::Region)
-> (HashMap<ty::BoundRegion,ty::Region>, ty::FnSig) {
debug!("replace_late_bound_regions_in_fn_sig({})", fn_sig.repr(tcx));
pub fn replace_late_bound_regions<T>(
tcx: &ty::ctxt,
binder_id: ast::NodeId,
value: &T,
map_fn: |ty::BoundRegion| -> ty::Region)
-> (HashMap<ty::BoundRegion,ty::Region>, T)
where T : TypeFoldable + Repr
{
debug!("replace_late_bound_regions(binder_id={}, value={})",
binder_id, value.repr(tcx));
let mut map = HashMap::new();
let fn_sig = {
let mut f = ty_fold::RegionFolder::regions(tcx, |r| {
debug!("region r={}", r.to_string());
let new_value = {
let mut folder = ty_fold::RegionFolder::regions(tcx, |r| {
match r {
ty::ReLateBound(s, br) if s == fn_sig.binder_id => {
* match map.entry(br) {
Vacant(entry) => entry.set(mapf(br)),
Occupied(entry) => entry.into_mut(),
ty::ReLateBound(s, br) if s == binder_id => {
match map.entry(br) {
Vacant(entry) => *entry.set(map_fn(br)),
Occupied(entry) => *entry.into_mut(),
}
}
_ => r
}
});
ty_fold::super_fold_sig(&mut f, fn_sig)
value.fold_with(&mut folder)
};
debug!("resulting map: {}", map);
(map, fn_sig)
(map, new_value)
}
pub enum WfConstraint {

View File

@ -15,7 +15,7 @@ use middle::ty;
use middle::ty_fold::{TypeFolder, TypeFoldable};
use middle::typeck::astconv::AstConv;
use middle::typeck::check::{FnCtxt, Inherited, blank_fn_ctxt, vtable2, regionck};
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
use middle::typeck::check::regionmanip::replace_late_bound_regions;
use middle::typeck::CrateCtxt;
use util::ppaux::Repr;
@ -373,8 +373,8 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
self.binding_count += 1;
let (_, fn_sig) =
replace_late_bound_regions_in_fn_sig(
self.fcx.tcx(), fn_sig,
replace_late_bound_regions(
self.fcx.tcx(), fn_sig.binder_id, fn_sig,
|br| ty::ReFree(ty::FreeRegion{scope_id: self.scope_id,
bound_region: br}));

View File

@ -28,7 +28,7 @@ use middle::ty::{TyVid, IntVid, FloatVid, RegionVid};
use middle::ty;
use middle::ty_fold;
use middle::ty_fold::{TypeFolder, TypeFoldable};
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
use middle::typeck::check::regionmanip::replace_late_bound_regions;
use std::cell::{RefCell};
use std::collections::HashMap;
use std::rc::Rc;
@ -962,7 +962,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
HashMap<ty::BoundRegion,
ty::Region>) {
let (map, fn_sig) =
replace_late_bound_regions_in_fn_sig(self.tcx, fsig, |br| {
replace_late_bound_regions(self.tcx, fsig.binder_id, fsig, |br| {
let rvar = self.next_region_var(
BoundRegionInFnType(trace.origin.span(), br));
debug!("Bound region {} maps to {}",

View File

@ -12,7 +12,7 @@
use middle::ty::{BuiltinBounds};
use middle::ty;
use middle::ty::TyVar;
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
use middle::typeck::check::regionmanip::replace_late_bound_regions;
use middle::typeck::infer::combine::*;
use middle::typeck::infer::{cres, CresCompare};
use middle::typeck::infer::equate::Equate;
@ -189,7 +189,7 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> {
// Second, we instantiate each bound region in the supertype with a
// fresh concrete region.
let (skol_map, b_sig) = {
replace_late_bound_regions_in_fn_sig(self.fields.infcx.tcx, b, |br| {
replace_late_bound_regions(self.fields.infcx.tcx, b.binder_id, b, |br| {
let skol = self.fields.infcx.region_vars.new_skolemized(br);
debug!("Bound region {} skolemized to {}",
bound_region_to_string(self.fields.infcx.tcx, "", false, br),