rustc_next_trait_solver/
resolve.rs

1use 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
10///////////////////////////////////////////////////////////////////////////
11// EAGER RESOLUTION
12
13/// Resolves ty, region, and const vars to their inferred values or their root vars.
14struct EagerResolver<'a, D, I = <D as SolverDelegate>::Interner>
15where
16    D: SolverDelegate<Interner = I>,
17    I: Interner,
18{
19    delegate: &'a D,
20    /// We're able to use a cache here as the folder does not have any
21    /// mutable state.
22    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}