Skip to content

Commit 1de196f

Browse files
HACK: Handle escaping bound vars from the canonical query
1 parent 5a31d5e commit 1de196f

File tree

2 files changed

+89
-3
lines changed
  • compiler
    • rustc_middle/src/ty
    • rustc_trait_selection/src/solve

2 files changed

+89
-3
lines changed

compiler/rustc_middle/src/ty/sty.rs

+88-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
77
use crate::ty::visit::ValidateBoundVars;
88
use crate::ty::InferTy::*;
99
use crate::ty::{
10-
self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
11-
TypeVisitor,
10+
self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
11+
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
1212
};
1313
use crate::ty::{List, ParamEnv};
1414
use hir::def::DefKind;
@@ -1106,6 +1106,17 @@ impl<'tcx, T> Binder<'tcx, T> {
11061106
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
11071107
}
11081108

1109+
pub fn no_bound_vars_ignoring_escaping(self, tcx: TyCtxt<'tcx>) -> Option<T>
1110+
where
1111+
T: TypeFoldable<'tcx>,
1112+
{
1113+
if !self.0.has_escaping_bound_vars() {
1114+
Some(self.skip_binder())
1115+
} else {
1116+
self.0.try_fold_with(&mut SkipBindersAt { index: ty::INNERMOST, tcx }).ok()
1117+
}
1118+
}
1119+
11091120
/// Splits the contents into two things that share the same binder
11101121
/// level as the original, returning two distinct binders.
11111122
///
@@ -1135,6 +1146,81 @@ impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
11351146
}
11361147
}
11371148

1149+
struct SkipBindersAt<'tcx> {
1150+
tcx: TyCtxt<'tcx>,
1151+
index: ty::DebruijnIndex,
1152+
}
1153+
1154+
impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
1155+
type Error = ();
1156+
1157+
fn tcx(&self) -> TyCtxt<'tcx> {
1158+
self.tcx
1159+
}
1160+
1161+
fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
1162+
where
1163+
T: ty::TypeFoldable<'tcx>,
1164+
{
1165+
self.index.shift_in(1);
1166+
let value = t.try_map_bound(|t| t.try_fold_with(self));
1167+
self.index.shift_out(1);
1168+
value
1169+
}
1170+
1171+
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
1172+
if !ty.has_escaping_bound_vars() {
1173+
Ok(ty)
1174+
} else if let ty::Bound(index, bv) = *ty.kind() {
1175+
if index == self.index {
1176+
Err(())
1177+
} else {
1178+
Ok(self.tcx().mk_ty(ty::Bound(index.shifted_out(1), bv)))
1179+
}
1180+
} else {
1181+
ty.try_super_fold_with(self)
1182+
}
1183+
}
1184+
1185+
fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
1186+
if !r.has_escaping_bound_vars() {
1187+
Ok(r)
1188+
} else if let ty::ReLateBound(index, bv) = r.kind() {
1189+
if index == self.index {
1190+
Err(())
1191+
} else {
1192+
Ok(self.tcx().mk_region(ty::ReLateBound(index.shifted_out(1), bv)))
1193+
}
1194+
} else {
1195+
r.try_super_fold_with(self)
1196+
}
1197+
}
1198+
1199+
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
1200+
if !ct.has_escaping_bound_vars() {
1201+
Ok(ct)
1202+
} else if let ty::ConstKind::Bound(index, bv) = ct.kind() {
1203+
if index == self.index {
1204+
Err(())
1205+
} else {
1206+
Ok(self.tcx().mk_const(
1207+
ty::ConstKind::Bound(index.shifted_out(1), bv),
1208+
ct.ty().try_fold_with(self)?,
1209+
))
1210+
}
1211+
} else {
1212+
ct.try_super_fold_with(self)
1213+
}
1214+
}
1215+
1216+
fn try_fold_predicate(
1217+
&mut self,
1218+
p: ty::Predicate<'tcx>,
1219+
) -> Result<ty::Predicate<'tcx>, Self::Error> {
1220+
if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) }
1221+
}
1222+
}
1223+
11381224
/// Represents the projection of an associated type.
11391225
///
11401226
/// For a projection, this would be `<Ty as Trait<...>>::N`.

compiler/rustc_trait_selection/src/solve/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ impl<'tcx> EvalCtxt<'tcx> {
213213
// recanonicalizing.
214214
let Goal { param_env, predicate } = canonical_goal.value;
215215

216-
if let Some(kind) = predicate.kind().no_bound_vars() {
216+
if let Some(kind) = predicate.kind().no_bound_vars_ignoring_escaping(self.tcx) {
217217
match kind {
218218
ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => self.compute_trait_goal(
219219
canonical_goal.unchecked_rebind(Goal { param_env, predicate }),

0 commit comments

Comments
 (0)