| use rustc_type_ir::data_structures::DelayedMap; | |
| use rustc_type_ir::inherent::*; | |
| use rustc_type_ir::{ | |
| self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, | |
| TypeVisitableExt, | |
| }; | |
| use crate::delegate::SolverDelegate; | |
| /////////////////////////////////////////////////////////////////////////// | |
| // EAGER RESOLUTION | |
| /// Resolves ty, region, and const vars to their inferred values or their root vars. | |
| struct EagerResolver<'a, D, I = <D as SolverDelegate>::Interner> | |
| where | |
| D: SolverDelegate<Interner = I>, | |
| I: Interner, | |
| { | |
| delegate: &'a D, | |
| /// We're able to use a cache here as the folder does not have any | |
| /// mutable state. | |
| cache: DelayedMap<I::Ty, I::Ty>, | |
| } | |
| pub fn eager_resolve_vars<D: SolverDelegate, T: TypeFoldable<D::Interner>>( | |
| delegate: &D, | |
| value: T, | |
| ) -> T { | |
| if value.has_infer() { | |
| let mut folder = EagerResolver::new(delegate); | |
| value.fold_with(&mut folder) | |
| } else { | |
| value | |
| } | |
| } | |
| impl<'a, D: SolverDelegate> EagerResolver<'a, D> { | |
| fn new(delegate: &'a D) -> Self { | |
| EagerResolver { delegate, cache: Default::default() } | |
| } | |
| } | |
| impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> 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 | |
| } | |
| } | |
| _ => { | |
| if c.has_infer() { | |
| c.super_fold_with(self) | |
| } else { | |
| c | |
| } | |
| } | |
| } | |
| } | |
| fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { | |
| if p.has_infer() { p.super_fold_with(self) } else { p } | |
| } | |
| fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { | |
| if c.has_infer() { c.super_fold_with(self) } else { c } | |
| } | |
| } |