rustc_infer/infer/
resolve.rs
1use rustc_middle::bug;
2use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
3use rustc_middle::ty::visit::TypeVisitableExt;
4use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
5use rustc_type_ir::data_structures::DelayedMap;
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
60pub struct OpportunisticRegionResolver<'a, 'tcx> {
68 infcx: &'a InferCtxt<'tcx>,
69}
70
71impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> {
72 pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
73 OpportunisticRegionResolver { infcx }
74 }
75}
76
77impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx> {
78 fn cx(&self) -> TyCtxt<'tcx> {
79 self.infcx.tcx
80 }
81
82 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
83 if !t.has_infer_regions() {
84 t } else {
86 t.super_fold_with(self)
87 }
88 }
89
90 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
91 match *r {
92 ty::ReVar(vid) => self
93 .infcx
94 .inner
95 .borrow_mut()
96 .unwrap_region_constraints()
97 .opportunistic_resolve_var(TypeFolder::cx(self), vid),
98 _ => r,
99 }
100 }
101
102 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
103 if !ct.has_infer_regions() {
104 ct } else {
106 ct.super_fold_with(self)
107 }
108 }
109}
110
111pub fn fully_resolve<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> FixupResult<T>
118where
119 T: TypeFoldable<TyCtxt<'tcx>>,
120{
121 value.try_fold_with(&mut FullTypeResolver { infcx })
122}
123
124struct FullTypeResolver<'a, 'tcx> {
125 infcx: &'a InferCtxt<'tcx>,
126}
127
128impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
129 type Error = FixupError;
130
131 fn cx(&self) -> TyCtxt<'tcx> {
132 self.infcx.tcx
133 }
134
135 fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
136 if !t.has_infer() {
137 Ok(t) } else {
139 use super::TyOrConstInferVar::*;
140
141 let t = self.infcx.shallow_resolve(t);
142 match *t.kind() {
143 ty::Infer(ty::TyVar(vid)) => Err(FixupError { unresolved: Ty(vid) }),
144 ty::Infer(ty::IntVar(vid)) => Err(FixupError { unresolved: TyInt(vid) }),
145 ty::Infer(ty::FloatVar(vid)) => Err(FixupError { unresolved: TyFloat(vid) }),
146 ty::Infer(_) => {
147 bug!("Unexpected type in full type resolver: {:?}", t);
148 }
149 _ => t.try_super_fold_with(self),
150 }
151 }
152 }
153
154 fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
155 match *r {
156 ty::ReVar(_) => Ok(self
157 .infcx
158 .lexical_region_resolutions
159 .borrow()
160 .as_ref()
161 .expect("region resolution not performed")
162 .resolve_region(self.infcx.tcx, r)),
163 _ => Ok(r),
164 }
165 }
166
167 fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
168 if !c.has_infer() {
169 Ok(c) } else {
171 let c = self.infcx.shallow_resolve_const(c);
172 match c.kind() {
173 ty::ConstKind::Infer(InferConst::Var(vid)) => {
174 return Err(FixupError { unresolved: super::TyOrConstInferVar::Const(vid) });
175 }
176 ty::ConstKind::Infer(InferConst::Fresh(_)) => {
177 bug!("Unexpected const in full const resolver: {:?}", c);
178 }
179 _ => {}
180 }
181 c.try_super_fold_with(self)
182 }
183 }
184}