Skip to content

Commit bf164bc

Browse files
author
Ariel Ben-Yehuda
committed
Fix lifetime elision region accounting
This merges accumulate_regions_in_type with ty_fold::collect_regions. Fixes #26638
1 parent a1110bc commit bf164bc

File tree

9 files changed

+187
-179
lines changed

9 files changed

+187
-179
lines changed

src/librustc/middle/infer/higher_ranked/mod.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>,
359359
where T: TypeFoldable<'tcx>,
360360
F: FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
361361
{
362-
unbound_value.fold_with(&mut ty_fold::RegionFolder::new(tcx, &mut |region, current_depth| {
362+
ty_fold::fold_regions(tcx, unbound_value, &mut false, |region, current_depth| {
363363
// we should only be encountering "escaping" late-bound regions here,
364364
// because the ones at the current level should have been replaced
365365
// with fresh variables
@@ -369,7 +369,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>,
369369
});
370370

371371
fldr(region, ty::DebruijnIndex::new(current_depth))
372-
}))
372+
})
373373
}
374374

375375
impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
@@ -437,11 +437,10 @@ impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
437437
let escaping_types =
438438
self.type_variables.borrow().types_escaping_snapshot(&snapshot.type_snapshot);
439439

440-
let escaping_region_vars: FnvHashSet<_> =
441-
escaping_types
442-
.iter()
443-
.flat_map(|&t| ty_fold::collect_regions(self.tcx, &t))
444-
.collect();
440+
let mut escaping_region_vars = FnvHashSet();
441+
for ty in &escaping_types {
442+
ty_fold::collect_regions(self.tcx, ty, &mut escaping_region_vars);
443+
}
445444

446445
region_vars.retain(|&region_vid| {
447446
let r = ty::ReInfer(ty::ReVar(region_vid));
@@ -649,7 +648,7 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
649648
// binder is that we encountered in `value`. The caller is
650649
// responsible for ensuring that (a) `value` contains at least one
651650
// binder and (b) that binder is the one we want to use.
652-
let result = ty_fold::fold_regions(infcx.tcx, &value, |r, current_depth| {
651+
let result = ty_fold::fold_regions(infcx.tcx, &value, &mut false, |r, current_depth| {
653652
match inv_skol_map.get(&r) {
654653
None => r,
655654
Some(br) => {

src/librustc/middle/ty.rs

Lines changed: 12 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,6 +1713,16 @@ impl Region {
17131713
_ => false,
17141714
}
17151715
}
1716+
1717+
/// Returns the depth of `self` from the (1-based) binding level `depth`
1718+
pub fn from_depth(&self, depth: u32) -> Region {
1719+
match *self {
1720+
ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex {
1721+
depth: debruijn.depth - (depth - 1)
1722+
}, r),
1723+
r => r
1724+
}
1725+
}
17161726
}
17171727

17181728
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
@@ -6783,60 +6793,6 @@ pub enum ExplicitSelfCategory {
67836793
ByBoxExplicitSelfCategory,
67846794
}
67856795

6786-
impl<'tcx> TyS<'tcx> {
6787-
/// Pushes all the lifetimes in the given type onto the given list. A
6788-
/// "lifetime in a type" is a lifetime specified by a reference or a lifetime
6789-
/// in a list of type substitutions. This does *not* traverse into nominal
6790-
/// types, nor does it resolve fictitious types.
6791-
pub fn accumulate_lifetimes_in_type(&self, accumulator: &mut Vec<ty::Region>) {
6792-
for ty in self.walk() {
6793-
match ty.sty {
6794-
TyRef(region, _) => {
6795-
accumulator.push(*region)
6796-
}
6797-
TyTrait(ref t) => {
6798-
accumulator.push_all(t.principal.0.substs.regions().as_slice());
6799-
}
6800-
TyEnum(_, substs) |
6801-
TyStruct(_, substs) => {
6802-
accum_substs(accumulator, substs);
6803-
}
6804-
TyClosure(_, substs) => {
6805-
accum_substs(accumulator, substs);
6806-
}
6807-
TyBool |
6808-
TyChar |
6809-
TyInt(_) |
6810-
TyUint(_) |
6811-
TyFloat(_) |
6812-
TyBox(_) |
6813-
TyStr |
6814-
TyArray(_, _) |
6815-
TySlice(_) |
6816-
TyRawPtr(_) |
6817-
TyBareFn(..) |
6818-
TyTuple(_) |
6819-
TyProjection(_) |
6820-
TyParam(_) |
6821-
TyInfer(_) |
6822-
TyError => {
6823-
}
6824-
}
6825-
}
6826-
6827-
fn accum_substs(accumulator: &mut Vec<Region>, substs: &Substs) {
6828-
match substs.regions {
6829-
subst::ErasedRegions => {}
6830-
subst::NonerasedRegions(ref regions) => {
6831-
for region in regions {
6832-
accumulator.push(*region)
6833-
}
6834-
}
6835-
}
6836-
}
6837-
}
6838-
}
6839-
68406796
/// A free variable referred to in a function.
68416797
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
68426798
pub struct Freevar {
@@ -6917,7 +6873,8 @@ impl<'tcx> ctxt<'tcx> {
69176873
where T: TypeFoldable<'tcx>
69186874
{
69196875
let bound0_value = bound2_value.skip_binder().skip_binder();
6920-
let value = ty_fold::fold_regions(self, bound0_value, |region, current_depth| {
6876+
let value = ty_fold::fold_regions(self, bound0_value, &mut false,
6877+
|region, current_depth| {
69216878
match region {
69226879
ty::ReLateBound(debruijn, br) if debruijn.depth >= current_depth => {
69236880
// should be true if no escaping regions from bound2_value

src/librustc/middle/ty_fold.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use std::rc::Rc;
4444
use syntax::abi;
4545
use syntax::ast;
4646
use syntax::owned_slice::OwnedSlice;
47-
use util::nodemap::FnvHashMap;
47+
use util::nodemap::{FnvHashMap, FnvHashSet};
4848

4949
///////////////////////////////////////////////////////////////////////////
5050
// Two generic traits
@@ -783,38 +783,51 @@ impl<'a, 'tcx, F> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx, F> where
783783
784784
pub struct RegionFolder<'a, 'tcx: 'a> {
785785
tcx: &'a ty::ctxt<'tcx>,
786+
skipped_regions: &'a mut bool,
786787
current_depth: u32,
787788
fld_r: &'a mut (FnMut(ty::Region, u32) -> ty::Region + 'a),
788789
}
789790

790791
impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
791-
pub fn new<F>(tcx: &'a ty::ctxt<'tcx>, fld_r: &'a mut F) -> RegionFolder<'a, 'tcx>
792+
pub fn new<F>(tcx: &'a ty::ctxt<'tcx>,
793+
skipped_regions: &'a mut bool,
794+
fld_r: &'a mut F) -> RegionFolder<'a, 'tcx>
792795
where F : FnMut(ty::Region, u32) -> ty::Region
793796
{
794797
RegionFolder {
795798
tcx: tcx,
799+
skipped_regions: skipped_regions,
796800
current_depth: 1,
797801
fld_r: fld_r,
798802
}
799803
}
800804
}
801805

802-
pub fn collect_regions<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> Vec<ty::Region>
806+
/// Collects the free and escaping regions in `value` into `region_set`. Returns
807+
/// whether any late-bound regions were skipped
808+
pub fn collect_regions<'tcx,T>(tcx: &ty::ctxt<'tcx>,
809+
value: &T,
810+
region_set: &mut FnvHashSet<ty::Region>) -> bool
803811
where T : TypeFoldable<'tcx>
804812
{
805-
let mut vec = Vec::new();
806-
fold_regions(tcx, value, |r, _| { vec.push(r); r });
807-
vec
813+
let mut have_bound_regions = false;
814+
fold_regions(tcx, value, &mut have_bound_regions,
815+
|r, d| { region_set.insert(r.from_depth(d)); r });
816+
have_bound_regions
808817
}
809818

819+
/// Folds the escaping and free regions in `value` using `f`, and
820+
/// sets `skipped_regions` to true if any late-bound region was found
821+
/// and skipped.
810822
pub fn fold_regions<'tcx,T,F>(tcx: &ty::ctxt<'tcx>,
811823
value: &T,
824+
skipped_regions: &mut bool,
812825
mut f: F)
813826
-> T
814827
where F : FnMut(ty::Region, u32) -> ty::Region,
815828
T : TypeFoldable<'tcx>,
816829
{
817-
value.fold_with(&mut RegionFolder::new(tcx, &mut f))
830+
value.fold_with(&mut RegionFolder::new(tcx, skipped_regions, &mut f))
818831
}
819832

820833
impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
@@ -834,6 +847,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
834847
ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
835848
debug!("RegionFolder.fold_region({:?}) skipped bound region (current depth={})",
836849
r, self.current_depth);
850+
*self.skipped_regions = true;
837851
r
838852
}
839853
_ => {
@@ -989,7 +1003,7 @@ pub fn shift_regions<'tcx, T:TypeFoldable<'tcx>>(tcx: &ty::ctxt<'tcx>,
9891003
debug!("shift_regions(value={:?}, amount={})",
9901004
value, amount);
9911005

992-
value.fold_with(&mut RegionFolder::new(tcx, &mut |region, _current_depth| {
1006+
value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| {
9931007
shift_region(region, amount)
9941008
}))
9951009
}

src/librustc/middle/ty_walk.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
//! An iterator over the type substructure.
12+
//! WARNING: this does not keep track of the region depth.
1213
1314
use middle::ty::{self, Ty};
1415
use std::iter::Iterator;

0 commit comments

Comments
 (0)