From aec62af7427083ac7f6dcb2fd484876199147fdc Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 7 Jan 2015 14:05:32 -0500 Subject: [PATCH] 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. --- .../middle/infer/higher_ranked/mod.rs | 2 +- src/librustc/middle/infer/mod.rs | 2 +- src/librustc/middle/ty.rs | 27 +++++++++++++------ src/librustc/util/ppaux.rs | 4 +-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index 073052dd3687..40f32a51e22f 100644 --- a/src/librustc/middle/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/infer/higher_ranked/mod.rs @@ -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) }); diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 3f18af3d768e..c1f0c10e11fe 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -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` diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9b9a58178cc3..2c9ff35364b2 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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) 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 diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 2d433369366e..0cf676b7035b 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1182,8 +1182,8 @@ impl<'tcx, T> UserString<'tcx> for ty::Binder // 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