]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/resolve.rs
Rollup merge of #60287 - Zoxc:the-arena-variances_of, r=eddyb
[rust.git] / src / librustc / infer / resolve.rs
1 use super::{InferCtxt, FixupError, FixupResult, Span, type_variable::TypeVariableOrigin};
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 a type searching for
81 /// type variables that don't yet have a value. The first unresolved type is stored.
82 /// 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     /// Used to find the type parameter name and location for error reporting.
88     pub first_unresolved: Option<(Ty<'tcx>,Option<Span>)>,
89 }
90
91 impl<'a, 'gcx, 'tcx> UnresolvedTypeFinder<'a, 'gcx, 'tcx> {
92     pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
93         UnresolvedTypeFinder { infcx, first_unresolved: None }
94     }
95 }
96
97 impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx> {
98     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
99         let t = self.infcx.shallow_resolve(t);
100         if t.has_infer_types() {
101             if let ty::Infer(infer_ty) = t.sty {
102                 // Since we called `shallow_resolve` above, this must
103                 // be an (as yet...) unresolved inference variable.
104                 let ty_var_span =
105                 if let ty::TyVar(ty_vid) = infer_ty {
106                     let ty_vars = self.infcx.type_variables.borrow();
107                     if let TypeVariableOrigin::TypeParameterDefinition(span, _name)
108                         = *ty_vars.var_origin(ty_vid)
109                     {
110                         Some(span)
111                     } else {
112                         None
113                     }
114                 } else {
115                     None
116                 };
117                 self.first_unresolved = Some((t, ty_var_span));
118                 true  // Halt visiting.
119             } else {
120                 // Otherwise, visit its contents.
121                 t.super_visit_with(self)
122             }
123         } else {
124             // All type variables in inference types must already be resolved,
125             // - no need to visit the contents, continue visiting.
126             false
127         }
128     }
129 }
130
131
132 ///////////////////////////////////////////////////////////////////////////
133 // FULL TYPE RESOLUTION
134
135 /// Full type resolution replaces all type and region variables with
136 /// their concrete results. If any variable cannot be replaced (never unified, etc)
137 /// then an `Err` result is returned.
138 pub fn fully_resolve<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
139                                         value: &T) -> FixupResult<T>
140     where T : TypeFoldable<'tcx>
141 {
142     let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
143     let result = value.fold_with(&mut full_resolver);
144     match full_resolver.err {
145         None => Ok(result),
146         Some(e) => Err(e),
147     }
148 }
149
150 // N.B. This type is not public because the protocol around checking the
151 // `err` field is not enforcable otherwise.
152 struct FullTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
153     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
154     err: Option<FixupError>,
155 }
156
157 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> {
158     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
159         self.infcx.tcx
160     }
161
162     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
163         if !t.needs_infer() && !ty::keep_local(&t) {
164             t // micro-optimize -- if there is nothing in this type that this fold affects...
165               // ^ we need to have the `keep_local` check to un-default
166               // defaulted tuples.
167         } else {
168             let t = self.infcx.shallow_resolve(t);
169             match t.sty {
170                 ty::Infer(ty::TyVar(vid)) => {
171                     self.err = Some(FixupError::UnresolvedTy(vid));
172                     self.tcx().types.err
173                 }
174                 ty::Infer(ty::IntVar(vid)) => {
175                     self.err = Some(FixupError::UnresolvedIntTy(vid));
176                     self.tcx().types.err
177                 }
178                 ty::Infer(ty::FloatVar(vid)) => {
179                     self.err = Some(FixupError::UnresolvedFloatTy(vid));
180                     self.tcx().types.err
181                 }
182                 ty::Infer(_) => {
183                     bug!("Unexpected type in full type resolver: {:?}", t);
184                 }
185                 _ => {
186                     t.super_fold_with(self)
187                 }
188             }
189         }
190     }
191
192     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
193         match *r {
194             ty::ReVar(rid) => self.infcx.lexical_region_resolutions
195                                         .borrow()
196                                         .as_ref()
197                                         .expect("region resolution not performed")
198                                         .resolve_var(rid),
199             _ => r,
200         }
201     }
202 }