Skip to main content

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
8///////////////////////////////////////////////////////////////////////////
9// EAGER RESOLUTION
10
11/// Resolves ty, region, and const vars to their inferred values or their root vars.
12struct EagerResolver<'a, D, I = <D as InferCtxtLike>::Interner>
13where
14    D: InferCtxtLike<Interner = I>,
15    I: Interner,
16{
17    delegate: &'a D,
18    /// We're able to use a cache here as the folder does not have any
19    /// mutable state.
20    cache: DelayedMap<I::Ty, I::Ty>,
21}
22
23pub fn eager_resolve_vars<Infcx: InferCtxtLike, T: TypeFoldable<Infcx::Interner>>(
24    infcx: &Infcx,
25    value: T,
26) -> T {
27    if value.has_infer() {
28        let mut folder = EagerResolver::new(infcx);
29        value.fold_with(&mut folder)
30    } else {
31        value
32    }
33}
34
35impl<'a, Infcx: InferCtxtLike> EagerResolver<'a, Infcx> {
36    fn new(delegate: &'a Infcx) -> Self {
37        EagerResolver { delegate, cache: Default::default() }
38    }
39}
40
41impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, Infcx> {
42    fn cx(&self) -> I {
43        self.delegate.cx()
44    }
45
46    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
47        match t.kind() {
48            ty::Infer(ty::TyVar(vid)) => {
49                let resolved = self.delegate.opportunistic_resolve_ty_var(vid);
50                if t != resolved && resolved.has_infer() {
51                    resolved.fold_with(self)
52                } else {
53                    resolved
54                }
55            }
56            ty::Infer(ty::IntVar(vid)) => self.delegate.opportunistic_resolve_int_var(vid),
57            ty::Infer(ty::FloatVar(vid)) => self.delegate.opportunistic_resolve_float_var(vid),
58            _ => {
59                if t.has_infer() {
60                    if let Some(&ty) = self.cache.get(&t) {
61                        return ty;
62                    }
63                    let res = t.super_fold_with(self);
64                    if !self.cache.insert(t, res) {
    ::core::panicking::panic("assertion failed: self.cache.insert(t, res)")
};assert!(self.cache.insert(t, res));
65                    res
66                } else {
67                    t
68                }
69            }
70        }
71    }
72
73    fn fold_region(&mut self, r: I::Region) -> I::Region {
74        match r.kind() {
75            ty::ReVar(vid) => self.delegate.opportunistic_resolve_lt_var(vid),
76            _ => r,
77        }
78    }
79
80    fn fold_const(&mut self, c: I::Const) -> I::Const {
81        match c.kind() {
82            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
83                let resolved = self.delegate.opportunistic_resolve_ct_var(vid);
84                if c != resolved && resolved.has_infer() {
85                    resolved.fold_with(self)
86                } else {
87                    resolved
88                }
89            }
90            _ => {
91                if c.has_infer() {
92                    c.super_fold_with(self)
93                } else {
94                    c
95                }
96            }
97        }
98    }
99
100    fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
101        if p.has_infer() { p.super_fold_with(self) } else { p }
102    }
103
104    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
105        if c.has_infer() { c.super_fold_with(self) } else { c }
106    }
107}