diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 9a66b98ee58..930d92ad1eb 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -70,6 +70,13 @@ pub trait TypeFolder<'tcx> : Sized { /// track the Debruijn index nesting level. fn exit_region_binder(&mut self) { } + fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + where T : TypeFoldable<'tcx> + Repr<'tcx> + { + // TODO this should eventually replace `enter_region_binder`/`exit_region_binder` altogether. + super_fold_binder(self, t) + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { super_fold_ty(self, t) } @@ -183,12 +190,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { } } -impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { +impl<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>> TypeFoldable<'tcx> for ty::Binder { fn fold_with>(&self, folder: &mut F) -> ty::Binder { - folder.enter_region_binder(); - let result = ty::Binder(self.0.fold_with(folder)); - folder.exit_region_binder(); - result + folder.fold_binder(self) } } @@ -556,6 +560,17 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> { // // They should invoke `foo.fold_with()` to do recursive folding. +pub fn super_fold_binder<'tcx, T, U>(this: &mut T, + binder: &ty::Binder) + -> ty::Binder + where T : TypeFolder<'tcx>, U : TypeFoldable<'tcx> +{ + this.enter_region_binder(); + let result = ty::Binder(binder.0.fold_with(this)); + this.exit_region_binder(); + result +} + pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, ty: Ty<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 704025f38ce..42ac1af325f 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -301,6 +301,18 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { self.fcx.tcx() } + fn fold_binder(&mut self, binder: &ty::Binder) -> ty::Binder + where T : TypeFoldable<'tcx> + Repr<'tcx> + { + self.binding_count += 1; + let value = liberate_late_bound_regions(self.fcx.tcx(), self.scope, binder); + debug!("BoundsChecker::fold_binder: late-bound regions replaced: {}", + value.repr(self.tcx())); + let value = value.fold_with(self); + self.binding_count -= 1; + ty::Binder(value) + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { debug!("BoundsChecker t={}", t.repr(self.tcx())); @@ -361,19 +373,6 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { self.fold_substs(substs); } - ty::ty_bare_fn(_, &ty::BareFnTy{sig: ref fn_sig, ..}) | - ty::ty_closure(box ty::ClosureTy{sig: ref fn_sig, ..}) => { - self.binding_count += 1; - - let fn_sig = liberate_late_bound_regions(self.fcx.tcx(), self.scope, fn_sig); - - debug!("late-bound regions replaced: {}", - fn_sig.repr(self.tcx())); - - self.fold_fn_sig(&fn_sig); - - self.binding_count -= 1; - } _ => { super_fold_ty(self, t); } diff --git a/src/test/run-pass/wf-bound-region-in-object-type.rs b/src/test/run-pass/wf-bound-region-in-object-type.rs new file mode 100644 index 00000000000..256b199d729 --- /dev/null +++ b/src/test/run-pass/wf-bound-region-in-object-type.rs @@ -0,0 +1,26 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the `wf` checker properly handles bound regions in object +// types. Compiling this code used to trigger an ICE. + +pub struct Context<'tcx> { + vec: &'tcx Vec +} + +pub type Cmd<'a> = &'a int; + +pub type DecodeInlinedItem<'a> = + Box FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx int, ()> + 'a>; + +fn foo(d: DecodeInlinedItem) { +} + +fn main() { }