Fix ICE in WF checker when we encounter bound regions in object types.

This commit is contained in:
Niko Matsakis 2015-01-04 06:07:36 -05:00
parent 5e21e17d96
commit 71cdf76240
3 changed files with 58 additions and 18 deletions

View file

@ -70,6 +70,13 @@ pub trait TypeFolder<'tcx> : Sized {
/// track the Debruijn index nesting level. /// track the Debruijn index nesting level.
fn exit_region_binder(&mut self) { } 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> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
super_fold_ty(self, t) super_fold_ty(self, t)
} }
@ -183,12 +190,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for 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> { fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
folder.enter_region_binder(); folder.fold_binder(self)
let result = ty::Binder(self.0.fold_with(folder));
folder.exit_region_binder();
result
} }
} }
@ -556,6 +560,17 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> {
// //
// They should invoke `foo.fold_with()` to do recursive folding. // 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, pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
ty: Ty<'tcx>) ty: Ty<'tcx>)
-> Ty<'tcx> { -> Ty<'tcx> {

View file

@ -301,6 +301,18 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
self.fcx.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> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
debug!("BoundsChecker t={}", debug!("BoundsChecker t={}",
t.repr(self.tcx())); t.repr(self.tcx()));
@ -361,19 +373,6 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
self.fold_substs(substs); 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); super_fold_ty(self, t);
} }

View file

@ -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() { }