rustc_next_trait_solver/
resolve.rs

1use rustc_type_ir::data_structures::DelayedMap;
2use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
3use rustc_type_ir::inherent::*;
4use rustc_type_ir::visit::TypeVisitableExt;
5use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
6
7use crate::delegate::SolverDelegate;
8
9///////////////////////////////////////////////////////////////////////////
10// EAGER RESOLUTION
11
12/// Resolves ty, region, and const vars to their inferred values or their root vars.
13pub struct EagerResolver<'a, D, I = <D as SolverDelegate>::Interner>
14where
15    D: SolverDelegate<Interner = I>,
16    I: Interner,
17{
18    delegate: &'a D,
19    /// We're able to use a cache here as the folder does not have any
20    /// mutable state.
21    cache: DelayedMap<I::Ty, I::Ty>,
22}
23
24impl<'a, D: SolverDelegate> EagerResolver<'a, D> {
25    pub fn new(delegate: &'a D) -> Self {
26        EagerResolver { delegate, cache: Default::default() }
27    }
28}
29
30impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, D> {
31    fn cx(&self) -> I {
32        self.delegate.cx()
33    }
34
35    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
36        match t.kind() {
37            ty::Infer(ty::TyVar(vid)) => {
38                let resolved = self.delegate.opportunistic_resolve_ty_var(vid);
39                if t != resolved && resolved.has_infer() {
40                    resolved.fold_with(self)
41                } else {
42                    resolved
43                }
44            }
45            ty::Infer(ty::IntVar(vid)) => self.delegate.opportunistic_resolve_int_var(vid),
46            ty::Infer(ty::FloatVar(vid)) => self.delegate.opportunistic_resolve_float_var(vid),
47            _ => {
48                if t.has_infer() {
49                    if let Some(&ty) = self.cache.get(&t) {
50                        return ty;
51                    }
52                    let res = t.super_fold_with(self);
53                    assert!(self.cache.insert(t, res));
54                    res
55                } else {
56                    t
57                }
58            }
59        }
60    }
61
62    fn fold_region(&mut self, r: I::Region) -> I::Region {
63        match r.kind() {
64            ty::ReVar(vid) => self.delegate.opportunistic_resolve_lt_var(vid),
65            _ => r,
66        }
67    }
68
69    fn fold_const(&mut self, c: I::Const) -> I::Const {
70        match c.kind() {
71            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
72                let resolved = self.delegate.opportunistic_resolve_ct_var(vid);
73                if c != resolved && resolved.has_infer() {
74                    resolved.fold_with(self)
75                } else {
76                    resolved
77                }
78            }
79            _ => {
80                if c.has_infer() {
81                    c.super_fold_with(self)
82                } else {
83                    c
84                }
85            }
86        }
87    }
88}