Solve rather subtle bug in replace_late_bound_regions -- we were passing the debruijn index in so that callees could construct late-bound regions at the right depth, but then the result was cached. When the cached result was used, it might be at the wrong depth. So now we don't pass the result in and instead simply adjust the depth to match the current nesting level as we go.

This commit is contained in:
Niko Matsakis 2015-01-07 14:05:32 -05:00
parent cf136cd350
commit aec62af742
4 changed files with 23 additions and 12 deletions

View file

@ -468,7 +468,7 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
* when higher-ranked things are involved. See `doc.rs` for more details.
*/
let (result, map) = ty::replace_late_bound_regions(infcx.tcx, binder, |br, _| {
let (result, map) = ty::replace_late_bound_regions(infcx.tcx, binder, |br| {
infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot)
});

View file

@ -1056,7 +1056,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
ty::replace_late_bound_regions(
self.tcx,
value,
|br, _| self.next_region_var(LateBoundRegion(span, br, lbrct)))
|br| self.next_region_var(LateBoundRegion(span, br, lbrct)))
}
/// See `verify_generic_bound` method in `region_inference`

View file

@ -6672,7 +6672,7 @@ pub fn liberate_late_bound_regions<'tcx, T>(
{
replace_late_bound_regions(
tcx, value,
|br, _| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0
|br| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0
}
pub fn count_late_bound_regions<'tcx, T>(
@ -6681,7 +6681,7 @@ pub fn count_late_bound_regions<'tcx, T>(
-> uint
where T : TypeFoldable<'tcx> + Repr<'tcx>
{
let (_, skol_map) = replace_late_bound_regions(tcx, value, |_, _| ty::ReStatic);
let (_, skol_map) = replace_late_bound_regions(tcx, value, |_| ty::ReStatic);
skol_map.len()
}
@ -6712,7 +6712,7 @@ pub fn erase_late_bound_regions<'tcx, T>(
-> T
where T : TypeFoldable<'tcx> + Repr<'tcx>
{
replace_late_bound_regions(tcx, value, |_, _| ty::ReStatic).0
replace_late_bound_regions(tcx, value, |_| ty::ReStatic).0
}
/// Rewrite any late-bound regions so that they are anonymous. Region numbers are
@ -6730,9 +6730,9 @@ pub fn anonymize_late_bound_regions<'tcx, T>(
where T : TypeFoldable<'tcx> + Repr<'tcx>,
{
let mut counter = 0;
ty::Binder(replace_late_bound_regions(tcx, sig, |_, db| {
ty::Binder(replace_late_bound_regions(tcx, sig, |_| {
counter += 1;
ReLateBound(db, BrAnon(counter))
ReLateBound(ty::DebruijnIndex::new(1), BrAnon(counter))
}).0)
}
@ -6743,7 +6743,7 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
mut mapf: F)
-> (T, FnvHashMap<ty::BoundRegion,ty::Region>)
where T : TypeFoldable<'tcx> + Repr<'tcx>,
F : FnMut(BoundRegion, DebruijnIndex) -> ty::Region,
F : FnMut(BoundRegion) -> ty::Region,
{
debug!("replace_late_bound_regions({})", binder.repr(tcx));
@ -6755,8 +6755,19 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
debug!("region={}", region.repr(tcx));
match region {
ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
* map.entry(br).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(mapf(br, debruijn)))
let region =
* map.entry(br).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(mapf(br)));
if let ty::ReLateBound(debruijn1, br) = region {
// If the callback returns a late-bound region,
// that region should always use depth 1. Then we
// adjust it to the correct depth.
assert_eq!(debruijn1.depth, 1);
ty::ReLateBound(debruijn, br)
} else {
region
}
}
_ => {
region

View file

@ -1182,8 +1182,8 @@ impl<'tcx, T> UserString<'tcx> for ty::Binder<T>
// the output. We'll probably want to tweak this over time to
// decide just how much information to give.
let mut names = Vec::new();
let (unbound_value, _) = ty::replace_late_bound_regions(tcx, self, |br, debruijn| {
ty::ReLateBound(debruijn, match br {
let (unbound_value, _) = ty::replace_late_bound_regions(tcx, self, |br| {
ty::ReLateBound(ty::DebruijnIndex::new(1), match br {
ty::BrNamed(_, name) => {
names.push(token::get_name(name));
br