]> git.proxmox.com Git - rustc.git/blame - src/librustc/infer/resolve.rs
New upstream version 1.33.0+dfsg1
[rustc.git] / src / librustc / infer / resolve.rs
CommitLineData
c1a9b12d 1use super::{InferCtxt, FixupError, FixupResult};
54a0048b 2use ty::{self, Ty, TyCtxt, TypeFoldable};
3b2f2976 3use ty::fold::{TypeFolder, TypeVisitor};
1a4d82fc
JJ
4
5///////////////////////////////////////////////////////////////////////////
6// OPPORTUNISTIC TYPE RESOLVER
7
8/// The opportunistic type resolver can be used at any time. It simply replaces
9/// type variables that have been unified with the things they have
10/// been unified with (similar to `shallow_resolve`, but deep). This is
11/// useful for printing messages etc but also required at various
12/// points for correctness.
a7813a04
XL
13pub struct OpportunisticTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
14 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
1a4d82fc
JJ
15}
16
a7813a04 17impl<'a, 'gcx, 'tcx> OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
a1dfa0c6 18 #[inline]
a7813a04 19 pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
a1dfa0c6 20 OpportunisticTypeResolver { infcx }
1a4d82fc
JJ
21 }
22}
23
a7813a04
XL
24impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
25 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
1a4d82fc
JJ
26 self.infcx.tcx
27 }
28
29 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
c1a9b12d 30 if !t.has_infer_types() {
1a4d82fc
JJ
31 t // micro-optimize -- if there is nothing in this type that this fold affects...
32 } else {
33 let t0 = self.infcx.shallow_resolve(t);
9cc50fc6
SL
34 t0.super_fold_with(self)
35 }
36 }
37}
38
39/// The opportunistic type and region resolver is similar to the
3b2f2976 40/// opportunistic type resolver, but also opportunistically resolves
9cc50fc6 41/// regions. It is useful for canonicalization.
a7813a04
XL
42pub struct OpportunisticTypeAndRegionResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
43 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
9cc50fc6
SL
44}
45
a7813a04
XL
46impl<'a, 'gcx, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'gcx, 'tcx> {
47 pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
a1dfa0c6 48 OpportunisticTypeAndRegionResolver { infcx }
9cc50fc6
SL
49 }
50}
51
a7813a04
XL
52impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeAndRegionResolver<'a, 'gcx, 'tcx> {
53 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
9cc50fc6
SL
54 self.infcx.tcx
55 }
56
57 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
58 if !t.needs_infer() {
59 t // micro-optimize -- if there is nothing in this type that this fold affects...
60 } else {
61 let t0 = self.infcx.shallow_resolve(t);
62 t0.super_fold_with(self)
63 }
64 }
65
7cac9316 66 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
9e0c209e 67 match *r {
abe05a73
XL
68 ty::ReVar(rid) =>
69 self.infcx.borrow_region_constraints()
70 .opportunistic_resolve_var(self.tcx(), rid),
71 _ =>
72 r,
1a4d82fc
JJ
73 }
74 }
75}
76
3b2f2976
XL
77///////////////////////////////////////////////////////////////////////////
78// UNRESOLVED TYPE FINDER
79
80/// The unresolved type **finder** walks your type and searches for
81/// type variables that don't yet have a value. They get pushed into a
82/// vector. It does not construct the fully resolved type (which might
83/// involve some hashing and so forth).
84pub struct UnresolvedTypeFinder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
85 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
86}
87
88impl<'a, 'gcx, 'tcx> UnresolvedTypeFinder<'a, 'gcx, 'tcx> {
89 pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
90 UnresolvedTypeFinder { infcx }
91 }
92}
93
94impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx> {
95 fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
96 let t = self.infcx.shallow_resolve(t);
97 if t.has_infer_types() {
b7449926 98 if let ty::Infer(_) = t.sty {
3b2f2976
XL
99 // Since we called `shallow_resolve` above, this must
100 // be an (as yet...) unresolved inference variable.
101 true
102 } else {
103 // Otherwise, visit its contents.
104 t.super_visit_with(self)
105 }
106 } else {
107 // Micro-optimize: no inference types at all Can't have unresolved type
108 // variables, no need to visit the contents.
109 false
110 }
111 }
112}
113
1a4d82fc
JJ
114///////////////////////////////////////////////////////////////////////////
115// FULL TYPE RESOLUTION
116
117/// Full type resolution replaces all type and region variables with
118/// their concrete results. If any variable cannot be replaced (never unified, etc)
119/// then an `Err` result is returned.
a7813a04
XL
120pub fn fully_resolve<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
121 value: &T) -> FixupResult<T>
1a4d82fc
JJ
122 where T : TypeFoldable<'tcx>
123{
124 let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
125 let result = value.fold_with(&mut full_resolver);
126 match full_resolver.err {
127 None => Ok(result),
128 Some(e) => Err(e),
129 }
130}
131
132// N.B. This type is not public because the protocol around checking the
133// `err` field is not enforcable otherwise.
a7813a04
XL
134struct FullTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
135 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
c1a9b12d 136 err: Option<FixupError>,
1a4d82fc
JJ
137}
138
a7813a04
XL
139impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> {
140 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
1a4d82fc
JJ
141 self.infcx.tcx
142 }
143
144 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
3b2f2976 145 if !t.needs_infer() && !ty::keep_local(&t) {
1a4d82fc 146 t // micro-optimize -- if there is nothing in this type that this fold affects...
0bf4aa26
XL
147 // ^ we need to have the `keep_local` check to un-default
148 // defaulted tuples.
1a4d82fc
JJ
149 } else {
150 let t = self.infcx.shallow_resolve(t);
151 match t.sty {
b7449926 152 ty::Infer(ty::TyVar(vid)) => {
c1a9b12d 153 self.err = Some(FixupError::UnresolvedTy(vid));
1a4d82fc
JJ
154 self.tcx().types.err
155 }
b7449926 156 ty::Infer(ty::IntVar(vid)) => {
c1a9b12d 157 self.err = Some(FixupError::UnresolvedIntTy(vid));
1a4d82fc
JJ
158 self.tcx().types.err
159 }
b7449926 160 ty::Infer(ty::FloatVar(vid)) => {
c1a9b12d 161 self.err = Some(FixupError::UnresolvedFloatTy(vid));
1a4d82fc
JJ
162 self.tcx().types.err
163 }
b7449926 164 ty::Infer(_) => {
54a0048b 165 bug!("Unexpected type in full type resolver: {:?}", t);
1a4d82fc
JJ
166 }
167 _ => {
9cc50fc6 168 t.super_fold_with(self)
1a4d82fc
JJ
169 }
170 }
171 }
172 }
173
7cac9316 174 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
9e0c209e 175 match *r {
abe05a73
XL
176 ty::ReVar(rid) => self.infcx.lexical_region_resolutions
177 .borrow()
178 .as_ref()
179 .expect("region resolution not performed")
180 .resolve_var(rid),
9e0c209e 181 _ => r,
1a4d82fc
JJ
182 }
183 }
184}