use rustc_type_ir::data_structures::DelayedMap; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::visit::TypeVisitableExt; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use crate::delegate::SolverDelegate; /////////////////////////////////////////////////////////////////////////// // EAGER RESOLUTION /// Resolves ty, region, and const vars to their inferred values or their root vars. pub struct EagerResolver<'a, D, I = ::Interner> where D: SolverDelegate, I: Interner, { delegate: &'a D, cache: DelayedMap, } impl<'a, D: SolverDelegate> EagerResolver<'a, D> { pub fn new(delegate: &'a D) -> Self { EagerResolver { delegate, cache: Default::default() } } } impl, I: Interner> TypeFolder for EagerResolver<'_, D> { fn cx(&self) -> I { self.delegate.cx() } fn fold_ty(&mut self, t: I::Ty) -> I::Ty { match t.kind() { ty::Infer(ty::TyVar(vid)) => { let resolved = self.delegate.opportunistic_resolve_ty_var(vid); if t != resolved && resolved.has_infer() { resolved.fold_with(self) } else { resolved } } ty::Infer(ty::IntVar(vid)) => self.delegate.opportunistic_resolve_int_var(vid), ty::Infer(ty::FloatVar(vid)) => self.delegate.opportunistic_resolve_float_var(vid), _ => { if t.has_infer() { if let Some(&ty) = self.cache.get(&t) { return ty; } let res = t.super_fold_with(self); assert!(self.cache.insert(t, res)); res } else { t } } } } fn fold_region(&mut self, r: I::Region) -> I::Region { match r.kind() { ty::ReVar(vid) => self.delegate.opportunistic_resolve_lt_var(vid), _ => r, } } fn fold_const(&mut self, c: I::Const) -> I::Const { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { let resolved = self.delegate.opportunistic_resolve_ct_var(vid); if c != resolved && resolved.has_infer() { resolved.fold_with(self) } else { resolved } } ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { self.delegate.opportunistic_resolve_effect_var(vid) } _ => { if c.has_infer() { c.super_fold_with(self) } else { c } } } } }