]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
85aaf69f | 11 | //! See the Book for more information. |
1a4d82fc | 12 | |
1a4d82fc JJ |
13 | pub use self::LateBoundRegionConversionTime::*; |
14 | pub use self::RegionVariableOrigin::*; | |
15 | pub use self::SubregionOrigin::*; | |
1a4d82fc | 16 | pub use self::ValuePairs::*; |
54a0048b | 17 | pub use ty::IntVarValue; |
1a4d82fc | 18 | pub use self::freshen::TypeFreshener; |
e9174d1e | 19 | pub use self::region_inference::{GenericKind, VerifyBound}; |
1a4d82fc | 20 | |
54a0048b SL |
21 | use hir::def_id::DefId; |
22 | use hir; | |
bd371182 | 23 | use middle::free_region::FreeRegionMap; |
c1a9b12d SL |
24 | use middle::mem_categorization as mc; |
25 | use middle::mem_categorization::McResult; | |
26 | use middle::region::CodeExtent; | |
a7813a04 | 27 | use mir::tcx::LvalueTy; |
54a0048b SL |
28 | use ty::subst; |
29 | use ty::subst::Substs; | |
30 | use ty::subst::Subst; | |
31 | use ty::adjustment; | |
32 | use ty::{TyVid, IntVid, FloatVid}; | |
33 | use ty::{self, Ty, TyCtxt}; | |
34 | use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; | |
5bcae85e | 35 | use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; |
54a0048b | 36 | use ty::relate::{Relate, RelateResult, TypeRelation}; |
5bcae85e | 37 | use traits::{self, PredicateObligations, Reveal}; |
d9579d0f | 38 | use rustc_data_structures::unify::{self, UnificationTable}; |
a7813a04 | 39 | use std::cell::{Cell, RefCell, Ref, RefMut}; |
c34b1796 | 40 | use std::fmt; |
1a4d82fc | 41 | use syntax::ast; |
3157f602 XL |
42 | use errors::DiagnosticBuilder; |
43 | use syntax_pos::{self, Span, DUMMY_SP}; | |
e9174d1e | 44 | use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap}; |
1a4d82fc | 45 | |
c34b1796 | 46 | use self::combine::CombineFields; |
3157f602 | 47 | use self::higher_ranked::HrMatchResult; |
1a4d82fc | 48 | use self::region_inference::{RegionVarBindings, RegionSnapshot}; |
d9579d0f | 49 | use self::unify_key::ToType; |
1a4d82fc | 50 | |
5bcae85e SL |
51 | mod bivariate; |
52 | mod combine; | |
53 | mod equate; | |
1a4d82fc | 54 | pub mod error_reporting; |
5bcae85e | 55 | mod glb; |
1a4d82fc JJ |
56 | mod higher_ranked; |
57 | pub mod lattice; | |
5bcae85e | 58 | mod lub; |
1a4d82fc JJ |
59 | pub mod region_inference; |
60 | pub mod resolve; | |
61 | mod freshen; | |
5bcae85e | 62 | mod sub; |
1a4d82fc | 63 | pub mod type_variable; |
d9579d0f | 64 | pub mod unify_key; |
1a4d82fc | 65 | |
3157f602 | 66 | #[must_use] |
54a0048b SL |
67 | pub struct InferOk<'tcx, T> { |
68 | pub value: T, | |
69 | pub obligations: PredicateObligations<'tcx>, | |
70 | } | |
71 | pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>; | |
72 | ||
1a4d82fc | 73 | pub type Bound<T> = Option<T>; |
c34b1796 | 74 | pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" |
c1a9b12d | 75 | pub type FixupResult<T> = Result<T, FixupError>; // "fixup result" |
1a4d82fc | 76 | |
a7813a04 XL |
77 | /// A version of &ty::Tables which can be global or local. |
78 | /// Only the local version supports borrow_mut. | |
79 | #[derive(Copy, Clone)] | |
80 | pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | |
81 | Global(&'a RefCell<ty::Tables<'gcx>>), | |
82 | Local(&'a RefCell<ty::Tables<'tcx>>) | |
83 | } | |
84 | ||
85 | impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> { | |
86 | pub fn borrow(self) -> Ref<'a, ty::Tables<'tcx>> { | |
87 | match self { | |
88 | InferTables::Global(tables) => tables.borrow(), | |
89 | InferTables::Local(tables) => tables.borrow() | |
90 | } | |
91 | } | |
92 | ||
93 | pub fn borrow_mut(self) -> RefMut<'a, ty::Tables<'tcx>> { | |
94 | match self { | |
95 | InferTables::Global(_) => { | |
96 | bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking"); | |
97 | } | |
98 | InferTables::Local(tables) => tables.borrow_mut() | |
99 | } | |
100 | } | |
101 | } | |
102 | ||
103 | pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | |
104 | pub tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
1a4d82fc | 105 | |
a7813a04 | 106 | pub tables: InferTables<'a, 'gcx, 'tcx>, |
c1a9b12d | 107 | |
3157f602 XL |
108 | // Cache for projections. This cache is snapshotted along with the |
109 | // infcx. | |
110 | // | |
111 | // Public so that `traits::project` can use it. | |
112 | pub projection_cache: RefCell<traits::ProjectionCache<'tcx>>, | |
113 | ||
1a4d82fc JJ |
114 | // We instantiate UnificationTable with bounds<Ty> because the |
115 | // types that might instantiate a general type variable have an | |
116 | // order, represented by its upper and lower bounds. | |
117 | type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>, | |
118 | ||
119 | // Map from integral variable to the kind of integer it represents | |
85aaf69f | 120 | int_unification_table: RefCell<UnificationTable<ty::IntVid>>, |
1a4d82fc JJ |
121 | |
122 | // Map from floating variable to the kind of float it represents | |
85aaf69f | 123 | float_unification_table: RefCell<UnificationTable<ty::FloatVid>>, |
1a4d82fc JJ |
124 | |
125 | // For region variables. | |
a7813a04 XL |
126 | region_vars: RegionVarBindings<'a, 'gcx, 'tcx>, |
127 | ||
128 | pub parameter_environment: ty::ParameterEnvironment<'gcx>, | |
129 | ||
130 | /// Caches the results of trait selection. This cache is used | |
131 | /// for things that have to do with the parameters in scope. | |
132 | pub selection_cache: traits::SelectionCache<'tcx>, | |
c1a9b12d | 133 | |
a7813a04 XL |
134 | /// Caches the results of trait evaluation. |
135 | pub evaluation_cache: traits::EvaluationCache<'tcx>, | |
c1a9b12d | 136 | |
e9174d1e SL |
137 | // the set of predicates on which errors have been reported, to |
138 | // avoid reporting the same error twice. | |
139 | pub reported_trait_errors: RefCell<FnvHashSet<traits::TraitErrorKey<'tcx>>>, | |
140 | ||
c1a9b12d SL |
141 | // This is a temporary field used for toggling on normalization in the inference context, |
142 | // as we move towards the approach described here: | |
143 | // https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293 | |
144 | // At a point sometime in the future normalization will be done by the typing context | |
145 | // directly. | |
146 | normalize: bool, | |
147 | ||
54a0048b SL |
148 | // Sadly, the behavior of projection varies a bit depending on the |
149 | // stage of compilation. The specifics are given in the | |
5bcae85e SL |
150 | // documentation for `Reveal`. |
151 | projection_mode: Reveal, | |
54a0048b | 152 | |
a7813a04 XL |
153 | // When an error occurs, we want to avoid reporting "derived" |
154 | // errors that are due to this original failure. Normally, we | |
155 | // handle this with the `err_count_on_creation` count, which | |
156 | // basically just tracks how many errors were reported when we | |
157 | // started type-checking a fn and checks to see if any new errors | |
158 | // have been reported since then. Not great, but it works. | |
159 | // | |
160 | // However, when errors originated in other passes -- notably | |
161 | // resolve -- this heuristic breaks down. Therefore, we have this | |
162 | // auxiliary flag that one can set whenever one creates a | |
163 | // type-error that is due to an error in a prior pass. | |
164 | // | |
165 | // Don't read this flag directly, call `is_tainted_by_errors()` | |
166 | // and `set_tainted_by_errors()`. | |
167 | tainted_by_errors_flag: Cell<bool>, | |
168 | ||
169 | // Track how many errors were reported when this infcx is created. | |
170 | // If the number of errors increases, that's also a sign (line | |
171 | // `tained_by_errors`) to avoid reporting certain kinds of errors. | |
c1a9b12d | 172 | err_count_on_creation: usize, |
3157f602 XL |
173 | |
174 | // This flag is used for debugging, and is set to true if there are | |
175 | // any obligations set during the current snapshot. In that case, the | |
176 | // snapshot can't be rolled back. | |
177 | pub obligations_in_snapshot: Cell<bool>, | |
1a4d82fc JJ |
178 | } |
179 | ||
180 | /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized | |
181 | /// region that each late-bound region was replaced with. | |
a7813a04 | 182 | pub type SkolemizationMap = FnvHashMap<ty::BoundRegion, ty::Region>; |
1a4d82fc JJ |
183 | |
184 | /// Why did we require that the two types be related? | |
185 | /// | |
186 | /// See `error_reporting.rs` for more details | |
85aaf69f | 187 | #[derive(Clone, Copy, Debug)] |
1a4d82fc JJ |
188 | pub enum TypeOrigin { |
189 | // Not yet categorized in a better way | |
190 | Misc(Span), | |
191 | ||
192 | // Checking that method of impl is compatible with trait | |
193 | MethodCompatCheck(Span), | |
194 | ||
195 | // Checking that this expression can be assigned where it needs to be | |
196 | // FIXME(eddyb) #11161 is the original Expr required? | |
197 | ExprAssignable(Span), | |
198 | ||
1a4d82fc JJ |
199 | // Relating trait type parameters to those found in impl etc |
200 | RelateOutputImplTypes(Span), | |
201 | ||
202 | // Computing common supertype in the arms of a match expression | |
92a42be0 | 203 | MatchExpressionArm(Span, Span, hir::MatchSource), |
1a4d82fc JJ |
204 | |
205 | // Computing common supertype in an if expression | |
206 | IfExpression(Span), | |
207 | ||
208 | // Computing common supertype of an if expression with no else counter-part | |
209 | IfExpressionWithNoElse(Span), | |
210 | ||
211 | // Computing common supertype in a range expression | |
212 | RangeExpression(Span), | |
213 | ||
214 | // `where a == b` | |
215 | EquatePredicate(Span), | |
5bcae85e SL |
216 | |
217 | // `main` has wrong type | |
218 | MainFunctionType(Span), | |
219 | ||
220 | // `start` has wrong type | |
221 | StartFunctionType(Span), | |
222 | ||
223 | // intrinsic has wrong type | |
224 | IntrinsicType(Span), | |
225 | ||
226 | // method receiver | |
227 | MethodReceiver(Span), | |
1a4d82fc JJ |
228 | } |
229 | ||
c34b1796 | 230 | impl TypeOrigin { |
5bcae85e | 231 | fn as_failure_str(&self) -> &'static str { |
c34b1796 AL |
232 | match self { |
233 | &TypeOrigin::Misc(_) | | |
c34b1796 AL |
234 | &TypeOrigin::RelateOutputImplTypes(_) | |
235 | &TypeOrigin::ExprAssignable(_) => "mismatched types", | |
c34b1796 | 236 | &TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait", |
92a42be0 SL |
237 | &TypeOrigin::MatchExpressionArm(_, _, source) => match source { |
238 | hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types", | |
239 | _ => "match arms have incompatible types", | |
240 | }, | |
c34b1796 AL |
241 | &TypeOrigin::IfExpression(_) => "if and else have incompatible types", |
242 | &TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause", | |
243 | &TypeOrigin::RangeExpression(_) => "start and end of range have incompatible types", | |
244 | &TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied", | |
5bcae85e SL |
245 | &TypeOrigin::MainFunctionType(_) => "main function has wrong type", |
246 | &TypeOrigin::StartFunctionType(_) => "start function has wrong type", | |
247 | &TypeOrigin::IntrinsicType(_) => "intrinsic has wrong type", | |
248 | &TypeOrigin::MethodReceiver(_) => "mismatched method receiver", | |
c34b1796 AL |
249 | } |
250 | } | |
c34b1796 | 251 | |
5bcae85e SL |
252 | fn as_requirement_str(&self) -> &'static str { |
253 | match self { | |
254 | &TypeOrigin::Misc(_) => "types are compatible", | |
255 | &TypeOrigin::MethodCompatCheck(_) => "method type is compatible with trait", | |
256 | &TypeOrigin::ExprAssignable(_) => "expression is assignable", | |
257 | &TypeOrigin::RelateOutputImplTypes(_) => { | |
258 | "trait type parameters matches those specified on the impl" | |
259 | } | |
260 | &TypeOrigin::MatchExpressionArm(_, _, _) => "match arms have compatible types", | |
261 | &TypeOrigin::IfExpression(_) => "if and else have compatible types", | |
262 | &TypeOrigin::IfExpressionWithNoElse(_) => "if missing an else returns ()", | |
263 | &TypeOrigin::RangeExpression(_) => "start and end of range have compatible types", | |
264 | &TypeOrigin::EquatePredicate(_) => "equality where clause is satisfied", | |
265 | &TypeOrigin::MainFunctionType(_) => "`main` function has the correct type", | |
266 | &TypeOrigin::StartFunctionType(_) => "`start` function has the correct type", | |
267 | &TypeOrigin::IntrinsicType(_) => "intrinsic has the correct type", | |
268 | &TypeOrigin::MethodReceiver(_) => "method receiver has the correct type", | |
269 | } | |
c34b1796 AL |
270 | } |
271 | } | |
272 | ||
1a4d82fc | 273 | /// See `error_reporting.rs` for more details |
85aaf69f | 274 | #[derive(Clone, Debug)] |
1a4d82fc | 275 | pub enum ValuePairs<'tcx> { |
e9174d1e SL |
276 | Types(ExpectedFound<Ty<'tcx>>), |
277 | TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>), | |
278 | PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>), | |
1a4d82fc JJ |
279 | } |
280 | ||
281 | /// The trace designates the path through inference that we took to | |
282 | /// encounter an error or subtyping constraint. | |
283 | /// | |
284 | /// See `error_reporting.rs` for more details. | |
62682a34 | 285 | #[derive(Clone)] |
1a4d82fc JJ |
286 | pub struct TypeTrace<'tcx> { |
287 | origin: TypeOrigin, | |
288 | values: ValuePairs<'tcx>, | |
289 | } | |
290 | ||
291 | /// The origin of a `r1 <= r2` constraint. | |
292 | /// | |
293 | /// See `error_reporting.rs` for more details | |
85aaf69f | 294 | #[derive(Clone, Debug)] |
1a4d82fc JJ |
295 | pub enum SubregionOrigin<'tcx> { |
296 | // Arose from a subtyping relation | |
297 | Subtype(TypeTrace<'tcx>), | |
298 | ||
299 | // Stack-allocated closures cannot outlive innermost loop | |
300 | // or function so as to ensure we only require finite stack | |
301 | InfStackClosure(Span), | |
302 | ||
303 | // Invocation of closure must be within its lifetime | |
304 | InvokeClosure(Span), | |
305 | ||
306 | // Dereference of reference must be within its lifetime | |
307 | DerefPointer(Span), | |
308 | ||
309 | // Closure bound must not outlive captured free variables | |
310 | FreeVariable(Span, ast::NodeId), | |
311 | ||
312 | // Index into slice must be within its lifetime | |
313 | IndexSlice(Span), | |
314 | ||
315 | // When casting `&'a T` to an `&'b Trait` object, | |
316 | // relating `'a` to `'b` | |
317 | RelateObjectBound(Span), | |
318 | ||
319 | // Some type parameter was instantiated with the given type, | |
320 | // and that type must outlive some region. | |
321 | RelateParamBound(Span, Ty<'tcx>), | |
322 | ||
323 | // The given region parameter was instantiated with a region | |
324 | // that must outlive some other region. | |
325 | RelateRegionParamBound(Span), | |
326 | ||
327 | // A bound placed on type parameters that states that must outlive | |
328 | // the moment of their instantiation. | |
329 | RelateDefaultParamBound(Span, Ty<'tcx>), | |
330 | ||
331 | // Creating a pointer `b` to contents of another reference | |
332 | Reborrow(Span), | |
333 | ||
334 | // Creating a pointer `b` to contents of an upvar | |
335 | ReborrowUpvar(Span, ty::UpvarId), | |
336 | ||
e9174d1e SL |
337 | // Data with type `Ty<'tcx>` was borrowed |
338 | DataBorrowed(Ty<'tcx>, Span), | |
339 | ||
1a4d82fc JJ |
340 | // (&'a &'b T) where a >= b |
341 | ReferenceOutlivesReferent(Ty<'tcx>, Span), | |
342 | ||
e9174d1e SL |
343 | // Type or region parameters must be in scope. |
344 | ParameterInScope(ParameterOrigin, Span), | |
345 | ||
1a4d82fc JJ |
346 | // The type T of an expression E must outlive the lifetime for E. |
347 | ExprTypeIsNotInScope(Ty<'tcx>, Span), | |
348 | ||
349 | // A `ref b` whose region does not enclose the decl site | |
350 | BindingTypeIsNotValidAtDecl(Span), | |
351 | ||
352 | // Regions appearing in a method receiver must outlive method call | |
353 | CallRcvr(Span), | |
354 | ||
355 | // Regions appearing in a function argument must outlive func call | |
356 | CallArg(Span), | |
357 | ||
358 | // Region in return type of invoked fn must enclose call | |
359 | CallReturn(Span), | |
360 | ||
85aaf69f SL |
361 | // Operands must be in scope |
362 | Operand(Span), | |
363 | ||
1a4d82fc JJ |
364 | // Region resulting from a `&` expr must enclose the `&` expr |
365 | AddrOf(Span), | |
366 | ||
367 | // An auto-borrow that does not enclose the expr where it occurs | |
368 | AutoBorrow(Span), | |
85aaf69f SL |
369 | |
370 | // Region constraint arriving from destructor safety | |
371 | SafeDestructor(Span), | |
1a4d82fc JJ |
372 | } |
373 | ||
e9174d1e SL |
374 | /// Places that type/region parameters can appear. |
375 | #[derive(Clone, Copy, Debug)] | |
376 | pub enum ParameterOrigin { | |
377 | Path, // foo::bar | |
378 | MethodCall, // foo.bar() <-- parameters on impl providing bar() | |
379 | OverloadedOperator, // a + b when overloaded | |
380 | OverloadedDeref, // *a when overloaded | |
381 | } | |
382 | ||
1a4d82fc | 383 | /// Times when we replace late-bound regions with variables: |
85aaf69f | 384 | #[derive(Clone, Copy, Debug)] |
1a4d82fc JJ |
385 | pub enum LateBoundRegionConversionTime { |
386 | /// when a fn is called | |
387 | FnCall, | |
388 | ||
389 | /// when two higher-ranked types are compared | |
390 | HigherRankedType, | |
391 | ||
392 | /// when projecting an associated type | |
393 | AssocTypeProjection(ast::Name), | |
394 | } | |
395 | ||
396 | /// Reasons to create a region inference variable | |
397 | /// | |
398 | /// See `error_reporting.rs` for more details | |
85aaf69f | 399 | #[derive(Clone, Debug)] |
c34b1796 | 400 | pub enum RegionVariableOrigin { |
1a4d82fc JJ |
401 | // Region variables created for ill-categorized reasons, |
402 | // mostly indicates places in need of refactoring | |
403 | MiscVariable(Span), | |
404 | ||
405 | // Regions created by a `&P` or `[...]` pattern | |
406 | PatternRegion(Span), | |
407 | ||
408 | // Regions created by `&` operator | |
409 | AddrOfRegion(Span), | |
410 | ||
1a4d82fc JJ |
411 | // Regions created as part of an autoref of a method receiver |
412 | Autoref(Span), | |
413 | ||
414 | // Regions created as part of an automatic coercion | |
c34b1796 | 415 | Coercion(Span), |
1a4d82fc JJ |
416 | |
417 | // Region variables created as the values for early-bound regions | |
418 | EarlyBoundRegion(Span, ast::Name), | |
419 | ||
420 | // Region variables created for bound regions | |
421 | // in a function or method that is called | |
422 | LateBoundRegion(Span, ty::BoundRegion, LateBoundRegionConversionTime), | |
423 | ||
424 | UpvarRegion(ty::UpvarId, Span), | |
425 | ||
426 | BoundRegionInCoherence(ast::Name), | |
427 | } | |
428 | ||
c34b1796 | 429 | #[derive(Copy, Clone, Debug)] |
c1a9b12d SL |
430 | pub enum FixupError { |
431 | UnresolvedIntTy(IntVid), | |
432 | UnresolvedFloatTy(FloatVid), | |
433 | UnresolvedTy(TyVid) | |
1a4d82fc JJ |
434 | } |
435 | ||
a7813a04 XL |
436 | impl fmt::Display for FixupError { |
437 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
438 | use self::FixupError::*; | |
1a4d82fc | 439 | |
a7813a04 XL |
440 | match *self { |
441 | UnresolvedIntTy(_) => { | |
442 | write!(f, "cannot determine the type of this integer; \ | |
443 | add a suffix to specify the type explicitly") | |
444 | } | |
445 | UnresolvedFloatTy(_) => { | |
446 | write!(f, "cannot determine the type of this number; \ | |
447 | add a suffix to specify the type explicitly") | |
448 | } | |
449 | UnresolvedTy(_) => write!(f, "unconstrained type") | |
450 | } | |
1a4d82fc JJ |
451 | } |
452 | } | |
453 | ||
a7813a04 XL |
454 | /// Helper type of a temporary returned by tcx.infer_ctxt(...). |
455 | /// Necessary because we can't write the following bound: | |
456 | /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>). | |
457 | pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | |
458 | global_tcx: TyCtxt<'a, 'gcx, 'gcx>, | |
459 | arenas: ty::CtxtArenas<'tcx>, | |
460 | tables: Option<RefCell<ty::Tables<'tcx>>>, | |
461 | param_env: Option<ty::ParameterEnvironment<'gcx>>, | |
5bcae85e | 462 | projection_mode: Reveal, |
a7813a04 | 463 | normalize: bool |
1a4d82fc JJ |
464 | } |
465 | ||
a7813a04 XL |
466 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { |
467 | pub fn infer_ctxt(self, | |
468 | tables: Option<ty::Tables<'tcx>>, | |
469 | param_env: Option<ty::ParameterEnvironment<'gcx>>, | |
5bcae85e | 470 | projection_mode: Reveal) |
a7813a04 XL |
471 | -> InferCtxtBuilder<'a, 'gcx, 'tcx> { |
472 | InferCtxtBuilder { | |
473 | global_tcx: self, | |
474 | arenas: ty::CtxtArenas::new(), | |
475 | tables: tables.map(RefCell::new), | |
476 | param_env: param_env, | |
477 | projection_mode: projection_mode, | |
478 | normalize: false | |
479 | } | |
480 | } | |
1a4d82fc | 481 | |
5bcae85e | 482 | pub fn normalizing_infer_ctxt(self, projection_mode: Reveal) |
a7813a04 XL |
483 | -> InferCtxtBuilder<'a, 'gcx, 'tcx> { |
484 | InferCtxtBuilder { | |
485 | global_tcx: self, | |
486 | arenas: ty::CtxtArenas::new(), | |
487 | tables: None, | |
488 | param_env: None, | |
489 | projection_mode: projection_mode, | |
490 | normalize: false | |
491 | } | |
492 | } | |
1a4d82fc | 493 | |
a7813a04 XL |
494 | /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck |
495 | /// for MemCategorizationContext/ExprUseVisitor. | |
496 | /// If any inference functionality is used, ICEs will occur. | |
497 | pub fn borrowck_fake_infer_ctxt(self, param_env: ty::ParameterEnvironment<'gcx>) | |
498 | -> InferCtxt<'a, 'gcx, 'gcx> { | |
499 | InferCtxt { | |
500 | tcx: self, | |
501 | tables: InferTables::Global(&self.tables), | |
502 | type_variables: RefCell::new(type_variable::TypeVariableTable::new()), | |
503 | int_unification_table: RefCell::new(UnificationTable::new()), | |
504 | float_unification_table: RefCell::new(UnificationTable::new()), | |
505 | region_vars: RegionVarBindings::new(self), | |
506 | parameter_environment: param_env, | |
507 | selection_cache: traits::SelectionCache::new(), | |
508 | evaluation_cache: traits::EvaluationCache::new(), | |
3157f602 | 509 | projection_cache: RefCell::new(traits::ProjectionCache::new()), |
a7813a04 XL |
510 | reported_trait_errors: RefCell::new(FnvHashSet()), |
511 | normalize: false, | |
5bcae85e | 512 | projection_mode: Reveal::NotSpecializable, |
a7813a04 | 513 | tainted_by_errors_flag: Cell::new(false), |
3157f602 XL |
514 | err_count_on_creation: self.sess.err_count(), |
515 | obligations_in_snapshot: Cell::new(false), | |
a7813a04 XL |
516 | } |
517 | } | |
92a42be0 SL |
518 | } |
519 | ||
a7813a04 XL |
520 | impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { |
521 | pub fn enter<F, R>(&'tcx mut self, f: F) -> R | |
522 | where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R | |
523 | { | |
524 | let InferCtxtBuilder { | |
525 | global_tcx, | |
526 | ref arenas, | |
527 | ref tables, | |
528 | ref mut param_env, | |
529 | projection_mode, | |
530 | normalize | |
531 | } = *self; | |
532 | let tables = if let Some(ref tables) = *tables { | |
533 | InferTables::Local(tables) | |
534 | } else { | |
535 | InferTables::Global(&global_tcx.tables) | |
536 | }; | |
537 | let param_env = param_env.take().unwrap_or_else(|| { | |
538 | global_tcx.empty_parameter_environment() | |
539 | }); | |
540 | global_tcx.enter_local(arenas, |tcx| f(InferCtxt { | |
541 | tcx: tcx, | |
542 | tables: tables, | |
3157f602 | 543 | projection_cache: RefCell::new(traits::ProjectionCache::new()), |
a7813a04 XL |
544 | type_variables: RefCell::new(type_variable::TypeVariableTable::new()), |
545 | int_unification_table: RefCell::new(UnificationTable::new()), | |
546 | float_unification_table: RefCell::new(UnificationTable::new()), | |
547 | region_vars: RegionVarBindings::new(tcx), | |
548 | parameter_environment: param_env, | |
549 | selection_cache: traits::SelectionCache::new(), | |
550 | evaluation_cache: traits::EvaluationCache::new(), | |
551 | reported_trait_errors: RefCell::new(FnvHashSet()), | |
552 | normalize: normalize, | |
553 | projection_mode: projection_mode, | |
554 | tainted_by_errors_flag: Cell::new(false), | |
3157f602 XL |
555 | err_count_on_creation: tcx.sess.err_count(), |
556 | obligations_in_snapshot: Cell::new(false), | |
a7813a04 XL |
557 | })) |
558 | } | |
54a0048b SL |
559 | } |
560 | ||
a7813a04 XL |
561 | impl<T> ExpectedFound<T> { |
562 | fn new(a_is_expected: bool, a: T, b: T) -> Self { | |
563 | if a_is_expected { | |
564 | ExpectedFound {expected: a, found: b} | |
565 | } else { | |
566 | ExpectedFound {expected: b, found: a} | |
567 | } | |
54a0048b | 568 | } |
1a4d82fc JJ |
569 | } |
570 | ||
a7813a04 | 571 | impl<'tcx, T> InferOk<'tcx, T> { |
3157f602 | 572 | pub fn unit(self) -> InferOk<'tcx, ()> { |
a7813a04 | 573 | InferOk { value: (), obligations: self.obligations } |
1a4d82fc JJ |
574 | } |
575 | } | |
576 | ||
1a4d82fc JJ |
577 | #[must_use = "once you start a snapshot, you should always consume it"] |
578 | pub struct CombinedSnapshot { | |
3157f602 | 579 | projection_cache_snapshot: traits::ProjectionCacheSnapshot, |
1a4d82fc JJ |
580 | type_snapshot: type_variable::Snapshot, |
581 | int_snapshot: unify::Snapshot<ty::IntVid>, | |
582 | float_snapshot: unify::Snapshot<ty::FloatVid>, | |
583 | region_vars_snapshot: RegionSnapshot, | |
3157f602 | 584 | obligations_in_snapshot: bool, |
1a4d82fc JJ |
585 | } |
586 | ||
a7813a04 XL |
587 | /// Helper trait for shortening the lifetimes inside a |
588 | /// value for post-type-checking normalization. | |
589 | pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> { | |
590 | fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self; | |
591 | } | |
c1a9b12d | 592 | |
a7813a04 XL |
593 | macro_rules! items { ($($item:item)+) => ($($item)+) } |
594 | macro_rules! impl_trans_normalize { | |
595 | ($lt_gcx:tt, $($ty:ty),+) => { | |
596 | items!($(impl<$lt_gcx> TransNormalize<$lt_gcx> for $ty { | |
597 | fn trans_normalize<'a, 'tcx>(&self, | |
598 | infcx: &InferCtxt<'a, $lt_gcx, 'tcx>) | |
599 | -> Self { | |
600 | infcx.normalize_projections_in(self) | |
601 | } | |
602 | })+); | |
603 | } | |
604 | } | |
c1a9b12d | 605 | |
a7813a04 XL |
606 | impl_trans_normalize!('gcx, |
607 | Ty<'gcx>, | |
608 | &'gcx Substs<'gcx>, | |
609 | ty::FnSig<'gcx>, | |
a7813a04 XL |
610 | &'gcx ty::BareFnTy<'gcx>, |
611 | ty::ClosureSubsts<'gcx>, | |
612 | ty::PolyTraitRef<'gcx> | |
613 | ); | |
614 | ||
615 | impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> { | |
616 | fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self { | |
617 | match *self { | |
618 | LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx) }, | |
619 | LvalueTy::Downcast { adt_def, substs, variant_index } => { | |
620 | LvalueTy::Downcast { | |
621 | adt_def: adt_def, | |
622 | substs: substs.trans_normalize(infcx), | |
623 | variant_index: variant_index | |
624 | } | |
625 | } | |
626 | } | |
c1a9b12d | 627 | } |
a7813a04 | 628 | } |
c1a9b12d | 629 | |
a7813a04 XL |
630 | // NOTE: Callable from trans only! |
631 | impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { | |
632 | pub fn normalize_associated_type<T>(self, value: &T) -> T | |
633 | where T: TransNormalize<'tcx> | |
634 | { | |
635 | debug!("normalize_associated_type(t={:?})", value); | |
c1a9b12d | 636 | |
a7813a04 | 637 | let value = self.erase_regions(value); |
c1a9b12d | 638 | |
a7813a04 XL |
639 | if !value.has_projection_types() { |
640 | return value; | |
641 | } | |
c1a9b12d | 642 | |
5bcae85e | 643 | self.infer_ctxt(None, None, Reveal::All).enter(|infcx| { |
a7813a04 XL |
644 | value.trans_normalize(&infcx) |
645 | }) | |
c1a9b12d | 646 | } |
3157f602 XL |
647 | |
648 | pub fn normalize_associated_type_in_env<T>( | |
649 | self, value: &T, env: &'a ty::ParameterEnvironment<'tcx> | |
650 | ) -> T | |
651 | where T: TransNormalize<'tcx> | |
652 | { | |
653 | debug!("normalize_associated_type_in_env(t={:?})", value); | |
654 | ||
655 | let value = self.erase_regions(value); | |
656 | ||
657 | if !value.has_projection_types() { | |
658 | return value; | |
659 | } | |
660 | ||
5bcae85e | 661 | self.infer_ctxt(None, Some(env.clone()), Reveal::All).enter(|infcx| { |
3157f602 XL |
662 | value.trans_normalize(&infcx) |
663 | }) | |
664 | } | |
c1a9b12d SL |
665 | } |
666 | ||
a7813a04 XL |
667 | impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { |
668 | fn normalize_projections_in<T>(&self, value: &T) -> T::Lifted | |
669 | where T: TypeFoldable<'tcx> + ty::Lift<'gcx> | |
670 | { | |
671 | let mut selcx = traits::SelectionContext::new(self); | |
672 | let cause = traits::ObligationCause::dummy(); | |
673 | let traits::Normalized { value: result, obligations } = | |
674 | traits::normalize(&mut selcx, cause, value); | |
675 | ||
676 | debug!("normalize_projections_in: result={:?} obligations={:?}", | |
677 | result, obligations); | |
678 | ||
679 | let mut fulfill_cx = traits::FulfillmentContext::new(); | |
680 | ||
681 | for obligation in obligations { | |
682 | fulfill_cx.register_predicate_obligation(self, obligation); | |
c1a9b12d | 683 | } |
a7813a04 XL |
684 | |
685 | self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result) | |
c1a9b12d | 686 | } |
c1a9b12d | 687 | |
a7813a04 XL |
688 | pub fn drain_fulfillment_cx_or_panic<T>(&self, |
689 | span: Span, | |
690 | fulfill_cx: &mut traits::FulfillmentContext<'tcx>, | |
691 | result: &T) | |
692 | -> T::Lifted | |
693 | where T: TypeFoldable<'tcx> + ty::Lift<'gcx> | |
694 | { | |
3157f602 XL |
695 | debug!("drain_fulfillment_cx_or_panic()"); |
696 | ||
a7813a04 XL |
697 | let when = "resolving bounds after type-checking"; |
698 | let v = match self.drain_fulfillment_cx(fulfill_cx, result) { | |
699 | Ok(v) => v, | |
700 | Err(errors) => { | |
701 | span_bug!(span, "Encountered errors `{:?}` {}", errors, when); | |
702 | } | |
703 | }; | |
704 | ||
705 | match self.tcx.lift_to_global(&v) { | |
706 | Some(v) => v, | |
707 | None => { | |
708 | span_bug!(span, "Uninferred types/regions in `{:?}` {}", v, when); | |
709 | } | |
c1a9b12d SL |
710 | } |
711 | } | |
712 | ||
a7813a04 XL |
713 | /// Finishes processes any obligations that remain in the fulfillment |
714 | /// context, and then "freshens" and returns `result`. This is | |
715 | /// primarily used during normalization and other cases where | |
716 | /// processing the obligations in `fulfill_cx` may cause type | |
717 | /// inference variables that appear in `result` to be unified, and | |
718 | /// hence we need to process those obligations to get the complete | |
719 | /// picture of the type. | |
720 | pub fn drain_fulfillment_cx<T>(&self, | |
721 | fulfill_cx: &mut traits::FulfillmentContext<'tcx>, | |
722 | result: &T) | |
723 | -> Result<T,Vec<traits::FulfillmentError<'tcx>>> | |
724 | where T : TypeFoldable<'tcx> | |
725 | { | |
726 | debug!("drain_fulfillment_cx(result={:?})", | |
727 | result); | |
c1a9b12d | 728 | |
a7813a04 XL |
729 | // In principle, we only need to do this so long as `result` |
730 | // contains unbound type parameters. It could be a slight | |
731 | // optimization to stop iterating early. | |
732 | fulfill_cx.select_all_or_error(self)?; | |
733 | ||
734 | let result = self.resolve_type_vars_if_possible(result); | |
735 | Ok(self.tcx.erase_regions(&result)) | |
54a0048b | 736 | } |
54a0048b | 737 | |
5bcae85e | 738 | pub fn projection_mode(&self) -> Reveal { |
54a0048b SL |
739 | self.projection_mode |
740 | } | |
741 | ||
1a4d82fc JJ |
742 | pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T { |
743 | t.fold_with(&mut self.freshener()) | |
744 | } | |
745 | ||
746 | pub fn type_var_diverges(&'a self, ty: Ty) -> bool { | |
747 | match ty.sty { | |
62682a34 | 748 | ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid), |
1a4d82fc JJ |
749 | _ => false |
750 | } | |
751 | } | |
752 | ||
a7813a04 | 753 | pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'gcx, 'tcx> { |
1a4d82fc JJ |
754 | freshen::TypeFreshener::new(self) |
755 | } | |
756 | ||
757 | pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric { | |
54a0048b SL |
758 | use ty::error::UnconstrainedNumeric::Neither; |
759 | use ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; | |
1a4d82fc | 760 | match ty.sty { |
62682a34 | 761 | ty::TyInfer(ty::IntVar(vid)) => { |
c34b1796 AL |
762 | if self.int_unification_table.borrow_mut().has_value(vid) { |
763 | Neither | |
764 | } else { | |
765 | UnconstrainedInt | |
1a4d82fc JJ |
766 | } |
767 | }, | |
62682a34 | 768 | ty::TyInfer(ty::FloatVar(vid)) => { |
c34b1796 AL |
769 | if self.float_unification_table.borrow_mut().has_value(vid) { |
770 | Neither | |
771 | } else { | |
772 | UnconstrainedFloat | |
1a4d82fc JJ |
773 | } |
774 | }, | |
775 | _ => Neither, | |
776 | } | |
777 | } | |
778 | ||
c1a9b12d SL |
779 | /// Returns a type variable's default fallback if any exists. A default |
780 | /// must be attached to the variable when created, if it is created | |
781 | /// without a default, this will return None. | |
782 | /// | |
783 | /// This code does not apply to integral or floating point variables, | |
784 | /// only to use declared defaults. | |
785 | /// | |
786 | /// See `new_ty_var_with_default` to create a type variable with a default. | |
787 | /// See `type_variable::Default` for details about what a default entails. | |
788 | pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> { | |
789 | match ty.sty { | |
790 | ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid), | |
791 | _ => None | |
792 | } | |
793 | } | |
794 | ||
795 | pub fn unsolved_variables(&self) -> Vec<ty::Ty<'tcx>> { | |
796 | let mut variables = Vec::new(); | |
797 | ||
798 | let unbound_ty_vars = self.type_variables | |
54a0048b | 799 | .borrow_mut() |
c1a9b12d SL |
800 | .unsolved_variables() |
801 | .into_iter() | |
802 | .map(|t| self.tcx.mk_var(t)); | |
803 | ||
804 | let unbound_int_vars = self.int_unification_table | |
805 | .borrow_mut() | |
806 | .unsolved_variables() | |
807 | .into_iter() | |
808 | .map(|v| self.tcx.mk_int_var(v)); | |
809 | ||
810 | let unbound_float_vars = self.float_unification_table | |
811 | .borrow_mut() | |
812 | .unsolved_variables() | |
813 | .into_iter() | |
814 | .map(|v| self.tcx.mk_float_var(v)); | |
815 | ||
816 | variables.extend(unbound_ty_vars); | |
817 | variables.extend(unbound_int_vars); | |
818 | variables.extend(unbound_float_vars); | |
819 | ||
820 | return variables; | |
821 | } | |
822 | ||
5bcae85e | 823 | fn combine_fields(&'a self, trace: TypeTrace<'tcx>) |
a7813a04 | 824 | -> CombineFields<'a, 'gcx, 'tcx> { |
54a0048b SL |
825 | CombineFields { |
826 | infcx: self, | |
54a0048b SL |
827 | trace: trace, |
828 | cause: None, | |
829 | obligations: PredicateObligations::new(), | |
830 | } | |
1a4d82fc JJ |
831 | } |
832 | ||
54a0048b SL |
833 | pub fn equate<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T) |
834 | -> InferResult<'tcx, T> | |
a7813a04 | 835 | where T: Relate<'tcx> |
c34b1796 | 836 | { |
5bcae85e SL |
837 | let mut fields = self.combine_fields(trace); |
838 | let result = fields.equate(a_is_expected).relate(a, b); | |
839 | result.map(move |t| InferOk { value: t, obligations: fields.obligations }) | |
c34b1796 AL |
840 | } |
841 | ||
54a0048b SL |
842 | pub fn sub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T) |
843 | -> InferResult<'tcx, T> | |
a7813a04 | 844 | where T: Relate<'tcx> |
c34b1796 | 845 | { |
5bcae85e SL |
846 | let mut fields = self.combine_fields(trace); |
847 | let result = fields.sub(a_is_expected).relate(a, b); | |
848 | result.map(move |t| InferOk { value: t, obligations: fields.obligations }) | |
1a4d82fc JJ |
849 | } |
850 | ||
54a0048b SL |
851 | pub fn lub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T) |
852 | -> InferResult<'tcx, T> | |
a7813a04 | 853 | where T: Relate<'tcx> |
c34b1796 | 854 | { |
5bcae85e SL |
855 | let mut fields = self.combine_fields(trace); |
856 | let result = fields.lub(a_is_expected).relate(a, b); | |
857 | result.map(move |t| InferOk { value: t, obligations: fields.obligations }) | |
1a4d82fc JJ |
858 | } |
859 | ||
54a0048b SL |
860 | pub fn glb<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T) |
861 | -> InferResult<'tcx, T> | |
a7813a04 | 862 | where T: Relate<'tcx> |
c34b1796 | 863 | { |
5bcae85e SL |
864 | let mut fields = self.combine_fields(trace); |
865 | let result = fields.glb(a_is_expected).relate(a, b); | |
866 | result.map(move |t| InferOk { value: t, obligations: fields.obligations }) | |
1a4d82fc JJ |
867 | } |
868 | ||
869 | fn start_snapshot(&self) -> CombinedSnapshot { | |
3157f602 XL |
870 | debug!("start_snapshot()"); |
871 | ||
872 | let obligations_in_snapshot = self.obligations_in_snapshot.get(); | |
873 | self.obligations_in_snapshot.set(false); | |
874 | ||
1a4d82fc | 875 | CombinedSnapshot { |
3157f602 | 876 | projection_cache_snapshot: self.projection_cache.borrow_mut().snapshot(), |
1a4d82fc JJ |
877 | type_snapshot: self.type_variables.borrow_mut().snapshot(), |
878 | int_snapshot: self.int_unification_table.borrow_mut().snapshot(), | |
879 | float_snapshot: self.float_unification_table.borrow_mut().snapshot(), | |
880 | region_vars_snapshot: self.region_vars.start_snapshot(), | |
3157f602 | 881 | obligations_in_snapshot: obligations_in_snapshot, |
1a4d82fc JJ |
882 | } |
883 | } | |
884 | ||
c1a9b12d SL |
885 | fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot) { |
886 | debug!("rollback_to(cause={})", cause); | |
3157f602 XL |
887 | let CombinedSnapshot { projection_cache_snapshot, |
888 | type_snapshot, | |
1a4d82fc JJ |
889 | int_snapshot, |
890 | float_snapshot, | |
3157f602 XL |
891 | region_vars_snapshot, |
892 | obligations_in_snapshot } = snapshot; | |
1a4d82fc | 893 | |
3157f602 XL |
894 | assert!(!self.obligations_in_snapshot.get()); |
895 | self.obligations_in_snapshot.set(obligations_in_snapshot); | |
896 | ||
897 | self.projection_cache | |
898 | .borrow_mut() | |
899 | .rollback_to(projection_cache_snapshot); | |
1a4d82fc JJ |
900 | self.type_variables |
901 | .borrow_mut() | |
902 | .rollback_to(type_snapshot); | |
903 | self.int_unification_table | |
904 | .borrow_mut() | |
905 | .rollback_to(int_snapshot); | |
906 | self.float_unification_table | |
907 | .borrow_mut() | |
908 | .rollback_to(float_snapshot); | |
909 | self.region_vars | |
910 | .rollback_to(region_vars_snapshot); | |
911 | } | |
912 | ||
913 | fn commit_from(&self, snapshot: CombinedSnapshot) { | |
3157f602 XL |
914 | debug!("commit_from()"); |
915 | let CombinedSnapshot { projection_cache_snapshot, | |
916 | type_snapshot, | |
1a4d82fc JJ |
917 | int_snapshot, |
918 | float_snapshot, | |
3157f602 XL |
919 | region_vars_snapshot, |
920 | obligations_in_snapshot } = snapshot; | |
921 | ||
922 | self.obligations_in_snapshot.set(obligations_in_snapshot); | |
1a4d82fc | 923 | |
3157f602 XL |
924 | self.projection_cache |
925 | .borrow_mut() | |
926 | .commit(projection_cache_snapshot); | |
1a4d82fc JJ |
927 | self.type_variables |
928 | .borrow_mut() | |
929 | .commit(type_snapshot); | |
930 | self.int_unification_table | |
931 | .borrow_mut() | |
932 | .commit(int_snapshot); | |
933 | self.float_unification_table | |
934 | .borrow_mut() | |
935 | .commit(float_snapshot); | |
936 | self.region_vars | |
937 | .commit(region_vars_snapshot); | |
938 | } | |
939 | ||
940 | /// Execute `f` and commit the bindings | |
941 | pub fn commit_unconditionally<R, F>(&self, f: F) -> R where | |
942 | F: FnOnce() -> R, | |
943 | { | |
944 | debug!("commit()"); | |
945 | let snapshot = self.start_snapshot(); | |
946 | let r = f(); | |
947 | self.commit_from(snapshot); | |
948 | r | |
949 | } | |
950 | ||
c34b1796 | 951 | /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)` |
1a4d82fc | 952 | pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where |
c34b1796 | 953 | F: FnOnce(&CombinedSnapshot) -> Result<T, E> |
1a4d82fc | 954 | { |
c34b1796 AL |
955 | debug!("commit_if_ok()"); |
956 | let snapshot = self.start_snapshot(); | |
957 | let r = f(&snapshot); | |
958 | debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); | |
959 | match r { | |
960 | Ok(_) => { self.commit_from(snapshot); } | |
c1a9b12d | 961 | Err(_) => { self.rollback_to("commit_if_ok -- error", snapshot); } |
c34b1796 AL |
962 | } |
963 | r | |
1a4d82fc JJ |
964 | } |
965 | ||
a7813a04 XL |
966 | // Execute `f` in a snapshot, and commit the bindings it creates |
967 | pub fn in_snapshot<T, F>(&self, f: F) -> T where | |
968 | F: FnOnce(&CombinedSnapshot) -> T | |
969 | { | |
970 | debug!("in_snapshot()"); | |
971 | let snapshot = self.start_snapshot(); | |
972 | let r = f(&snapshot); | |
973 | self.commit_from(snapshot); | |
974 | r | |
975 | } | |
976 | ||
85aaf69f SL |
977 | /// Execute `f` and commit only the region bindings if successful. |
978 | /// The function f must be very careful not to leak any non-region | |
979 | /// variables that get created. | |
980 | pub fn commit_regions_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where | |
981 | F: FnOnce() -> Result<T, E> | |
982 | { | |
983 | debug!("commit_regions_if_ok()"); | |
3157f602 XL |
984 | let CombinedSnapshot { projection_cache_snapshot, |
985 | type_snapshot, | |
85aaf69f SL |
986 | int_snapshot, |
987 | float_snapshot, | |
3157f602 XL |
988 | region_vars_snapshot, |
989 | obligations_in_snapshot } = self.start_snapshot(); | |
85aaf69f | 990 | |
c34b1796 | 991 | let r = self.commit_if_ok(|_| f()); |
85aaf69f | 992 | |
c1a9b12d SL |
993 | debug!("commit_regions_if_ok: rolling back everything but regions"); |
994 | ||
3157f602 XL |
995 | assert!(!self.obligations_in_snapshot.get()); |
996 | self.obligations_in_snapshot.set(obligations_in_snapshot); | |
997 | ||
85aaf69f SL |
998 | // Roll back any non-region bindings - they should be resolved |
999 | // inside `f`, with, e.g. `resolve_type_vars_if_possible`. | |
3157f602 XL |
1000 | self.projection_cache |
1001 | .borrow_mut() | |
1002 | .rollback_to(projection_cache_snapshot); | |
85aaf69f SL |
1003 | self.type_variables |
1004 | .borrow_mut() | |
1005 | .rollback_to(type_snapshot); | |
1006 | self.int_unification_table | |
1007 | .borrow_mut() | |
1008 | .rollback_to(int_snapshot); | |
1009 | self.float_unification_table | |
1010 | .borrow_mut() | |
1011 | .rollback_to(float_snapshot); | |
1012 | ||
1013 | // Commit region vars that may escape through resolved types. | |
1014 | self.region_vars | |
1015 | .commit(region_vars_snapshot); | |
1016 | ||
1017 | r | |
1018 | } | |
1019 | ||
1a4d82fc JJ |
1020 | /// Execute `f` then unroll any bindings it creates |
1021 | pub fn probe<R, F>(&self, f: F) -> R where | |
1022 | F: FnOnce(&CombinedSnapshot) -> R, | |
1023 | { | |
1024 | debug!("probe()"); | |
1025 | let snapshot = self.start_snapshot(); | |
1026 | let r = f(&snapshot); | |
c1a9b12d | 1027 | self.rollback_to("probe", snapshot); |
1a4d82fc JJ |
1028 | r |
1029 | } | |
1030 | ||
1031 | pub fn add_given(&self, | |
1032 | sub: ty::FreeRegion, | |
1033 | sup: ty::RegionVid) | |
1034 | { | |
1035 | self.region_vars.add_given(sub, sup); | |
1036 | } | |
1037 | ||
1038 | pub fn sub_types(&self, | |
1039 | a_is_expected: bool, | |
1040 | origin: TypeOrigin, | |
1041 | a: Ty<'tcx>, | |
1042 | b: Ty<'tcx>) | |
54a0048b | 1043 | -> InferResult<'tcx, ()> |
1a4d82fc | 1044 | { |
62682a34 | 1045 | debug!("sub_types({:?} <: {:?})", a, b); |
c34b1796 | 1046 | self.commit_if_ok(|_| { |
85aaf69f | 1047 | let trace = TypeTrace::types(origin, a_is_expected, a, b); |
54a0048b | 1048 | self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit()) |
1a4d82fc JJ |
1049 | }) |
1050 | } | |
1051 | ||
a7813a04 XL |
1052 | pub fn can_sub_types(&self, |
1053 | a: Ty<'tcx>, | |
1054 | b: Ty<'tcx>) | |
1055 | -> UnitResult<'tcx> | |
1056 | { | |
1057 | self.probe(|_| { | |
3157f602 | 1058 | let origin = TypeOrigin::Misc(syntax_pos::DUMMY_SP); |
a7813a04 XL |
1059 | let trace = TypeTrace::types(origin, true, a, b); |
1060 | self.sub(true, trace, &a, &b).map(|_| ()) | |
1061 | }) | |
1062 | } | |
1063 | ||
1a4d82fc JJ |
1064 | pub fn eq_types(&self, |
1065 | a_is_expected: bool, | |
1066 | origin: TypeOrigin, | |
1067 | a: Ty<'tcx>, | |
1068 | b: Ty<'tcx>) | |
54a0048b | 1069 | -> InferResult<'tcx, ()> |
1a4d82fc | 1070 | { |
c34b1796 | 1071 | self.commit_if_ok(|_| { |
85aaf69f | 1072 | let trace = TypeTrace::types(origin, a_is_expected, a, b); |
54a0048b | 1073 | self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit()) |
1a4d82fc JJ |
1074 | }) |
1075 | } | |
1076 | ||
92a42be0 | 1077 | pub fn eq_trait_refs(&self, |
1a4d82fc JJ |
1078 | a_is_expected: bool, |
1079 | origin: TypeOrigin, | |
d9579d0f AL |
1080 | a: ty::TraitRef<'tcx>, |
1081 | b: ty::TraitRef<'tcx>) | |
54a0048b | 1082 | -> InferResult<'tcx, ()> |
1a4d82fc | 1083 | { |
a7813a04 | 1084 | debug!("eq_trait_refs({:?} = {:?})", a, b); |
c34b1796 | 1085 | self.commit_if_ok(|_| { |
1a4d82fc JJ |
1086 | let trace = TypeTrace { |
1087 | origin: origin, | |
a7813a04 | 1088 | values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)) |
1a4d82fc | 1089 | }; |
54a0048b | 1090 | self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit()) |
1a4d82fc JJ |
1091 | }) |
1092 | } | |
1093 | ||
a7813a04 XL |
1094 | pub fn eq_impl_headers(&self, |
1095 | a_is_expected: bool, | |
1096 | origin: TypeOrigin, | |
1097 | a: &ty::ImplHeader<'tcx>, | |
1098 | b: &ty::ImplHeader<'tcx>) | |
1099 | -> InferResult<'tcx, ()> | |
1100 | { | |
1101 | debug!("eq_impl_header({:?} = {:?})", a, b); | |
1102 | match (a.trait_ref, b.trait_ref) { | |
1103 | (Some(a_ref), Some(b_ref)) => self.eq_trait_refs(a_is_expected, origin, a_ref, b_ref), | |
1104 | (None, None) => self.eq_types(a_is_expected, origin, a.self_ty, b.self_ty), | |
1105 | _ => bug!("mk_eq_impl_headers given mismatched impl kinds"), | |
1106 | } | |
1107 | } | |
1108 | ||
1a4d82fc JJ |
1109 | pub fn sub_poly_trait_refs(&self, |
1110 | a_is_expected: bool, | |
1111 | origin: TypeOrigin, | |
1112 | a: ty::PolyTraitRef<'tcx>, | |
1113 | b: ty::PolyTraitRef<'tcx>) | |
54a0048b | 1114 | -> InferResult<'tcx, ()> |
1a4d82fc | 1115 | { |
a7813a04 | 1116 | debug!("sub_poly_trait_refs({:?} <: {:?})", a, b); |
c34b1796 | 1117 | self.commit_if_ok(|_| { |
1a4d82fc JJ |
1118 | let trace = TypeTrace { |
1119 | origin: origin, | |
a7813a04 | 1120 | values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b)) |
1a4d82fc | 1121 | }; |
54a0048b | 1122 | self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit()) |
1a4d82fc JJ |
1123 | }) |
1124 | } | |
1125 | ||
a7813a04 XL |
1126 | pub fn sub_regions(&self, |
1127 | origin: SubregionOrigin<'tcx>, | |
1128 | a: ty::Region, | |
1129 | b: ty::Region) { | |
1130 | debug!("sub_regions({:?} <: {:?})", a, b); | |
1131 | self.region_vars.make_subregion(origin, a, b); | |
1a4d82fc JJ |
1132 | } |
1133 | ||
1134 | pub fn equality_predicate(&self, | |
1135 | span: Span, | |
1136 | predicate: &ty::PolyEquatePredicate<'tcx>) | |
54a0048b SL |
1137 | -> InferResult<'tcx, ()> |
1138 | { | |
c34b1796 | 1139 | self.commit_if_ok(|snapshot| { |
1a4d82fc JJ |
1140 | let (ty::EquatePredicate(a, b), skol_map) = |
1141 | self.skolemize_late_bound_regions(predicate, snapshot); | |
92a42be0 | 1142 | let origin = TypeOrigin::EquatePredicate(span); |
a7813a04 | 1143 | let eqty_ok = self.eq_types(false, origin, a, b)?; |
3157f602 XL |
1144 | self.leak_check(false, span, &skol_map, snapshot)?; |
1145 | self.pop_skolemized(skol_map, snapshot); | |
1146 | Ok(eqty_ok.unit()) | |
1a4d82fc JJ |
1147 | }) |
1148 | } | |
1149 | ||
1150 | pub fn region_outlives_predicate(&self, | |
1151 | span: Span, | |
1152 | predicate: &ty::PolyRegionOutlivesPredicate) | |
54a0048b SL |
1153 | -> UnitResult<'tcx> |
1154 | { | |
c34b1796 | 1155 | self.commit_if_ok(|snapshot| { |
1a4d82fc JJ |
1156 | let (ty::OutlivesPredicate(r_a, r_b), skol_map) = |
1157 | self.skolemize_late_bound_regions(predicate, snapshot); | |
1158 | let origin = RelateRegionParamBound(span); | |
a7813a04 | 1159 | self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` |
3157f602 XL |
1160 | self.leak_check(false, span, &skol_map, snapshot)?; |
1161 | Ok(self.pop_skolemized(skol_map, snapshot)) | |
1a4d82fc JJ |
1162 | }) |
1163 | } | |
1164 | ||
1165 | pub fn next_ty_var_id(&self, diverging: bool) -> TyVid { | |
1166 | self.type_variables | |
1167 | .borrow_mut() | |
c1a9b12d | 1168 | .new_var(diverging, None) |
1a4d82fc JJ |
1169 | } |
1170 | ||
1171 | pub fn next_ty_var(&self) -> Ty<'tcx> { | |
c1a9b12d SL |
1172 | self.tcx.mk_var(self.next_ty_var_id(false)) |
1173 | } | |
1174 | ||
1175 | pub fn next_ty_var_with_default(&self, | |
1176 | default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> { | |
1177 | let ty_var_id = self.type_variables | |
1178 | .borrow_mut() | |
1179 | .new_var(false, default); | |
1180 | ||
1181 | self.tcx.mk_var(ty_var_id) | |
1a4d82fc JJ |
1182 | } |
1183 | ||
1184 | pub fn next_diverging_ty_var(&self) -> Ty<'tcx> { | |
c1a9b12d | 1185 | self.tcx.mk_var(self.next_ty_var_id(true)) |
1a4d82fc JJ |
1186 | } |
1187 | ||
c34b1796 | 1188 | pub fn next_ty_vars(&self, n: usize) -> Vec<Ty<'tcx>> { |
85aaf69f | 1189 | (0..n).map(|_i| self.next_ty_var()).collect() |
1a4d82fc JJ |
1190 | } |
1191 | ||
1192 | pub fn next_int_var_id(&self) -> IntVid { | |
1193 | self.int_unification_table | |
1194 | .borrow_mut() | |
1195 | .new_key(None) | |
1196 | } | |
1197 | ||
1198 | pub fn next_float_var_id(&self) -> FloatVid { | |
1199 | self.float_unification_table | |
1200 | .borrow_mut() | |
1201 | .new_key(None) | |
1202 | } | |
1203 | ||
c34b1796 | 1204 | pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region { |
e9174d1e | 1205 | ty::ReVar(self.region_vars.new_region_var(origin)) |
1a4d82fc JJ |
1206 | } |
1207 | ||
1208 | pub fn region_vars_for_defs(&self, | |
1209 | span: Span, | |
1210 | defs: &[ty::RegionParameterDef]) | |
1211 | -> Vec<ty::Region> { | |
1212 | defs.iter() | |
1213 | .map(|d| self.next_region_var(EarlyBoundRegion(span, d.name))) | |
1214 | .collect() | |
1215 | } | |
1216 | ||
c1a9b12d SL |
1217 | // We have to take `&mut Substs` in order to provide the correct substitutions for defaults |
1218 | // along the way, for this reason we don't return them. | |
1219 | pub fn type_vars_for_defs(&self, | |
1220 | span: Span, | |
1221 | space: subst::ParamSpace, | |
1222 | substs: &mut Substs<'tcx>, | |
1223 | defs: &[ty::TypeParameterDef<'tcx>]) { | |
1224 | ||
c1a9b12d SL |
1225 | for def in defs.iter() { |
1226 | let default = def.default.map(|default| { | |
1227 | type_variable::Default { | |
1228 | ty: default.subst_spanned(self.tcx, substs, Some(span)), | |
1229 | origin_span: span, | |
1230 | def_id: def.default_def_id | |
1231 | } | |
1232 | }); | |
1233 | ||
1234 | let ty_var = self.next_ty_var_with_default(default); | |
1235 | substs.types.push(space, ty_var); | |
c1a9b12d SL |
1236 | } |
1237 | } | |
1238 | ||
1a4d82fc JJ |
1239 | /// Given a set of generics defined on a type or impl, returns a substitution mapping each |
1240 | /// type/region parameter to a fresh inference variable. | |
1241 | pub fn fresh_substs_for_generics(&self, | |
1242 | span: Span, | |
1243 | generics: &ty::Generics<'tcx>) | |
a7813a04 | 1244 | -> &'tcx subst::Substs<'tcx> |
1a4d82fc | 1245 | { |
c1a9b12d SL |
1246 | let type_params = subst::VecPerParamSpace::empty(); |
1247 | ||
1a4d82fc JJ |
1248 | let region_params = |
1249 | generics.regions.map( | |
1250 | |d| self.next_region_var(EarlyBoundRegion(span, d.name))); | |
c1a9b12d SL |
1251 | |
1252 | let mut substs = subst::Substs::new(type_params, region_params); | |
1253 | ||
1254 | for space in subst::ParamSpace::all().iter() { | |
1255 | self.type_vars_for_defs( | |
1256 | span, | |
1257 | *space, | |
1258 | &mut substs, | |
1259 | generics.types.get_slice(*space)); | |
1260 | } | |
1261 | ||
a7813a04 | 1262 | self.tcx.mk_substs(substs) |
1a4d82fc JJ |
1263 | } |
1264 | ||
1265 | /// Given a set of generics defined on a trait, returns a substitution mapping each output | |
1266 | /// type/region parameter to a fresh inference variable, and mapping the self type to | |
1267 | /// `self_ty`. | |
1268 | pub fn fresh_substs_for_trait(&self, | |
1269 | span: Span, | |
1270 | generics: &ty::Generics<'tcx>, | |
1271 | self_ty: Ty<'tcx>) | |
1272 | -> subst::Substs<'tcx> | |
1273 | { | |
1274 | ||
1275 | assert!(generics.types.len(subst::SelfSpace) == 1); | |
1276 | assert!(generics.types.len(subst::FnSpace) == 0); | |
1277 | assert!(generics.regions.len(subst::SelfSpace) == 0); | |
1278 | assert!(generics.regions.len(subst::FnSpace) == 0); | |
1279 | ||
c1a9b12d | 1280 | let type_params = Vec::new(); |
1a4d82fc JJ |
1281 | |
1282 | let region_param_defs = generics.regions.get_slice(subst::TypeSpace); | |
1283 | let regions = self.region_vars_for_defs(span, region_param_defs); | |
1284 | ||
c1a9b12d SL |
1285 | let mut substs = subst::Substs::new_trait(type_params, regions, self_ty); |
1286 | ||
1287 | let type_parameter_defs = generics.types.get_slice(subst::TypeSpace); | |
1288 | self.type_vars_for_defs(span, subst::TypeSpace, &mut substs, type_parameter_defs); | |
1289 | ||
1290 | return substs; | |
1a4d82fc JJ |
1291 | } |
1292 | ||
1293 | pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region { | |
1294 | self.region_vars.new_bound(debruijn) | |
1295 | } | |
1296 | ||
c1a9b12d SL |
1297 | /// Apply `adjustment` to the type of `expr` |
1298 | pub fn adjust_expr_ty(&self, | |
e9174d1e SL |
1299 | expr: &hir::Expr, |
1300 | adjustment: Option<&adjustment::AutoAdjustment<'tcx>>) | |
c1a9b12d SL |
1301 | -> Ty<'tcx> |
1302 | { | |
1303 | let raw_ty = self.expr_ty(expr); | |
1304 | let raw_ty = self.shallow_resolve(raw_ty); | |
1305 | let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty); | |
1306 | raw_ty.adjust(self.tcx, | |
1307 | expr.span, | |
1308 | expr.id, | |
1309 | adjustment, | |
1310 | |method_call| self.tables | |
1311 | .borrow() | |
1312 | .method_map | |
1313 | .get(&method_call) | |
1314 | .map(|method| resolve_ty(method.ty))) | |
1315 | } | |
1316 | ||
a7813a04 XL |
1317 | /// True if errors have been reported since this infcx was |
1318 | /// created. This is sometimes used as a heuristic to skip | |
1319 | /// reporting errors that often occur as a result of earlier | |
1320 | /// errors, but where it's hard to be 100% sure (e.g., unresolved | |
1321 | /// inference variables, regionck errors). | |
1322 | pub fn is_tainted_by_errors(&self) -> bool { | |
1323 | debug!("is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ | |
1324 | tainted_by_errors_flag={})", | |
1325 | self.tcx.sess.err_count(), | |
1326 | self.err_count_on_creation, | |
1327 | self.tainted_by_errors_flag.get()); | |
1328 | ||
1329 | if self.tcx.sess.err_count() > self.err_count_on_creation { | |
1330 | return true; // errors reported since this infcx was made | |
1331 | } | |
1332 | self.tainted_by_errors_flag.get() | |
1333 | } | |
1334 | ||
1335 | /// Set the "tainted by errors" flag to true. We call this when we | |
1336 | /// observe an error from a prior pass. | |
1337 | pub fn set_tainted_by_errors(&self) { | |
1338 | debug!("set_tainted_by_errors()"); | |
1339 | self.tainted_by_errors_flag.set(true) | |
7453a54e SL |
1340 | } |
1341 | ||
c1a9b12d SL |
1342 | pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> { |
1343 | match self.tables.borrow().node_types.get(&id) { | |
1344 | Some(&t) => t, | |
1345 | // FIXME | |
a7813a04 | 1346 | None if self.is_tainted_by_errors() => |
c1a9b12d SL |
1347 | self.tcx.types.err, |
1348 | None => { | |
54a0048b SL |
1349 | bug!("no type for node {}: {} in fcx", |
1350 | id, self.tcx.map.node_to_string(id)); | |
c1a9b12d SL |
1351 | } |
1352 | } | |
1353 | } | |
1354 | ||
e9174d1e | 1355 | pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> { |
c1a9b12d SL |
1356 | match self.tables.borrow().node_types.get(&ex.id) { |
1357 | Some(&t) => t, | |
1358 | None => { | |
54a0048b | 1359 | bug!("no type for expr in fcx"); |
c1a9b12d SL |
1360 | } |
1361 | } | |
1362 | } | |
1363 | ||
bd371182 AL |
1364 | pub fn resolve_regions_and_report_errors(&self, |
1365 | free_regions: &FreeRegionMap, | |
1366 | subject_node_id: ast::NodeId) { | |
1367 | let errors = self.region_vars.resolve_regions(free_regions, subject_node_id); | |
a7813a04 | 1368 | if !self.is_tainted_by_errors() { |
7453a54e SL |
1369 | // As a heuristic, just skip reporting region errors |
1370 | // altogether if other errors have been reported while | |
1371 | // this infcx was in use. This is totally hokey but | |
1372 | // otherwise we have a hard time separating legit region | |
1373 | // errors from silly ones. | |
1374 | self.report_region_errors(&errors); // see error_reporting.rs | |
1375 | } | |
1a4d82fc JJ |
1376 | } |
1377 | ||
1378 | pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { | |
62682a34 | 1379 | self.resolve_type_vars_if_possible(&t).to_string() |
1a4d82fc JJ |
1380 | } |
1381 | ||
1382 | pub fn tys_to_string(&self, ts: &[Ty<'tcx>]) -> String { | |
1383 | let tstrs: Vec<String> = ts.iter().map(|t| self.ty_to_string(*t)).collect(); | |
c1a9b12d | 1384 | format!("({})", tstrs.join(", ")) |
1a4d82fc JJ |
1385 | } |
1386 | ||
d9579d0f | 1387 | pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String { |
62682a34 | 1388 | self.resolve_type_vars_if_possible(t).to_string() |
1a4d82fc JJ |
1389 | } |
1390 | ||
1391 | pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> { | |
1392 | match typ.sty { | |
62682a34 | 1393 | ty::TyInfer(ty::TyVar(v)) => { |
1a4d82fc JJ |
1394 | // Not entirely obvious: if `typ` is a type variable, |
1395 | // it can be resolved to an int/float variable, which | |
1396 | // can then be recursively resolved, hence the | |
1397 | // recursion. Note though that we prevent type | |
1398 | // variables from unifying to other type variables | |
1399 | // directly (though they may be embedded | |
1400 | // structurally), and we prevent cycles in any case, | |
1401 | // so this recursion should always be of very limited | |
1402 | // depth. | |
54a0048b | 1403 | self.type_variables.borrow_mut() |
1a4d82fc JJ |
1404 | .probe(v) |
1405 | .map(|t| self.shallow_resolve(t)) | |
1406 | .unwrap_or(typ) | |
1407 | } | |
1408 | ||
62682a34 | 1409 | ty::TyInfer(ty::IntVar(v)) => { |
c34b1796 AL |
1410 | self.int_unification_table |
1411 | .borrow_mut() | |
1412 | .probe(v) | |
1413 | .map(|v| v.to_type(self.tcx)) | |
1a4d82fc JJ |
1414 | .unwrap_or(typ) |
1415 | } | |
1416 | ||
62682a34 | 1417 | ty::TyInfer(ty::FloatVar(v)) => { |
c34b1796 AL |
1418 | self.float_unification_table |
1419 | .borrow_mut() | |
1420 | .probe(v) | |
1421 | .map(|v| v.to_type(self.tcx)) | |
1a4d82fc JJ |
1422 | .unwrap_or(typ) |
1423 | } | |
1424 | ||
1425 | _ => { | |
1426 | typ | |
1427 | } | |
1428 | } | |
1429 | } | |
1430 | ||
e9174d1e | 1431 | pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T |
9cc50fc6 | 1432 | where T: TypeFoldable<'tcx> |
e9174d1e | 1433 | { |
1a4d82fc JJ |
1434 | /*! |
1435 | * Where possible, replaces type/int/float variables in | |
1436 | * `value` with their final value. Note that region variables | |
1437 | * are unaffected. If a type variable has not been unified, it | |
1438 | * is left as is. This is an idempotent operation that does | |
1439 | * not affect inference state in any way and so you can do it | |
1440 | * at will. | |
1441 | */ | |
1442 | ||
e9174d1e SL |
1443 | if !value.needs_infer() { |
1444 | return value.clone(); // avoid duplicated subst-folding | |
1445 | } | |
1a4d82fc JJ |
1446 | let mut r = resolve::OpportunisticTypeResolver::new(self); |
1447 | value.fold_with(&mut r) | |
1448 | } | |
1449 | ||
9cc50fc6 SL |
1450 | pub fn resolve_type_and_region_vars_if_possible<T>(&self, value: &T) -> T |
1451 | where T: TypeFoldable<'tcx> | |
1452 | { | |
1453 | let mut r = resolve::OpportunisticTypeAndRegionResolver::new(self); | |
1454 | value.fold_with(&mut r) | |
1455 | } | |
1456 | ||
c1a9b12d SL |
1457 | /// Resolves all type variables in `t` and then, if any were left |
1458 | /// unresolved, substitutes an error type. This is used after the | |
1459 | /// main checking when doing a second pass before writeback. The | |
1460 | /// justification is that writeback will produce an error for | |
1461 | /// these unconstrained type variables. | |
1462 | fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> { | |
1463 | let ty = self.resolve_type_vars_if_possible(t); | |
1464 | if ty.references_error() || ty.is_ty_var() { | |
1465 | debug!("resolve_type_vars_or_error: error from {:?}", ty); | |
1466 | Err(()) | |
1467 | } else { | |
1468 | Ok(ty) | |
1469 | } | |
1470 | } | |
1471 | ||
1472 | pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> { | |
1a4d82fc JJ |
1473 | /*! |
1474 | * Attempts to resolve all type/region variables in | |
1475 | * `value`. Region inference must have been run already (e.g., | |
1476 | * by calling `resolve_regions_and_report_errors`). If some | |
1477 | * variable was never unified, an `Err` results. | |
1478 | * | |
1479 | * This method is idempotent, but it not typically not invoked | |
1480 | * except during the writeback phase. | |
1481 | */ | |
1482 | ||
1483 | resolve::fully_resolve(self, value) | |
1484 | } | |
1485 | ||
1486 | // [Note-Type-error-reporting] | |
62682a34 | 1487 | // An invariant is that anytime the expected or actual type is TyError (the special |
1a4d82fc JJ |
1488 | // error type, meaning that an error occurred when typechecking this expression), |
1489 | // this is a derived error. The error cascaded from another error (that was already | |
1490 | // reported), so it's not useful to display it to the user. | |
5bcae85e | 1491 | // The following methods implement this logic. |
62682a34 | 1492 | // They check if either the actual or expected type is TyError, and don't print the error |
1a4d82fc | 1493 | // in this case. The typechecker should only ever report type errors involving mismatched |
5bcae85e | 1494 | // types using one of these methods, and should not call span_err directly for such |
1a4d82fc | 1495 | // errors. |
1a4d82fc JJ |
1496 | |
1497 | pub fn type_error_message<M>(&self, | |
1498 | sp: Span, | |
1499 | mk_msg: M, | |
5bcae85e | 1500 | actual_ty: Ty<'tcx>) |
9cc50fc6 SL |
1501 | where M: FnOnce(String) -> String, |
1502 | { | |
5bcae85e | 1503 | self.type_error_struct(sp, mk_msg, actual_ty).emit(); |
9cc50fc6 SL |
1504 | } |
1505 | ||
5bcae85e | 1506 | // FIXME: this results in errors without an error code. Deprecate? |
9cc50fc6 SL |
1507 | pub fn type_error_struct<M>(&self, |
1508 | sp: Span, | |
1509 | mk_msg: M, | |
5bcae85e | 1510 | actual_ty: Ty<'tcx>) |
9cc50fc6 SL |
1511 | -> DiagnosticBuilder<'tcx> |
1512 | where M: FnOnce(String) -> String, | |
5bcae85e SL |
1513 | { |
1514 | self.type_error_struct_with_diag(sp, |actual_ty| { | |
1515 | self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty)) | |
1516 | }, actual_ty) | |
1517 | } | |
1518 | ||
1519 | pub fn type_error_struct_with_diag<M>(&self, | |
1520 | sp: Span, | |
1521 | mk_diag: M, | |
1522 | actual_ty: Ty<'tcx>) | |
1523 | -> DiagnosticBuilder<'tcx> | |
1524 | where M: FnOnce(String) -> DiagnosticBuilder<'tcx>, | |
1a4d82fc JJ |
1525 | { |
1526 | let actual_ty = self.resolve_type_vars_if_possible(&actual_ty); | |
5bcae85e | 1527 | debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); |
1a4d82fc | 1528 | |
62682a34 | 1529 | // Don't report an error if actual type is TyError. |
c1a9b12d | 1530 | if actual_ty.references_error() { |
9cc50fc6 | 1531 | return self.tcx.sess.diagnostic().struct_dummy(); |
1a4d82fc JJ |
1532 | } |
1533 | ||
5bcae85e | 1534 | mk_diag(self.ty_to_string(actual_ty)) |
1a4d82fc JJ |
1535 | } |
1536 | ||
1537 | pub fn report_mismatched_types(&self, | |
54a0048b | 1538 | origin: TypeOrigin, |
1a4d82fc JJ |
1539 | expected: Ty<'tcx>, |
1540 | actual: Ty<'tcx>, | |
54a0048b | 1541 | err: TypeError<'tcx>) { |
1a4d82fc | 1542 | let trace = TypeTrace { |
54a0048b | 1543 | origin: origin, |
e9174d1e | 1544 | values: Types(ExpectedFound { |
1a4d82fc JJ |
1545 | expected: expected, |
1546 | found: actual | |
1547 | }) | |
1548 | }; | |
54a0048b | 1549 | self.report_and_explain_type_error(trace, &err).emit(); |
1a4d82fc JJ |
1550 | } |
1551 | ||
c1a9b12d SL |
1552 | pub fn report_conflicting_default_types(&self, |
1553 | span: Span, | |
1554 | expected: type_variable::Default<'tcx>, | |
1555 | actual: type_variable::Default<'tcx>) { | |
1556 | let trace = TypeTrace { | |
92a42be0 | 1557 | origin: TypeOrigin::Misc(span), |
e9174d1e | 1558 | values: Types(ExpectedFound { |
c1a9b12d SL |
1559 | expected: expected.ty, |
1560 | found: actual.ty | |
1561 | }) | |
1562 | }; | |
1563 | ||
54a0048b SL |
1564 | self.report_and_explain_type_error( |
1565 | trace, | |
e9174d1e | 1566 | &TypeError::TyParamDefaultMismatch(ExpectedFound { |
c1a9b12d SL |
1567 | expected: expected, |
1568 | found: actual | |
54a0048b SL |
1569 | })) |
1570 | .emit(); | |
c1a9b12d SL |
1571 | } |
1572 | ||
1a4d82fc JJ |
1573 | pub fn replace_late_bound_regions_with_fresh_var<T>( |
1574 | &self, | |
1575 | span: Span, | |
1576 | lbrct: LateBoundRegionConversionTime, | |
1577 | value: &ty::Binder<T>) | |
1578 | -> (T, FnvHashMap<ty::BoundRegion,ty::Region>) | |
62682a34 | 1579 | where T : TypeFoldable<'tcx> |
1a4d82fc | 1580 | { |
e9174d1e | 1581 | self.tcx.replace_late_bound_regions( |
1a4d82fc JJ |
1582 | value, |
1583 | |br| self.next_region_var(LateBoundRegion(span, br, lbrct))) | |
1584 | } | |
1585 | ||
3157f602 XL |
1586 | /// Given a higher-ranked projection predicate like: |
1587 | /// | |
1588 | /// for<'a> <T as Fn<&'a u32>>::Output = &'a u32 | |
1589 | /// | |
1590 | /// and a target trait-ref like: | |
1591 | /// | |
1592 | /// <T as Fn<&'x u32>> | |
1593 | /// | |
1594 | /// find a substitution `S` for the higher-ranked regions (here, | |
1595 | /// `['a => 'x]`) such that the predicate matches the trait-ref, | |
1596 | /// and then return the value (here, `&'a u32`) but with the | |
1597 | /// substitution applied (hence, `&'x u32`). | |
1598 | /// | |
1599 | /// See `higher_ranked_match` in `higher_ranked/mod.rs` for more | |
1600 | /// details. | |
1601 | pub fn match_poly_projection_predicate(&self, | |
1602 | origin: TypeOrigin, | |
1603 | match_a: ty::PolyProjectionPredicate<'tcx>, | |
1604 | match_b: ty::TraitRef<'tcx>) | |
1605 | -> InferResult<'tcx, HrMatchResult<Ty<'tcx>>> | |
1606 | { | |
1607 | let span = origin.span(); | |
1608 | let match_trait_ref = match_a.skip_binder().projection_ty.trait_ref; | |
1609 | let trace = TypeTrace { | |
1610 | origin: origin, | |
1611 | values: TraitRefs(ExpectedFound::new(true, match_trait_ref, match_b)) | |
1612 | }; | |
1613 | ||
1614 | let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty)); | |
5bcae85e SL |
1615 | let mut combine = self.combine_fields(trace); |
1616 | let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?; | |
3157f602 XL |
1617 | Ok(InferOk { value: result, obligations: combine.obligations }) |
1618 | } | |
1619 | ||
1a4d82fc JJ |
1620 | /// See `verify_generic_bound` method in `region_inference` |
1621 | pub fn verify_generic_bound(&self, | |
1622 | origin: SubregionOrigin<'tcx>, | |
1623 | kind: GenericKind<'tcx>, | |
1624 | a: ty::Region, | |
e9174d1e | 1625 | bound: VerifyBound) { |
62682a34 SL |
1626 | debug!("verify_generic_bound({:?}, {:?} <: {:?})", |
1627 | kind, | |
1628 | a, | |
e9174d1e | 1629 | bound); |
1a4d82fc | 1630 | |
e9174d1e | 1631 | self.region_vars.verify_generic_bound(origin, kind, a, bound); |
1a4d82fc JJ |
1632 | } |
1633 | ||
a7813a04 XL |
1634 | pub fn can_equate<T>(&self, a: &T, b: &T) -> UnitResult<'tcx> |
1635 | where T: Relate<'tcx> + fmt::Debug | |
1a4d82fc | 1636 | { |
62682a34 | 1637 | debug!("can_equate({:?}, {:?})", a, b); |
1a4d82fc JJ |
1638 | self.probe(|_| { |
1639 | // Gin up a dummy trace, since this won't be committed | |
1640 | // anyhow. We should make this typetrace stuff more | |
1641 | // generic so we don't have to do anything quite this | |
1642 | // terrible. | |
a7813a04 | 1643 | self.equate(true, TypeTrace::dummy(self.tcx), a, b) |
c34b1796 | 1644 | }).map(|_| ()) |
1a4d82fc | 1645 | } |
c1a9b12d SL |
1646 | |
1647 | pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> { | |
1648 | let ty = self.node_type(id); | |
1649 | self.resolve_type_vars_or_error(&ty) | |
1650 | } | |
1651 | ||
e9174d1e | 1652 | pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> { |
c1a9b12d SL |
1653 | let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id)); |
1654 | self.resolve_type_vars_or_error(&ty) | |
1655 | } | |
1656 | ||
1657 | pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { | |
1658 | let ty = self.resolve_type_vars_if_possible(&ty); | |
a7813a04 XL |
1659 | if let Some(ty) = self.tcx.lift_to_global(&ty) { |
1660 | // Even if the type may have no inference variables, during | |
1661 | // type-checking closure types are in local tables only. | |
1662 | let local_closures = match self.tables { | |
1663 | InferTables::Local(_) => ty.has_closure_types(), | |
1664 | InferTables::Global(_) => false | |
1665 | }; | |
1666 | if !local_closures { | |
1667 | return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span); | |
1668 | } | |
e9174d1e | 1669 | } |
a7813a04 XL |
1670 | |
1671 | // this can get called from typeck (by euv), and moves_by_default | |
1672 | // rightly refuses to work with inference variables, but | |
1673 | // moves_by_default has a cache, which we want to use in other | |
1674 | // cases. | |
1675 | !traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span) | |
c1a9b12d SL |
1676 | } |
1677 | ||
1678 | pub fn node_method_ty(&self, method_call: ty::MethodCall) | |
1679 | -> Option<Ty<'tcx>> { | |
1680 | self.tables | |
1681 | .borrow() | |
1682 | .method_map | |
1683 | .get(&method_call) | |
1684 | .map(|method| method.ty) | |
1685 | .map(|ty| self.resolve_type_vars_if_possible(&ty)) | |
1686 | } | |
1687 | ||
1688 | pub fn node_method_id(&self, method_call: ty::MethodCall) | |
e9174d1e | 1689 | -> Option<DefId> { |
c1a9b12d SL |
1690 | self.tables |
1691 | .borrow() | |
1692 | .method_map | |
1693 | .get(&method_call) | |
1694 | .map(|method| method.def_id) | |
1695 | } | |
1696 | ||
e9174d1e | 1697 | pub fn adjustments(&self) -> Ref<NodeMap<adjustment::AutoAdjustment<'tcx>>> { |
c1a9b12d | 1698 | fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) |
e9174d1e | 1699 | -> &'a NodeMap<adjustment::AutoAdjustment<'tcx>> { |
c1a9b12d SL |
1700 | &tables.adjustments |
1701 | } | |
1702 | ||
1703 | Ref::map(self.tables.borrow(), project_adjustments) | |
1704 | } | |
1705 | ||
1706 | pub fn is_method_call(&self, id: ast::NodeId) -> bool { | |
1707 | self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) | |
1708 | } | |
1709 | ||
1710 | pub fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> { | |
1711 | self.tcx.region_maps.temporary_scope(rvalue_id) | |
1712 | } | |
1713 | ||
1714 | pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { | |
1715 | self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() | |
1716 | } | |
1717 | ||
a7813a04 | 1718 | pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> { |
c1a9b12d SL |
1719 | &self.parameter_environment |
1720 | } | |
1721 | ||
1722 | pub fn closure_kind(&self, | |
e9174d1e | 1723 | def_id: DefId) |
c1a9b12d SL |
1724 | -> Option<ty::ClosureKind> |
1725 | { | |
b039eaaf SL |
1726 | if def_id.is_local() { |
1727 | self.tables.borrow().closure_kinds.get(&def_id).cloned() | |
1728 | } else { | |
1729 | // During typeck, ALL closures are local. But afterwards, | |
1730 | // during trans, we see closure ids from other traits. | |
1731 | // That may require loading the closure data out of the | |
1732 | // cstore. | |
a7813a04 | 1733 | Some(self.tcx.closure_kind(def_id)) |
b039eaaf | 1734 | } |
c1a9b12d SL |
1735 | } |
1736 | ||
1737 | pub fn closure_type(&self, | |
e9174d1e | 1738 | def_id: DefId, |
a7813a04 | 1739 | substs: ty::ClosureSubsts<'tcx>) |
c1a9b12d SL |
1740 | -> ty::ClosureTy<'tcx> |
1741 | { | |
a7813a04 XL |
1742 | if let InferTables::Local(tables) = self.tables { |
1743 | if let Some(ty) = tables.borrow().closure_tys.get(&def_id) { | |
1744 | return ty.subst(self.tcx, substs.func_substs); | |
1745 | } | |
1746 | } | |
c1a9b12d | 1747 | |
a7813a04 | 1748 | let closure_ty = self.tcx.closure_type(def_id, substs); |
c1a9b12d | 1749 | if self.normalize { |
a7813a04 XL |
1750 | let closure_ty = self.tcx.erase_regions(&closure_ty); |
1751 | ||
1752 | if !closure_ty.has_projection_types() { | |
1753 | return closure_ty; | |
1754 | } | |
1755 | ||
1756 | self.normalize_projections_in(&closure_ty) | |
c1a9b12d SL |
1757 | } else { |
1758 | closure_ty | |
1759 | } | |
1760 | } | |
1a4d82fc JJ |
1761 | } |
1762 | ||
a7813a04 | 1763 | impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> { |
1a4d82fc JJ |
1764 | pub fn span(&self) -> Span { |
1765 | self.origin.span() | |
1766 | } | |
1767 | ||
85aaf69f SL |
1768 | pub fn types(origin: TypeOrigin, |
1769 | a_is_expected: bool, | |
1770 | a: Ty<'tcx>, | |
1771 | b: Ty<'tcx>) | |
1772 | -> TypeTrace<'tcx> { | |
1773 | TypeTrace { | |
1774 | origin: origin, | |
a7813a04 | 1775 | values: Types(ExpectedFound::new(a_is_expected, a, b)) |
85aaf69f SL |
1776 | } |
1777 | } | |
1778 | ||
a7813a04 | 1779 | pub fn dummy(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> TypeTrace<'tcx> { |
1a4d82fc | 1780 | TypeTrace { |
3157f602 | 1781 | origin: TypeOrigin::Misc(syntax_pos::DUMMY_SP), |
e9174d1e | 1782 | values: Types(ExpectedFound { |
1a4d82fc JJ |
1783 | expected: tcx.types.err, |
1784 | found: tcx.types.err, | |
1785 | }) | |
1786 | } | |
1787 | } | |
1788 | } | |
1789 | ||
62682a34 SL |
1790 | impl<'tcx> fmt::Debug for TypeTrace<'tcx> { |
1791 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
1792 | write!(f, "TypeTrace({:?})", self.origin) | |
1a4d82fc JJ |
1793 | } |
1794 | } | |
1795 | ||
1796 | impl TypeOrigin { | |
1797 | pub fn span(&self) -> Span { | |
1798 | match *self { | |
92a42be0 SL |
1799 | TypeOrigin::MethodCompatCheck(span) => span, |
1800 | TypeOrigin::ExprAssignable(span) => span, | |
1801 | TypeOrigin::Misc(span) => span, | |
92a42be0 SL |
1802 | TypeOrigin::RelateOutputImplTypes(span) => span, |
1803 | TypeOrigin::MatchExpressionArm(match_span, _, _) => match_span, | |
1804 | TypeOrigin::IfExpression(span) => span, | |
1805 | TypeOrigin::IfExpressionWithNoElse(span) => span, | |
1806 | TypeOrigin::RangeExpression(span) => span, | |
1807 | TypeOrigin::EquatePredicate(span) => span, | |
5bcae85e SL |
1808 | TypeOrigin::MainFunctionType(span) => span, |
1809 | TypeOrigin::StartFunctionType(span) => span, | |
1810 | TypeOrigin::IntrinsicType(span) => span, | |
1811 | TypeOrigin::MethodReceiver(span) => span, | |
1a4d82fc JJ |
1812 | } |
1813 | } | |
1814 | } | |
1815 | ||
1a4d82fc JJ |
1816 | impl<'tcx> SubregionOrigin<'tcx> { |
1817 | pub fn span(&self) -> Span { | |
1818 | match *self { | |
1819 | Subtype(ref a) => a.span(), | |
1820 | InfStackClosure(a) => a, | |
1821 | InvokeClosure(a) => a, | |
1822 | DerefPointer(a) => a, | |
1823 | FreeVariable(a, _) => a, | |
1824 | IndexSlice(a) => a, | |
1825 | RelateObjectBound(a) => a, | |
1826 | RelateParamBound(a, _) => a, | |
1827 | RelateRegionParamBound(a) => a, | |
1828 | RelateDefaultParamBound(a, _) => a, | |
1829 | Reborrow(a) => a, | |
1830 | ReborrowUpvar(a, _) => a, | |
e9174d1e | 1831 | DataBorrowed(_, a) => a, |
1a4d82fc | 1832 | ReferenceOutlivesReferent(_, a) => a, |
e9174d1e | 1833 | ParameterInScope(_, a) => a, |
1a4d82fc JJ |
1834 | ExprTypeIsNotInScope(_, a) => a, |
1835 | BindingTypeIsNotValidAtDecl(a) => a, | |
1836 | CallRcvr(a) => a, | |
1837 | CallArg(a) => a, | |
1838 | CallReturn(a) => a, | |
85aaf69f | 1839 | Operand(a) => a, |
1a4d82fc JJ |
1840 | AddrOf(a) => a, |
1841 | AutoBorrow(a) => a, | |
85aaf69f | 1842 | SafeDestructor(a) => a, |
1a4d82fc JJ |
1843 | } |
1844 | } | |
1845 | } | |
1846 | ||
c34b1796 | 1847 | impl RegionVariableOrigin { |
1a4d82fc JJ |
1848 | pub fn span(&self) -> Span { |
1849 | match *self { | |
1850 | MiscVariable(a) => a, | |
1851 | PatternRegion(a) => a, | |
1852 | AddrOfRegion(a) => a, | |
1a4d82fc | 1853 | Autoref(a) => a, |
c34b1796 | 1854 | Coercion(a) => a, |
1a4d82fc JJ |
1855 | EarlyBoundRegion(a, _) => a, |
1856 | LateBoundRegion(a, _, _) => a, | |
3157f602 | 1857 | BoundRegionInCoherence(_) => syntax_pos::DUMMY_SP, |
1a4d82fc JJ |
1858 | UpvarRegion(_, a) => a |
1859 | } | |
1860 | } | |
1861 | } | |
5bcae85e SL |
1862 | |
1863 | impl<'tcx> TypeFoldable<'tcx> for TypeOrigin { | |
1864 | fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { | |
1865 | self.clone() | |
1866 | } | |
1867 | ||
1868 | fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool { | |
1869 | false | |
1870 | } | |
1871 | } | |
1872 | ||
1873 | impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> { | |
1874 | fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { | |
1875 | match *self { | |
1876 | ValuePairs::Types(ref ef) => { | |
1877 | ValuePairs::Types(ef.fold_with(folder)) | |
1878 | } | |
1879 | ValuePairs::TraitRefs(ref ef) => { | |
1880 | ValuePairs::TraitRefs(ef.fold_with(folder)) | |
1881 | } | |
1882 | ValuePairs::PolyTraitRefs(ref ef) => { | |
1883 | ValuePairs::PolyTraitRefs(ef.fold_with(folder)) | |
1884 | } | |
1885 | } | |
1886 | } | |
1887 | ||
1888 | fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { | |
1889 | match *self { | |
1890 | ValuePairs::Types(ref ef) => ef.visit_with(visitor), | |
1891 | ValuePairs::TraitRefs(ref ef) => ef.visit_with(visitor), | |
1892 | ValuePairs::PolyTraitRefs(ref ef) => ef.visit_with(visitor), | |
1893 | } | |
1894 | } | |
1895 | } | |
1896 | ||
1897 | impl<'tcx> TypeFoldable<'tcx> for TypeTrace<'tcx> { | |
1898 | fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { | |
1899 | TypeTrace { | |
1900 | origin: self.origin.fold_with(folder), | |
1901 | values: self.values.fold_with(folder) | |
1902 | } | |
1903 | } | |
1904 | ||
1905 | fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { | |
1906 | self.origin.visit_with(visitor) || self.values.visit_with(visitor) | |
1907 | } | |
1908 | } |