hir_ty/next_solver/infer/
resolve.rs1use rustc_type_ir::{
4 TypeFolder, TypeSuperFoldable, TypeVisitableExt,
5 data_structures::DelayedMap,
6 inherent::{Const as _, Ty as _},
7};
8
9use crate::next_solver::{Const, DbInterner, ErrorGuaranteed, Region, Ty};
10
11use super::InferCtxt;
12
13pub struct OpportunisticVarResolver<'a, 'db> {
22 infcx: &'a InferCtxt<'db>,
23 cache: DelayedMap<Ty<'db>, Ty<'db>>,
26}
27
28impl<'a, 'db> OpportunisticVarResolver<'a, 'db> {
29 #[inline]
30 pub fn new(infcx: &'a InferCtxt<'db>) -> Self {
31 OpportunisticVarResolver { infcx, cache: Default::default() }
32 }
33}
34
35impl<'a, 'db> TypeFolder<DbInterner<'db>> for OpportunisticVarResolver<'a, 'db> {
36 fn cx(&self) -> DbInterner<'db> {
37 self.infcx.interner
38 }
39
40 #[inline]
41 fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
42 if !t.has_non_region_infer() {
43 t } else if let Some(ty) = self.cache.get(&t) {
45 *ty
46 } else {
47 let shallow = self.infcx.shallow_resolve(t);
48 let res = shallow.super_fold_with(self);
49 assert!(self.cache.insert(t, res));
50 res
51 }
52 }
53
54 fn fold_const(&mut self, ct: Const<'db>) -> Const<'db> {
55 if !ct.has_non_region_infer() {
56 ct } else {
58 let ct = self.infcx.shallow_resolve_const(ct);
59 ct.super_fold_with(self)
60 }
61 }
62}
63
64pub struct ReplaceInferWithError<'db> {
65 interner: DbInterner<'db>,
66}
67
68impl<'db> ReplaceInferWithError<'db> {
69 #[inline]
70 pub fn new(interner: DbInterner<'db>) -> Self {
71 Self { interner }
72 }
73}
74
75impl<'db> TypeFolder<DbInterner<'db>> for ReplaceInferWithError<'db> {
76 fn cx(&self) -> DbInterner<'db> {
77 self.interner
78 }
79
80 fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
81 if !t.has_infer() {
82 return t;
83 }
84
85 if t.is_infer() {
86 Ty::new_error(self.interner, ErrorGuaranteed)
87 } else {
88 t.super_fold_with(self)
89 }
90 }
91
92 fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
93 if !c.has_infer() {
94 return c;
95 }
96
97 if c.is_ct_infer() {
98 Const::new_error(self.interner, ErrorGuaranteed)
99 } else {
100 c.super_fold_with(self)
101 }
102 }
103
104 fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
105 if r.is_var() { Region::error(self.interner) } else { r }
106 }
107}