rustc_next_trait_solver/
resolve.rs1use rustc_type_ir::data_structures::DelayedMap;
2use rustc_type_ir::inherent::*;
3use rustc_type_ir::{
4 self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable,
5 TypeVisitableExt,
6};
7
8use crate::delegate::SolverDelegate;
9
10struct EagerResolver<'a, D, I = <D as SolverDelegate>::Interner>
15where
16 D: SolverDelegate<Interner = I>,
17 I: Interner,
18{
19 delegate: &'a D,
20 cache: DelayedMap<I::Ty, I::Ty>,
23}
24
25pub fn eager_resolve_vars<D: SolverDelegate, T: TypeFoldable<D::Interner>>(
26 delegate: &D,
27 value: T,
28) -> T {
29 if value.has_infer() {
30 let mut folder = EagerResolver::new(delegate);
31 value.fold_with(&mut folder)
32 } else {
33 value
34 }
35}
36
37impl<'a, D: SolverDelegate> EagerResolver<'a, D> {
38 fn new(delegate: &'a D) -> Self {
39 EagerResolver { delegate, cache: Default::default() }
40 }
41}
42
43impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, D> {
44 fn cx(&self) -> I {
45 self.delegate.cx()
46 }
47
48 fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
49 match t.kind() {
50 ty::Infer(ty::TyVar(vid)) => {
51 let resolved = self.delegate.opportunistic_resolve_ty_var(vid);
52 if t != resolved && resolved.has_infer() {
53 resolved.fold_with(self)
54 } else {
55 resolved
56 }
57 }
58 ty::Infer(ty::IntVar(vid)) => self.delegate.opportunistic_resolve_int_var(vid),
59 ty::Infer(ty::FloatVar(vid)) => self.delegate.opportunistic_resolve_float_var(vid),
60 _ => {
61 if t.has_infer() {
62 if let Some(&ty) = self.cache.get(&t) {
63 return ty;
64 }
65 let res = t.super_fold_with(self);
66 assert!(self.cache.insert(t, res));
67 res
68 } else {
69 t
70 }
71 }
72 }
73 }
74
75 fn fold_region(&mut self, r: I::Region) -> I::Region {
76 match r.kind() {
77 ty::ReVar(vid) => self.delegate.opportunistic_resolve_lt_var(vid),
78 _ => r,
79 }
80 }
81
82 fn fold_const(&mut self, c: I::Const) -> I::Const {
83 match c.kind() {
84 ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
85 let resolved = self.delegate.opportunistic_resolve_ct_var(vid);
86 if c != resolved && resolved.has_infer() {
87 resolved.fold_with(self)
88 } else {
89 resolved
90 }
91 }
92 _ => {
93 if c.has_infer() {
94 c.super_fold_with(self)
95 } else {
96 c
97 }
98 }
99 }
100 }
101
102 fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
103 if p.has_infer() { p.super_fold_with(self) } else { p }
104 }
105
106 fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
107 if c.has_infer() { c.super_fold_with(self) } else { c }
108 }
109}