]> git.proxmox.com Git - rustc.git/blob - src/librustc/infer/resolve.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / librustc / infer / resolve.rs
1 use super::{InferCtxt, FixupError, FixupResult};
2 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
3 use crate::ty::fold::{TypeFolder, TypeVisitor};
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.
13 pub struct OpportunisticTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
14 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
15 }
16
17 impl<'a, 'gcx, 'tcx> OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
18 #[inline]
19 pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
20 OpportunisticTypeResolver { infcx }
21 }
22 }
23
24 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
25 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
26 self.infcx.tcx
27 }
28
29 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
30 if !t.has_infer_types() {
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);
34 t0.super_fold_with(self)
35 }
36 }
37 }
38
39 /// The opportunistic type and region resolver is similar to the
40 /// opportunistic type resolver, but also opportunistically resolves
41 /// regions. It is useful for canonicalization.
42 pub struct OpportunisticTypeAndRegionResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
43 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
44 }
45
46 impl<'a, 'gcx, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'gcx, 'tcx> {
47 pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
48 OpportunisticTypeAndRegionResolver { infcx }
49 }
50 }
51
52 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeAndRegionResolver<'a, 'gcx, 'tcx> {
53 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
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
66 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
67 match *r {
68 ty::ReVar(rid) =>
69 self.infcx.borrow_region_constraints()
70 .opportunistic_resolve_var(self.tcx(), rid),
71 _ =>
72 r,
73 }
74 }
75 }
76
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).
84 pub struct UnresolvedTypeFinder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
85 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
86 }
87
88 impl<'a, 'gcx, 'tcx> UnresolvedTypeFinder<'a, 'gcx, 'tcx> {
89 pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
90 UnresolvedTypeFinder { infcx }
91 }
92 }
93
94 impl<'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() {
98 if let ty::Infer(_) = t.sty {
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
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.
120 pub fn fully_resolve<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
121 value: &T) -> FixupResult<T>
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.
134 struct FullTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
135 infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
136 err: Option<FixupError>,
137 }
138
139 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> {
140 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
141 self.infcx.tcx
142 }
143
144 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
145 if !t.needs_infer() && !ty::keep_local(&t) {
146 t // micro-optimize -- if there is nothing in this type that this fold affects...
147 // ^ we need to have the `keep_local` check to un-default
148 // defaulted tuples.
149 } else {
150 let t = self.infcx.shallow_resolve(t);
151 match t.sty {
152 ty::Infer(ty::TyVar(vid)) => {
153 self.err = Some(FixupError::UnresolvedTy(vid));
154 self.tcx().types.err
155 }
156 ty::Infer(ty::IntVar(vid)) => {
157 self.err = Some(FixupError::UnresolvedIntTy(vid));
158 self.tcx().types.err
159 }
160 ty::Infer(ty::FloatVar(vid)) => {
161 self.err = Some(FixupError::UnresolvedFloatTy(vid));
162 self.tcx().types.err
163 }
164 ty::Infer(_) => {
165 bug!("Unexpected type in full type resolver: {:?}", t);
166 }
167 _ => {
168 t.super_fold_with(self)
169 }
170 }
171 }
172 }
173
174 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
175 match *r {
176 ty::ReVar(rid) => self.infcx.lexical_region_resolutions
177 .borrow()
178 .as_ref()
179 .expect("region resolution not performed")
180 .resolve_var(rid),
181 _ => r,
182 }
183 }
184 }