]> git.lizzy.rs Git - rust.git/commitdiff
Fix ICE in WF checker when we encounter bound regions in object types.
authorNiko Matsakis <niko@alum.mit.edu>
Sun, 4 Jan 2015 11:07:36 +0000 (06:07 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Sun, 4 Jan 2015 17:01:19 +0000 (12:01 -0500)
src/librustc/middle/ty_fold.rs
src/librustc_typeck/check/wf.rs
src/test/run-pass/wf-bound-region-in-object-type.rs [new file with mode: 0644]

index 9a66b98ee5841918d35c091111febeafdf91ed09..930d92ad1eb1970f211025a106c71258c156a53e 100644 (file)
@@ -70,6 +70,13 @@ fn enter_region_binder(&mut self) { }
     /// track the Debruijn index nesting level.
     fn exit_region_binder(&mut self) { }
 
+    fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+        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 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> {
     }
 }
 
-impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
+impl<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
-        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 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnboxedClosureUpv
 //
 // They should invoke `foo.fold_with()` to do recursive folding.
 
+pub fn super_fold_binder<'tcx, T, U>(this: &mut T,
+                                     binder: &ty::Binder<U>)
+                                     -> ty::Binder<U>
+    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> {
index 704025f38ce0d726c5454830bdf487a827a0e77b..42ac1af325f4842f4194b0783027459e375bb11c 100644 (file)
@@ -301,6 +301,18 @@ fn tcx(&self) -> &ty::ctxt<'tcx> {
         self.fcx.tcx()
     }
 
+    fn fold_binder<T>(&mut self, binder: &ty::Binder<T>) -> ty::Binder<T>
+        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 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'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 (file)
index 0000000..256b199
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<int>
+}
+
+pub type Cmd<'a> = &'a int;
+
+pub type DecodeInlinedItem<'a> =
+    Box<for<'tcx> FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx int, ()> + 'a>;
+
+fn foo(d: DecodeInlinedItem) {
+}
+
+fn main() { }