diff options
| author | Michael Goulet <michael@errs.io> | 2023-01-10 23:41:43 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-01-12 21:01:34 +0000 |
| commit | 1de196fef308c236aee8804c7b452ad5f5bbaf88 (patch) | |
| tree | 23aede873e7e4efb361bac0f14fdb15e592ed56a | |
| parent | 5a31d5ebe253827f971352b5cac43884a35c6aaa (diff) | |
| download | rust-1de196fef308c236aee8804c7b452ad5f5bbaf88.tar.gz rust-1de196fef308c236aee8804c7b452ad5f5bbaf88.zip | |
HACK: Handle escaping bound vars from the canonical query
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 90 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/mod.rs | 2 |
2 files changed, 89 insertions, 3 deletions
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f7e4c821569..0d811d333be 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, - TypeVisitor, + self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; @@ -1106,6 +1106,17 @@ impl<'tcx, T> Binder<'tcx, T> { if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } + pub fn no_bound_vars_ignoring_escaping(self, tcx: TyCtxt<'tcx>) -> Option<T> + where + T: TypeFoldable<'tcx>, + { + if !self.0.has_escaping_bound_vars() { + Some(self.skip_binder()) + } else { + self.0.try_fold_with(&mut SkipBindersAt { index: ty::INNERMOST, tcx }).ok() + } + } + /// Splits the contents into two things that share the same binder /// level as the original, returning two distinct binders. /// @@ -1135,6 +1146,81 @@ impl<'tcx, T: IntoIterator> Binder<'tcx, T> { } } +struct SkipBindersAt<'tcx> { + tcx: TyCtxt<'tcx>, + index: ty::DebruijnIndex, +} + +impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> { + type Error = (); + + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error> + where + T: ty::TypeFoldable<'tcx>, + { + self.index.shift_in(1); + let value = t.try_map_bound(|t| t.try_fold_with(self)); + self.index.shift_out(1); + value + } + + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { + if !ty.has_escaping_bound_vars() { + Ok(ty) + } else if let ty::Bound(index, bv) = *ty.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_ty(ty::Bound(index.shifted_out(1), bv))) + } + } else { + ty.try_super_fold_with(self) + } + } + + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { + if !r.has_escaping_bound_vars() { + Ok(r) + } else if let ty::ReLateBound(index, bv) = r.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_region(ty::ReLateBound(index.shifted_out(1), bv))) + } + } else { + r.try_super_fold_with(self) + } + } + + fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> { + if !ct.has_escaping_bound_vars() { + Ok(ct) + } else if let ty::ConstKind::Bound(index, bv) = ct.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_const( + ty::ConstKind::Bound(index.shifted_out(1), bv), + ct.ty().try_fold_with(self)?, + )) + } + } else { + ct.try_super_fold_with(self) + } + } + + fn try_fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result<ty::Predicate<'tcx>, Self::Error> { + if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) } + } +} + /// Represents the projection of an associated type. /// /// For a projection, this would be `<Ty as Trait<...>>::N`. diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 35bb68b6fce..042ba96b379 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -213,7 +213,7 @@ impl<'tcx> EvalCtxt<'tcx> { // recanonicalizing. let Goal { param_env, predicate } = canonical_goal.value; - if let Some(kind) = predicate.kind().no_bound_vars() { + if let Some(kind) = predicate.kind().no_bound_vars_ignoring_escaping(self.tcx) { match kind { ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => self.compute_trait_goal( canonical_goal.unchecked_rebind(Goal { param_env, predicate }), |
