]> git.proxmox.com Git - rustc.git/blame - src/librustc_infer/infer/resolve.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_infer / infer / resolve.rs
CommitLineData
dc9dc135 1use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
dfeec247 2use super::{FixupError, FixupResult, InferCtxt, Span};
ba9703b0
XL
3use rustc_middle::ty::fold::{TypeFolder, TypeVisitor};
4use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
1a4d82fc
JJ
5
6///////////////////////////////////////////////////////////////////////////
dc9dc135 7// OPPORTUNISTIC VAR RESOLVER
1a4d82fc 8
dc9dc135
XL
9/// The opportunistic resolver can be used at any time. It simply replaces
10/// type/const variables that have been unified with the things they have
1a4d82fc
JJ
11/// been unified with (similar to `shallow_resolve`, but deep). This is
12/// useful for printing messages etc but also required at various
13/// points for correctness.
dc9dc135
XL
14pub struct OpportunisticVarResolver<'a, 'tcx> {
15 infcx: &'a InferCtxt<'a, 'tcx>,
1a4d82fc
JJ
16}
17
dc9dc135 18impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
a1dfa0c6 19 #[inline]
dc9dc135
XL
20 pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
21 OpportunisticVarResolver { infcx }
1a4d82fc
JJ
22 }
23}
24
dc9dc135
XL
25impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
26 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
1a4d82fc
JJ
27 self.infcx.tcx
28 }
29
30 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
74b04a01 31 if !t.has_infer_types_or_consts() {
1a4d82fc
JJ
32 t // micro-optimize -- if there is nothing in this type that this fold affects...
33 } else {
dc9dc135
XL
34 let t = self.infcx.shallow_resolve(t);
35 t.super_fold_with(self)
36 }
37 }
38
39 fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> {
74b04a01 40 if !ct.has_infer_types_or_consts() {
dc9dc135
XL
41 ct // micro-optimize -- if there is nothing in this const that this fold affects...
42 } else {
43 let ct = self.infcx.shallow_resolve(ct);
44 ct.super_fold_with(self)
9cc50fc6
SL
45 }
46 }
47}
48
f035d41b
XL
49/// The opportunistic region resolver opportunistically resolves regions
50/// variables to the variable with the least variable id. It is used when
51/// normlizing projections to avoid hitting the recursion limit by creating
52/// many versions of a predicate for types that in the end have to unify.
53///
54/// If you want to resolve type and const variables as well, call
55/// [InferCtxt::resolve_vars_if_possible] first.
56pub struct OpportunisticRegionResolver<'a, 'tcx> {
dc9dc135 57 infcx: &'a InferCtxt<'a, 'tcx>,
9cc50fc6
SL
58}
59
f035d41b 60impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> {
dc9dc135 61 pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
f035d41b 62 OpportunisticRegionResolver { infcx }
9cc50fc6
SL
63 }
64}
65
f035d41b 66impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
dc9dc135 67 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
9cc50fc6
SL
68 self.infcx.tcx
69 }
70
71 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
f035d41b 72 if !t.has_infer_regions() {
9cc50fc6
SL
73 t // micro-optimize -- if there is nothing in this type that this fold affects...
74 } else {
f035d41b 75 t.super_fold_with(self)
9cc50fc6
SL
76 }
77 }
78
7cac9316 79 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
9e0c209e 80 match *r {
f035d41b
XL
81 ty::ReVar(rid) => {
82 let resolved = self
83 .infcx
84 .inner
85 .borrow_mut()
86 .unwrap_region_constraints()
87 .opportunistic_resolve_var(rid);
88 self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved))
89 }
dfeec247 90 _ => r,
1a4d82fc
JJ
91 }
92 }
48663c56
XL
93
94 fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
f035d41b 95 if !ct.has_infer_regions() {
48663c56
XL
96 ct // micro-optimize -- if there is nothing in this const that this fold affects...
97 } else {
f035d41b 98 ct.super_fold_with(self)
48663c56
XL
99 }
100 }
1a4d82fc
JJ
101}
102
3b2f2976
XL
103///////////////////////////////////////////////////////////////////////////
104// UNRESOLVED TYPE FINDER
105
48663c56
XL
106/// The unresolved type **finder** walks a type searching for
107/// type variables that don't yet have a value. The first unresolved type is stored.
108/// It does not construct the fully resolved type (which might
3b2f2976 109/// involve some hashing and so forth).
dc9dc135
XL
110pub struct UnresolvedTypeFinder<'a, 'tcx> {
111 infcx: &'a InferCtxt<'a, 'tcx>,
48663c56
XL
112
113 /// Used to find the type parameter name and location for error reporting.
dc9dc135 114 pub first_unresolved: Option<(Ty<'tcx>, Option<Span>)>,
3b2f2976
XL
115}
116
dc9dc135
XL
117impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
118 pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
48663c56 119 UnresolvedTypeFinder { infcx, first_unresolved: None }
3b2f2976
XL
120 }
121}
122
dc9dc135 123impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
3b2f2976
XL
124 fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
125 let t = self.infcx.shallow_resolve(t);
126 if t.has_infer_types() {
e74abb32 127 if let ty::Infer(infer_ty) = t.kind {
3b2f2976
XL
128 // Since we called `shallow_resolve` above, this must
129 // be an (as yet...) unresolved inference variable.
dfeec247 130 let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
f9f354fc
XL
131 let mut inner = self.infcx.inner.borrow_mut();
132 let ty_vars = &inner.type_variables();
dc9dc135 133 if let TypeVariableOrigin {
dfeec247 134 kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
dc9dc135
XL
135 span,
136 } = *ty_vars.var_origin(ty_vid)
48663c56
XL
137 {
138 Some(span)
139 } else {
140 None
141 }
142 } else {
143 None
144 };
145 self.first_unresolved = Some((t, ty_var_span));
dfeec247 146 true // Halt visiting.
3b2f2976
XL
147 } else {
148 // Otherwise, visit its contents.
149 t.super_visit_with(self)
150 }
151 } else {
48663c56
XL
152 // All type variables in inference types must already be resolved,
153 // - no need to visit the contents, continue visiting.
3b2f2976
XL
154 false
155 }
156 }
157}
158
1a4d82fc
JJ
159///////////////////////////////////////////////////////////////////////////
160// FULL TYPE RESOLUTION
161
162/// Full type resolution replaces all type and region variables with
163/// their concrete results. If any variable cannot be replaced (never unified, etc)
164/// then an `Err` result is returned.
dc9dc135
XL
165pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: &T) -> FixupResult<'tcx, T>
166where
167 T: TypeFoldable<'tcx>,
1a4d82fc 168{
74b04a01 169 let mut full_resolver = FullTypeResolver { infcx, err: None };
1a4d82fc
JJ
170 let result = value.fold_with(&mut full_resolver);
171 match full_resolver.err {
172 None => Ok(result),
173 Some(e) => Err(e),
174 }
175}
176
177// N.B. This type is not public because the protocol around checking the
74b04a01 178// `err` field is not enforceable otherwise.
dc9dc135
XL
179struct FullTypeResolver<'a, 'tcx> {
180 infcx: &'a InferCtxt<'a, 'tcx>,
48663c56 181 err: Option<FixupError<'tcx>>,
1a4d82fc
JJ
182}
183
dc9dc135
XL
184impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
185 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
1a4d82fc
JJ
186 self.infcx.tcx
187 }
188
189 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
ba9703b0 190 if !t.needs_infer() {
1a4d82fc
JJ
191 t // micro-optimize -- if there is nothing in this type that this fold affects...
192 } else {
193 let t = self.infcx.shallow_resolve(t);
e74abb32 194 match t.kind {
b7449926 195 ty::Infer(ty::TyVar(vid)) => {
c1a9b12d 196 self.err = Some(FixupError::UnresolvedTy(vid));
f035d41b 197 self.tcx().ty_error()
1a4d82fc 198 }
b7449926 199 ty::Infer(ty::IntVar(vid)) => {
c1a9b12d 200 self.err = Some(FixupError::UnresolvedIntTy(vid));
f035d41b 201 self.tcx().ty_error()
1a4d82fc 202 }
b7449926 203 ty::Infer(ty::FloatVar(vid)) => {
c1a9b12d 204 self.err = Some(FixupError::UnresolvedFloatTy(vid));
f035d41b 205 self.tcx().ty_error()
1a4d82fc 206 }
b7449926 207 ty::Infer(_) => {
54a0048b 208 bug!("Unexpected type in full type resolver: {:?}", t);
1a4d82fc 209 }
dfeec247 210 _ => t.super_fold_with(self),
1a4d82fc
JJ
211 }
212 }
213 }
214
7cac9316 215 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
9e0c209e 216 match *r {
dfeec247
XL
217 ty::ReVar(rid) => self
218 .infcx
219 .lexical_region_resolutions
220 .borrow()
221 .as_ref()
222 .expect("region resolution not performed")
223 .resolve_var(rid),
9e0c209e 224 _ => r,
1a4d82fc
JJ
225 }
226 }
48663c56
XL
227
228 fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
ba9703b0 229 if !c.needs_infer() {
48663c56 230 c // micro-optimize -- if there is nothing in this const that this fold affects...
48663c56
XL
231 } else {
232 let c = self.infcx.shallow_resolve(c);
233 match c.val {
60c5eb7d 234 ty::ConstKind::Infer(InferConst::Var(vid)) => {
48663c56 235 self.err = Some(FixupError::UnresolvedConst(vid));
f035d41b 236 return self.tcx().const_error(c.ty);
48663c56 237 }
60c5eb7d 238 ty::ConstKind::Infer(InferConst::Fresh(_)) => {
48663c56
XL
239 bug!("Unexpected const in full const resolver: {:?}", c);
240 }
241 _ => {}
242 }
243 c.super_fold_with(self)
244 }
245 }
1a4d82fc 246}