rustc_infer/infer/
resolve.rs1use rustc_middle::bug;
2use rustc_middle::ty::{
3 self, Const, DelayedMap, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder,
4 TypeSuperFoldable, TypeVisitableExt,
5};
6
7use super::{FixupError, FixupResult, InferCtxt};
8
9pub struct OpportunisticVarResolver<'a, 'tcx> {
18 infcx: &'a InferCtxt<'tcx>,
19 cache: DelayedMap<Ty<'tcx>, Ty<'tcx>>,
22}
23
24impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
25 #[inline]
26 pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
27 OpportunisticVarResolver { infcx, cache: Default::default() }
28 }
29}
30
31impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
32 fn cx(&self) -> TyCtxt<'tcx> {
33 self.infcx.tcx
34 }
35
36 #[inline]
37 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
38 if !t.has_non_region_infer() {
39 t } else if let Some(&ty) = self.cache.get(&t) {
41 ty
42 } else {
43 let shallow = self.infcx.shallow_resolve(t);
44 let res = shallow.super_fold_with(self);
45 assert!(self.cache.insert(t, res));
46 res
47 }
48 }
49
50 fn fold_const(&mut self, ct: Const<'tcx>) -> Const<'tcx> {
51 if !ct.has_non_region_infer() {
52 ct } else {
54 let ct = self.infcx.shallow_resolve_const(ct);
55 ct.super_fold_with(self)
56 }
57 }
58
59 fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
60 if !p.has_non_region_infer() { p } else { p.super_fold_with(self) }
61 }
62
63 fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
64 if !c.has_non_region_infer() { c } else { c.super_fold_with(self) }
65 }
66}
67
68pub struct OpportunisticRegionResolver<'a, 'tcx> {
76 infcx: &'a InferCtxt<'tcx>,
77}
78
79impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> {
80 pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
81 OpportunisticRegionResolver { infcx }
82 }
83}
84
85impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx> {
86 fn cx(&self) -> TyCtxt<'tcx> {
87 self.infcx.tcx
88 }
89
90 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
91 if !t.has_infer_regions() {
92 t } else {
94 t.super_fold_with(self)
95 }
96 }
97
98 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
99 match r.kind() {
100 ty::ReVar(vid) => self
101 .infcx
102 .inner
103 .borrow_mut()
104 .unwrap_region_constraints()
105 .opportunistic_resolve_var(TypeFolder::cx(self), vid),
106 _ => r,
107 }
108 }
109
110 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
111 if !ct.has_infer_regions() {
112 ct } else {
114 ct.super_fold_with(self)
115 }
116 }
117}
118
119pub fn fully_resolve<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> FixupResult<T>
126where
127 T: TypeFoldable<TyCtxt<'tcx>>,
128{
129 value.try_fold_with(&mut FullTypeResolver { infcx })
130}
131
132struct FullTypeResolver<'a, 'tcx> {
133 infcx: &'a InferCtxt<'tcx>,
134}
135
136impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
137 type Error = FixupError;
138
139 fn cx(&self) -> TyCtxt<'tcx> {
140 self.infcx.tcx
141 }
142
143 fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
144 if !t.has_infer() {
145 Ok(t) } else {
147 use super::TyOrConstInferVar::*;
148
149 let t = self.infcx.shallow_resolve(t);
150 match *t.kind() {
151 ty::Infer(ty::TyVar(vid)) => Err(FixupError { unresolved: Ty(vid) }),
152 ty::Infer(ty::IntVar(vid)) => Err(FixupError { unresolved: TyInt(vid) }),
153 ty::Infer(ty::FloatVar(vid)) => Err(FixupError { unresolved: TyFloat(vid) }),
154 ty::Infer(_) => {
155 bug!("Unexpected type in full type resolver: {:?}", t);
156 }
157 _ => t.try_super_fold_with(self),
158 }
159 }
160 }
161
162 fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
163 match r.kind() {
164 ty::ReVar(_) => Ok(self
165 .infcx
166 .lexical_region_resolutions
167 .borrow()
168 .as_ref()
169 .expect("region resolution not performed")
170 .resolve_region(self.infcx.tcx, r)),
171 _ => Ok(r),
172 }
173 }
174
175 fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
176 if !c.has_infer() {
177 Ok(c) } else {
179 let c = self.infcx.shallow_resolve_const(c);
180 match c.kind() {
181 ty::ConstKind::Infer(InferConst::Var(vid)) => {
182 return Err(FixupError { unresolved: super::TyOrConstInferVar::Const(vid) });
183 }
184 ty::ConstKind::Infer(InferConst::Fresh(_)) => {
185 bug!("Unexpected const in full const resolver: {:?}", c);
186 }
187 _ => {}
188 }
189 c.try_super_fold_with(self)
190 }
191 }
192}