Adjust bound tys indices in canonicalization

This commit is contained in:
scalexm 2018-10-23 19:47:53 +02:00
parent ee569c796d
commit 1f8de94f3b
4 changed files with 56 additions and 11 deletions

View File

@ -280,6 +280,8 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
indices: FxHashMap<Kind<'tcx>, BoundVar>, indices: FxHashMap<Kind<'tcx>, BoundVar>,
canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode, canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode,
needs_canonical_flags: TypeFlags, needs_canonical_flags: TypeFlags,
binder_index: ty::DebruijnIndex,
} }
impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> {
@ -287,11 +289,23 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
self.tcx self.tcx
} }
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
where T: TypeFoldable<'tcx>
{
self.binder_index.shift_in(1);
let t = t.super_fold_with(self);
self.binder_index.shift_out(1);
t
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r { match *r {
ty::ReLateBound(..) => { ty::ReLateBound(index, ..) => {
// leave bound regions alone if index >= self.binder_index {
r bug!("escaping late bound region during canonicalization")
} else {
r
}
} }
ty::ReVar(vid) => { ty::ReVar(vid) => {
@ -337,8 +351,12 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
bug!("encountered a fresh type during canonicalization") bug!("encountered a fresh type during canonicalization")
} }
ty::Bound(_) => { ty::Bound(bound_ty) => {
bug!("encountered a bound type during canonicalization") if bound_ty.index >= self.binder_index {
bug!("escaping bound type during canonicalization")
} else {
t
}
} }
ty::Closure(..) ty::Closure(..)
@ -422,6 +440,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
variables: SmallVec::new(), variables: SmallVec::new(),
query_state, query_state,
indices: FxHashMap::default(), indices: FxHashMap::default(),
binder_index: ty::INNERMOST,
}; };
let out_value = value.fold_with(&mut canonicalizer); let out_value = value.fold_with(&mut canonicalizer);
@ -567,7 +586,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
kind: CanonicalVarKind::Ty(ty_kind), kind: CanonicalVarKind::Ty(ty_kind),
}; };
let var = self.canonical_var(info, ty_var.into()); let var = self.canonical_var(info, ty_var.into());
self.tcx().mk_ty(ty::Bound(BoundTy::new(ty::INNERMOST, var))) self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
} }
} }
} }

View File

@ -433,6 +433,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
UnpackedKind::Type(result_value) => { UnpackedKind::Type(result_value) => {
// e.g., here `result_value` might be `?0` in the example above... // e.g., here `result_value` might be `?0` in the example above...
if let ty::Bound(b) = result_value.sty { if let ty::Bound(b) = result_value.sty {
assert_eq!(b.index, ty::INNERMOST);
// in which case we would set `canonical_vars[0]` to `Some(?U)`. // in which case we would set `canonical_vars[0]` to `Some(?U)`.
opt_values[b.var] = Some(*original_value); opt_values[b.var] = Some(*original_value);
} }

View File

@ -69,13 +69,18 @@ where
} else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) { } else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
value.clone() value.clone()
} else { } else {
value.fold_with(&mut CanonicalVarValuesSubst { tcx, var_values }) value.fold_with(&mut CanonicalVarValuesSubst {
tcx,
var_values,
binder_index: ty::INNERMOST,
})
} }
} }
struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> { struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
tcx: TyCtxt<'cx, 'gcx, 'tcx>, tcx: TyCtxt<'cx, 'gcx, 'tcx>,
var_values: &'cx CanonicalVarValues<'tcx>, var_values: &'cx CanonicalVarValues<'tcx>,
binder_index: ty::DebruijnIndex,
} }
impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> {
@ -83,12 +88,29 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g
self.tcx self.tcx
} }
fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
where T: TypeFoldable<'tcx>
{
self.binder_index.shift_in(1);
let t = t.super_fold_with(self);
self.binder_index.shift_out(1);
t
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match t.sty { match t.sty {
ty::Bound(b) => { ty::Bound(b) => {
match self.var_values.var_values[b.var].unpack() { if b.index == self.binder_index {
UnpackedKind::Type(ty) => ty, match self.var_values.var_values[b.var].unpack() {
r => bug!("{:?} is a type but value is {:?}", b, r), UnpackedKind::Type(ty) => ty::fold::shift_vars(
self.tcx,
self.binder_index.index() as u32,
&ty
),
r => bug!("{:?} is a type but value is {:?}", b, r),
}
} else {
t
} }
} }
_ => { _ => {

View File

@ -556,7 +556,10 @@ impl CanonicalUserSubsts<'tcx> {
self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
match kind.unpack() { match kind.unpack() {
UnpackedKind::Type(ty) => match ty.sty { UnpackedKind::Type(ty) => match ty.sty {
ty::Bound(ref b) => cvar == b.var, ty::Bound(ref b) => {
assert_eq!(b.index, ty::INNERMOST);
cvar == b.var
}
_ => false, _ => false,
}, },