]>
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::*; | |
16 | pub use self::TypeOrigin::*; | |
17 | pub use self::ValuePairs::*; | |
1a4d82fc JJ |
18 | pub use middle::ty::IntVarValue; |
19 | pub use self::freshen::TypeFreshener; | |
e9174d1e | 20 | pub use self::region_inference::{GenericKind, VerifyBound}; |
1a4d82fc | 21 | |
e9174d1e SL |
22 | use middle::def_id::DefId; |
23 | use rustc_front::hir; | |
bd371182 | 24 | use middle::free_region::FreeRegionMap; |
c1a9b12d SL |
25 | use middle::mem_categorization as mc; |
26 | use middle::mem_categorization::McResult; | |
27 | use middle::region::CodeExtent; | |
1a4d82fc JJ |
28 | use middle::subst; |
29 | use middle::subst::Substs; | |
c1a9b12d SL |
30 | use middle::subst::Subst; |
31 | use middle::traits::{self, FulfillmentContext, Normalized, | |
32 | SelectionContext, ObligationCause}; | |
e9174d1e SL |
33 | use middle::ty::adjustment; |
34 | use middle::ty::{TyVid, IntVid, FloatVid, RegionVid}; | |
35 | use middle::ty::{self, Ty, HasTypeFlags}; | |
36 | use middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; | |
37 | use middle::ty::fold::{TypeFolder, TypeFoldable}; | |
38 | use middle::ty::relate::{Relate, RelateResult, TypeRelation}; | |
d9579d0f | 39 | use rustc_data_structures::unify::{self, UnificationTable}; |
c1a9b12d | 40 | use std::cell::{RefCell, Ref}; |
c34b1796 | 41 | use std::fmt; |
e9174d1e | 42 | use std::rc::Rc; |
1a4d82fc JJ |
43 | use syntax::ast; |
44 | use syntax::codemap; | |
c1a9b12d | 45 | use syntax::codemap::{Span, DUMMY_SP}; |
e9174d1e | 46 | use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap}; |
1a4d82fc | 47 | |
c34b1796 | 48 | use self::combine::CombineFields; |
1a4d82fc | 49 | use self::region_inference::{RegionVarBindings, RegionSnapshot}; |
1a4d82fc | 50 | use self::error_reporting::ErrorReporting; |
d9579d0f | 51 | use self::unify_key::ToType; |
1a4d82fc | 52 | |
85aaf69f | 53 | pub mod bivariate; |
1a4d82fc | 54 | pub mod combine; |
1a4d82fc JJ |
55 | pub mod equate; |
56 | pub mod error_reporting; | |
57 | pub mod glb; | |
58 | mod higher_ranked; | |
59 | pub mod lattice; | |
60 | pub mod lub; | |
61 | pub mod region_inference; | |
62 | pub mod resolve; | |
63 | mod freshen; | |
64 | pub mod sub; | |
65 | pub mod type_variable; | |
d9579d0f | 66 | pub mod unify_key; |
1a4d82fc JJ |
67 | |
68 | pub type Bound<T> = Option<T>; | |
c34b1796 | 69 | pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" |
c1a9b12d | 70 | pub type FixupResult<T> = Result<T, FixupError>; // "fixup result" |
1a4d82fc JJ |
71 | |
72 | pub struct InferCtxt<'a, 'tcx: 'a> { | |
73 | pub tcx: &'a ty::ctxt<'tcx>, | |
74 | ||
c1a9b12d SL |
75 | pub tables: &'a RefCell<ty::Tables<'tcx>>, |
76 | ||
1a4d82fc JJ |
77 | // We instantiate UnificationTable with bounds<Ty> because the |
78 | // types that might instantiate a general type variable have an | |
79 | // order, represented by its upper and lower bounds. | |
80 | type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>, | |
81 | ||
82 | // Map from integral variable to the kind of integer it represents | |
85aaf69f | 83 | int_unification_table: RefCell<UnificationTable<ty::IntVid>>, |
1a4d82fc JJ |
84 | |
85 | // Map from floating variable to the kind of float it represents | |
85aaf69f | 86 | float_unification_table: RefCell<UnificationTable<ty::FloatVid>>, |
1a4d82fc JJ |
87 | |
88 | // For region variables. | |
85aaf69f | 89 | region_vars: RegionVarBindings<'a, 'tcx>, |
c1a9b12d SL |
90 | |
91 | pub parameter_environment: ty::ParameterEnvironment<'a, 'tcx>, | |
92 | ||
93 | pub fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>, | |
94 | ||
e9174d1e SL |
95 | // the set of predicates on which errors have been reported, to |
96 | // avoid reporting the same error twice. | |
97 | pub reported_trait_errors: RefCell<FnvHashSet<traits::TraitErrorKey<'tcx>>>, | |
98 | ||
c1a9b12d SL |
99 | // This is a temporary field used for toggling on normalization in the inference context, |
100 | // as we move towards the approach described here: | |
101 | // https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293 | |
102 | // At a point sometime in the future normalization will be done by the typing context | |
103 | // directly. | |
104 | normalize: bool, | |
105 | ||
106 | err_count_on_creation: usize, | |
1a4d82fc JJ |
107 | } |
108 | ||
109 | /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized | |
110 | /// region that each late-bound region was replaced with. | |
111 | pub type SkolemizationMap = FnvHashMap<ty::BoundRegion,ty::Region>; | |
112 | ||
113 | /// Why did we require that the two types be related? | |
114 | /// | |
115 | /// See `error_reporting.rs` for more details | |
85aaf69f | 116 | #[derive(Clone, Copy, Debug)] |
1a4d82fc JJ |
117 | pub enum TypeOrigin { |
118 | // Not yet categorized in a better way | |
119 | Misc(Span), | |
120 | ||
121 | // Checking that method of impl is compatible with trait | |
122 | MethodCompatCheck(Span), | |
123 | ||
124 | // Checking that this expression can be assigned where it needs to be | |
125 | // FIXME(eddyb) #11161 is the original Expr required? | |
126 | ExprAssignable(Span), | |
127 | ||
128 | // Relating trait refs when resolving vtables | |
129 | RelateTraitRefs(Span), | |
130 | ||
131 | // Relating self types when resolving vtables | |
132 | RelateSelfType(Span), | |
133 | ||
134 | // Relating trait type parameters to those found in impl etc | |
135 | RelateOutputImplTypes(Span), | |
136 | ||
137 | // Computing common supertype in the arms of a match expression | |
138 | MatchExpressionArm(Span, Span), | |
139 | ||
140 | // Computing common supertype in an if expression | |
141 | IfExpression(Span), | |
142 | ||
143 | // Computing common supertype of an if expression with no else counter-part | |
144 | IfExpressionWithNoElse(Span), | |
145 | ||
146 | // Computing common supertype in a range expression | |
147 | RangeExpression(Span), | |
148 | ||
149 | // `where a == b` | |
150 | EquatePredicate(Span), | |
151 | } | |
152 | ||
c34b1796 AL |
153 | impl TypeOrigin { |
154 | fn as_str(&self) -> &'static str { | |
155 | match self { | |
156 | &TypeOrigin::Misc(_) | | |
157 | &TypeOrigin::RelateSelfType(_) | | |
158 | &TypeOrigin::RelateOutputImplTypes(_) | | |
159 | &TypeOrigin::ExprAssignable(_) => "mismatched types", | |
160 | &TypeOrigin::RelateTraitRefs(_) => "mismatched traits", | |
161 | &TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait", | |
162 | &TypeOrigin::MatchExpressionArm(_, _) => "match arms have incompatible types", | |
163 | &TypeOrigin::IfExpression(_) => "if and else have incompatible types", | |
164 | &TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause", | |
165 | &TypeOrigin::RangeExpression(_) => "start and end of range have incompatible types", | |
166 | &TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied", | |
167 | } | |
168 | } | |
169 | } | |
170 | ||
171 | impl fmt::Display for TypeOrigin { | |
172 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error> { | |
173 | fmt::Display::fmt(self.as_str(), f) | |
174 | } | |
175 | } | |
176 | ||
1a4d82fc | 177 | /// See `error_reporting.rs` for more details |
85aaf69f | 178 | #[derive(Clone, Debug)] |
1a4d82fc | 179 | pub enum ValuePairs<'tcx> { |
e9174d1e SL |
180 | Types(ExpectedFound<Ty<'tcx>>), |
181 | TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>), | |
182 | PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>), | |
1a4d82fc JJ |
183 | } |
184 | ||
185 | /// The trace designates the path through inference that we took to | |
186 | /// encounter an error or subtyping constraint. | |
187 | /// | |
188 | /// See `error_reporting.rs` for more details. | |
62682a34 | 189 | #[derive(Clone)] |
1a4d82fc JJ |
190 | pub struct TypeTrace<'tcx> { |
191 | origin: TypeOrigin, | |
192 | values: ValuePairs<'tcx>, | |
193 | } | |
194 | ||
195 | /// The origin of a `r1 <= r2` constraint. | |
196 | /// | |
197 | /// See `error_reporting.rs` for more details | |
85aaf69f | 198 | #[derive(Clone, Debug)] |
1a4d82fc | 199 | pub enum SubregionOrigin<'tcx> { |
e9174d1e SL |
200 | // Marker to indicate a constraint that only arises due to new |
201 | // provisions from RFC 1214. This will result in a warning, not an | |
202 | // error. | |
203 | RFC1214Subregion(Rc<SubregionOrigin<'tcx>>), | |
204 | ||
1a4d82fc JJ |
205 | // Arose from a subtyping relation |
206 | Subtype(TypeTrace<'tcx>), | |
207 | ||
208 | // Stack-allocated closures cannot outlive innermost loop | |
209 | // or function so as to ensure we only require finite stack | |
210 | InfStackClosure(Span), | |
211 | ||
212 | // Invocation of closure must be within its lifetime | |
213 | InvokeClosure(Span), | |
214 | ||
215 | // Dereference of reference must be within its lifetime | |
216 | DerefPointer(Span), | |
217 | ||
218 | // Closure bound must not outlive captured free variables | |
219 | FreeVariable(Span, ast::NodeId), | |
220 | ||
221 | // Index into slice must be within its lifetime | |
222 | IndexSlice(Span), | |
223 | ||
224 | // When casting `&'a T` to an `&'b Trait` object, | |
225 | // relating `'a` to `'b` | |
226 | RelateObjectBound(Span), | |
227 | ||
228 | // Some type parameter was instantiated with the given type, | |
229 | // and that type must outlive some region. | |
230 | RelateParamBound(Span, Ty<'tcx>), | |
231 | ||
232 | // The given region parameter was instantiated with a region | |
233 | // that must outlive some other region. | |
234 | RelateRegionParamBound(Span), | |
235 | ||
236 | // A bound placed on type parameters that states that must outlive | |
237 | // the moment of their instantiation. | |
238 | RelateDefaultParamBound(Span, Ty<'tcx>), | |
239 | ||
240 | // Creating a pointer `b` to contents of another reference | |
241 | Reborrow(Span), | |
242 | ||
243 | // Creating a pointer `b` to contents of an upvar | |
244 | ReborrowUpvar(Span, ty::UpvarId), | |
245 | ||
e9174d1e SL |
246 | // Data with type `Ty<'tcx>` was borrowed |
247 | DataBorrowed(Ty<'tcx>, Span), | |
248 | ||
1a4d82fc JJ |
249 | // (&'a &'b T) where a >= b |
250 | ReferenceOutlivesReferent(Ty<'tcx>, Span), | |
251 | ||
e9174d1e SL |
252 | // Type or region parameters must be in scope. |
253 | ParameterInScope(ParameterOrigin, Span), | |
254 | ||
1a4d82fc JJ |
255 | // The type T of an expression E must outlive the lifetime for E. |
256 | ExprTypeIsNotInScope(Ty<'tcx>, Span), | |
257 | ||
258 | // A `ref b` whose region does not enclose the decl site | |
259 | BindingTypeIsNotValidAtDecl(Span), | |
260 | ||
261 | // Regions appearing in a method receiver must outlive method call | |
262 | CallRcvr(Span), | |
263 | ||
264 | // Regions appearing in a function argument must outlive func call | |
265 | CallArg(Span), | |
266 | ||
267 | // Region in return type of invoked fn must enclose call | |
268 | CallReturn(Span), | |
269 | ||
85aaf69f SL |
270 | // Operands must be in scope |
271 | Operand(Span), | |
272 | ||
1a4d82fc JJ |
273 | // Region resulting from a `&` expr must enclose the `&` expr |
274 | AddrOf(Span), | |
275 | ||
276 | // An auto-borrow that does not enclose the expr where it occurs | |
277 | AutoBorrow(Span), | |
85aaf69f SL |
278 | |
279 | // Region constraint arriving from destructor safety | |
280 | SafeDestructor(Span), | |
1a4d82fc JJ |
281 | } |
282 | ||
e9174d1e SL |
283 | /// Places that type/region parameters can appear. |
284 | #[derive(Clone, Copy, Debug)] | |
285 | pub enum ParameterOrigin { | |
286 | Path, // foo::bar | |
287 | MethodCall, // foo.bar() <-- parameters on impl providing bar() | |
288 | OverloadedOperator, // a + b when overloaded | |
289 | OverloadedDeref, // *a when overloaded | |
290 | } | |
291 | ||
1a4d82fc | 292 | /// Times when we replace late-bound regions with variables: |
85aaf69f | 293 | #[derive(Clone, Copy, Debug)] |
1a4d82fc JJ |
294 | pub enum LateBoundRegionConversionTime { |
295 | /// when a fn is called | |
296 | FnCall, | |
297 | ||
298 | /// when two higher-ranked types are compared | |
299 | HigherRankedType, | |
300 | ||
301 | /// when projecting an associated type | |
302 | AssocTypeProjection(ast::Name), | |
303 | } | |
304 | ||
305 | /// Reasons to create a region inference variable | |
306 | /// | |
307 | /// See `error_reporting.rs` for more details | |
85aaf69f | 308 | #[derive(Clone, Debug)] |
c34b1796 | 309 | pub enum RegionVariableOrigin { |
1a4d82fc JJ |
310 | // Region variables created for ill-categorized reasons, |
311 | // mostly indicates places in need of refactoring | |
312 | MiscVariable(Span), | |
313 | ||
314 | // Regions created by a `&P` or `[...]` pattern | |
315 | PatternRegion(Span), | |
316 | ||
317 | // Regions created by `&` operator | |
318 | AddrOfRegion(Span), | |
319 | ||
1a4d82fc JJ |
320 | // Regions created as part of an autoref of a method receiver |
321 | Autoref(Span), | |
322 | ||
323 | // Regions created as part of an automatic coercion | |
c34b1796 | 324 | Coercion(Span), |
1a4d82fc JJ |
325 | |
326 | // Region variables created as the values for early-bound regions | |
327 | EarlyBoundRegion(Span, ast::Name), | |
328 | ||
329 | // Region variables created for bound regions | |
330 | // in a function or method that is called | |
331 | LateBoundRegion(Span, ty::BoundRegion, LateBoundRegionConversionTime), | |
332 | ||
333 | UpvarRegion(ty::UpvarId, Span), | |
334 | ||
335 | BoundRegionInCoherence(ast::Name), | |
336 | } | |
337 | ||
c34b1796 | 338 | #[derive(Copy, Clone, Debug)] |
c1a9b12d SL |
339 | pub enum FixupError { |
340 | UnresolvedIntTy(IntVid), | |
341 | UnresolvedFloatTy(FloatVid), | |
342 | UnresolvedTy(TyVid) | |
1a4d82fc JJ |
343 | } |
344 | ||
c1a9b12d SL |
345 | pub fn fixup_err_to_string(f: FixupError) -> String { |
346 | use self::FixupError::*; | |
347 | ||
1a4d82fc | 348 | match f { |
c1a9b12d | 349 | UnresolvedIntTy(_) => { |
1a4d82fc JJ |
350 | "cannot determine the type of this integer; add a suffix to \ |
351 | specify the type explicitly".to_string() | |
352 | } | |
c1a9b12d | 353 | UnresolvedFloatTy(_) => { |
1a4d82fc JJ |
354 | "cannot determine the type of this number; add a suffix to specify \ |
355 | the type explicitly".to_string() | |
356 | } | |
c1a9b12d | 357 | UnresolvedTy(_) => "unconstrained type".to_string(), |
1a4d82fc JJ |
358 | } |
359 | } | |
360 | ||
c1a9b12d SL |
361 | /// errors_will_be_reported is required to proxy to the fulfillment context |
362 | /// FIXME -- a better option would be to hold back on modifying | |
363 | /// the global cache until we know that all dependent obligations | |
364 | /// are also satisfied. In that case, we could actually remove | |
365 | /// this boolean flag, and we'd also avoid the problem of squelching | |
366 | /// duplicate errors that occur across fns. | |
367 | pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, | |
368 | tables: &'a RefCell<ty::Tables<'tcx>>, | |
369 | param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>, | |
370 | errors_will_be_reported: bool) | |
1a4d82fc JJ |
371 | -> InferCtxt<'a, 'tcx> { |
372 | InferCtxt { | |
373 | tcx: tcx, | |
c1a9b12d | 374 | tables: tables, |
1a4d82fc JJ |
375 | type_variables: RefCell::new(type_variable::TypeVariableTable::new()), |
376 | int_unification_table: RefCell::new(UnificationTable::new()), | |
377 | float_unification_table: RefCell::new(UnificationTable::new()), | |
378 | region_vars: RegionVarBindings::new(tcx), | |
c1a9b12d SL |
379 | parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()), |
380 | fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)), | |
e9174d1e | 381 | reported_trait_errors: RefCell::new(FnvHashSet()), |
c1a9b12d SL |
382 | normalize: false, |
383 | err_count_on_creation: tcx.sess.err_count() | |
1a4d82fc JJ |
384 | } |
385 | } | |
386 | ||
c1a9b12d SL |
387 | pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, |
388 | tables: &'a RefCell<ty::Tables<'tcx>>) | |
389 | -> InferCtxt<'a, 'tcx> { | |
390 | let mut infcx = new_infer_ctxt(tcx, tables, None, false); | |
391 | infcx.normalize = true; | |
392 | infcx | |
393 | } | |
394 | ||
1a4d82fc JJ |
395 | /// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and |
396 | /// returns ty::err. | |
397 | pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, | |
398 | origin: TypeOrigin, | |
399 | a_is_expected: bool, | |
400 | a: Ty<'tcx>, | |
401 | b: Ty<'tcx>) | |
402 | -> Ty<'tcx> | |
403 | { | |
62682a34 SL |
404 | debug!("common_supertype({:?}, {:?})", |
405 | a, b); | |
1a4d82fc JJ |
406 | |
407 | let trace = TypeTrace { | |
408 | origin: origin, | |
409 | values: Types(expected_found(a_is_expected, a, b)) | |
410 | }; | |
411 | ||
c34b1796 | 412 | let result = cx.commit_if_ok(|_| cx.lub(a_is_expected, trace.clone()).relate(&a, &b)); |
1a4d82fc JJ |
413 | match result { |
414 | Ok(t) => t, | |
415 | Err(ref err) => { | |
416 | cx.report_and_explain_type_error(trace, err); | |
417 | cx.tcx.types.err | |
418 | } | |
419 | } | |
420 | } | |
421 | ||
422 | pub fn mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, | |
423 | a_is_expected: bool, | |
424 | origin: TypeOrigin, | |
425 | a: Ty<'tcx>, | |
426 | b: Ty<'tcx>) | |
c34b1796 | 427 | -> UnitResult<'tcx> |
1a4d82fc | 428 | { |
62682a34 | 429 | debug!("mk_subty({:?} <: {:?})", a, b); |
c34b1796 | 430 | cx.sub_types(a_is_expected, origin, a, b) |
1a4d82fc JJ |
431 | } |
432 | ||
433 | pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, | |
434 | a: Ty<'tcx>, | |
435 | b: Ty<'tcx>) | |
c34b1796 | 436 | -> UnitResult<'tcx> { |
62682a34 | 437 | debug!("can_mk_subty({:?} <: {:?})", a, b); |
1a4d82fc JJ |
438 | cx.probe(|_| { |
439 | let trace = TypeTrace { | |
440 | origin: Misc(codemap::DUMMY_SP), | |
441 | values: Types(expected_found(true, a, b)) | |
442 | }; | |
c34b1796 | 443 | cx.sub(true, trace).relate(&a, &b).map(|_| ()) |
1a4d82fc JJ |
444 | }) |
445 | } | |
446 | ||
c34b1796 AL |
447 | pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) |
448 | -> UnitResult<'tcx> | |
1a4d82fc JJ |
449 | { |
450 | cx.can_equate(&a, &b) | |
451 | } | |
452 | ||
453 | pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, | |
454 | origin: SubregionOrigin<'tcx>, | |
455 | a: ty::Region, | |
456 | b: ty::Region) { | |
62682a34 | 457 | debug!("mk_subr({:?} <: {:?})", a, b); |
1a4d82fc JJ |
458 | let snapshot = cx.region_vars.start_snapshot(); |
459 | cx.region_vars.make_subregion(origin, a, b); | |
460 | cx.region_vars.commit(snapshot); | |
461 | } | |
462 | ||
463 | pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, | |
464 | a_is_expected: bool, | |
465 | origin: TypeOrigin, | |
466 | a: Ty<'tcx>, | |
467 | b: Ty<'tcx>) | |
c34b1796 | 468 | -> UnitResult<'tcx> |
1a4d82fc | 469 | { |
62682a34 | 470 | debug!("mk_eqty({:?} <: {:?})", a, b); |
c34b1796 | 471 | cx.commit_if_ok(|_| cx.eq_types(a_is_expected, origin, a, b)) |
1a4d82fc JJ |
472 | } |
473 | ||
474 | pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, | |
475 | a_is_expected: bool, | |
476 | origin: TypeOrigin, | |
477 | a: ty::PolyTraitRef<'tcx>, | |
478 | b: ty::PolyTraitRef<'tcx>) | |
c34b1796 | 479 | -> UnitResult<'tcx> |
1a4d82fc | 480 | { |
62682a34 SL |
481 | debug!("mk_sub_trait_refs({:?} <: {:?})", |
482 | a, b); | |
c34b1796 | 483 | cx.commit_if_ok(|_| cx.sub_poly_trait_refs(a_is_expected, origin, a.clone(), b.clone())) |
1a4d82fc JJ |
484 | } |
485 | ||
486 | fn expected_found<T>(a_is_expected: bool, | |
487 | a: T, | |
488 | b: T) | |
e9174d1e | 489 | -> ExpectedFound<T> |
1a4d82fc JJ |
490 | { |
491 | if a_is_expected { | |
e9174d1e | 492 | ExpectedFound {expected: a, found: b} |
1a4d82fc | 493 | } else { |
e9174d1e | 494 | ExpectedFound {expected: b, found: a} |
1a4d82fc JJ |
495 | } |
496 | } | |
497 | ||
1a4d82fc JJ |
498 | #[must_use = "once you start a snapshot, you should always consume it"] |
499 | pub struct CombinedSnapshot { | |
500 | type_snapshot: type_variable::Snapshot, | |
501 | int_snapshot: unify::Snapshot<ty::IntVid>, | |
502 | float_snapshot: unify::Snapshot<ty::FloatVid>, | |
503 | region_vars_snapshot: RegionSnapshot, | |
504 | } | |
505 | ||
c1a9b12d SL |
506 | pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T |
507 | where T : TypeFoldable<'tcx> + HasTypeFlags | |
508 | { | |
509 | debug!("normalize_associated_type(t={:?})", value); | |
510 | ||
e9174d1e | 511 | let value = tcx.erase_regions(value); |
c1a9b12d SL |
512 | |
513 | if !value.has_projection_types() { | |
514 | return value; | |
515 | } | |
516 | ||
517 | let infcx = new_infer_ctxt(tcx, &tcx.tables, None, true); | |
518 | let mut selcx = traits::SelectionContext::new(&infcx); | |
519 | let cause = traits::ObligationCause::dummy(); | |
520 | let traits::Normalized { value: result, obligations } = | |
521 | traits::normalize(&mut selcx, cause, &value); | |
522 | ||
523 | debug!("normalize_associated_type: result={:?} obligations={:?}", | |
524 | result, | |
525 | obligations); | |
526 | ||
527 | let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut(); | |
528 | ||
529 | for obligation in obligations { | |
530 | fulfill_cx.register_predicate_obligation(&infcx, obligation); | |
531 | } | |
532 | ||
e9174d1e | 533 | drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result) |
c1a9b12d SL |
534 | } |
535 | ||
536 | pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span, | |
537 | infcx: &InferCtxt<'a,'tcx>, | |
538 | fulfill_cx: &mut traits::FulfillmentContext<'tcx>, | |
539 | result: &T) | |
540 | -> T | |
e9174d1e | 541 | where T : TypeFoldable<'tcx> + HasTypeFlags |
c1a9b12d SL |
542 | { |
543 | match drain_fulfillment_cx(infcx, fulfill_cx, result) { | |
544 | Ok(v) => v, | |
545 | Err(errors) => { | |
546 | infcx.tcx.sess.span_bug( | |
547 | span, | |
548 | &format!("Encountered errors `{:?}` fulfilling during trans", | |
549 | errors)); | |
550 | } | |
551 | } | |
552 | } | |
553 | ||
554 | /// Finishes processes any obligations that remain in the fulfillment | |
555 | /// context, and then "freshens" and returns `result`. This is | |
556 | /// primarily used during normalization and other cases where | |
557 | /// processing the obligations in `fulfill_cx` may cause type | |
558 | /// inference variables that appear in `result` to be unified, and | |
559 | /// hence we need to process those obligations to get the complete | |
560 | /// picture of the type. | |
561 | pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, | |
562 | fulfill_cx: &mut traits::FulfillmentContext<'tcx>, | |
563 | result: &T) | |
564 | -> Result<T,Vec<traits::FulfillmentError<'tcx>>> | |
e9174d1e | 565 | where T : TypeFoldable<'tcx> + HasTypeFlags |
c1a9b12d SL |
566 | { |
567 | debug!("drain_fulfillment_cx(result={:?})", | |
568 | result); | |
569 | ||
570 | // In principle, we only need to do this so long as `result` | |
571 | // contains unbound type parameters. It could be a slight | |
572 | // optimization to stop iterating early. | |
573 | match fulfill_cx.select_all_or_error(infcx) { | |
574 | Ok(()) => { } | |
575 | Err(errors) => { | |
576 | return Err(errors); | |
577 | } | |
578 | } | |
579 | ||
e9174d1e SL |
580 | let result = infcx.resolve_type_vars_if_possible(result); |
581 | Ok(infcx.tcx.erase_regions(&result)) | |
c1a9b12d SL |
582 | } |
583 | ||
1a4d82fc JJ |
584 | impl<'a, 'tcx> InferCtxt<'a, 'tcx> { |
585 | pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T { | |
586 | t.fold_with(&mut self.freshener()) | |
587 | } | |
588 | ||
589 | pub fn type_var_diverges(&'a self, ty: Ty) -> bool { | |
590 | match ty.sty { | |
62682a34 | 591 | ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid), |
1a4d82fc JJ |
592 | _ => false |
593 | } | |
594 | } | |
595 | ||
596 | pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> { | |
597 | freshen::TypeFreshener::new(self) | |
598 | } | |
599 | ||
600 | pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric { | |
e9174d1e SL |
601 | use middle::ty::error::UnconstrainedNumeric::Neither; |
602 | use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; | |
1a4d82fc | 603 | match ty.sty { |
62682a34 | 604 | ty::TyInfer(ty::IntVar(vid)) => { |
c34b1796 AL |
605 | if self.int_unification_table.borrow_mut().has_value(vid) { |
606 | Neither | |
607 | } else { | |
608 | UnconstrainedInt | |
1a4d82fc JJ |
609 | } |
610 | }, | |
62682a34 | 611 | ty::TyInfer(ty::FloatVar(vid)) => { |
c34b1796 AL |
612 | if self.float_unification_table.borrow_mut().has_value(vid) { |
613 | Neither | |
614 | } else { | |
615 | UnconstrainedFloat | |
1a4d82fc JJ |
616 | } |
617 | }, | |
618 | _ => Neither, | |
619 | } | |
620 | } | |
621 | ||
c1a9b12d SL |
622 | /// Returns a type variable's default fallback if any exists. A default |
623 | /// must be attached to the variable when created, if it is created | |
624 | /// without a default, this will return None. | |
625 | /// | |
626 | /// This code does not apply to integral or floating point variables, | |
627 | /// only to use declared defaults. | |
628 | /// | |
629 | /// See `new_ty_var_with_default` to create a type variable with a default. | |
630 | /// See `type_variable::Default` for details about what a default entails. | |
631 | pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> { | |
632 | match ty.sty { | |
633 | ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid), | |
634 | _ => None | |
635 | } | |
636 | } | |
637 | ||
638 | pub fn unsolved_variables(&self) -> Vec<ty::Ty<'tcx>> { | |
639 | let mut variables = Vec::new(); | |
640 | ||
641 | let unbound_ty_vars = self.type_variables | |
642 | .borrow() | |
643 | .unsolved_variables() | |
644 | .into_iter() | |
645 | .map(|t| self.tcx.mk_var(t)); | |
646 | ||
647 | let unbound_int_vars = self.int_unification_table | |
648 | .borrow_mut() | |
649 | .unsolved_variables() | |
650 | .into_iter() | |
651 | .map(|v| self.tcx.mk_int_var(v)); | |
652 | ||
653 | let unbound_float_vars = self.float_unification_table | |
654 | .borrow_mut() | |
655 | .unsolved_variables() | |
656 | .into_iter() | |
657 | .map(|v| self.tcx.mk_float_var(v)); | |
658 | ||
659 | variables.extend(unbound_ty_vars); | |
660 | variables.extend(unbound_int_vars); | |
661 | variables.extend(unbound_float_vars); | |
662 | ||
663 | return variables; | |
664 | } | |
665 | ||
c34b1796 AL |
666 | fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) |
667 | -> CombineFields<'a, 'tcx> { | |
1a4d82fc JJ |
668 | CombineFields {infcx: self, |
669 | a_is_expected: a_is_expected, | |
62682a34 SL |
670 | trace: trace, |
671 | cause: None} | |
1a4d82fc JJ |
672 | } |
673 | ||
c34b1796 AL |
674 | // public so that it can be used from the rustc_driver unit tests |
675 | pub fn equate(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) | |
676 | -> equate::Equate<'a, 'tcx> | |
677 | { | |
678 | self.combine_fields(a_is_expected, trace).equate() | |
679 | } | |
680 | ||
681 | // public so that it can be used from the rustc_driver unit tests | |
682 | pub fn sub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) | |
683 | -> sub::Sub<'a, 'tcx> | |
684 | { | |
685 | self.combine_fields(a_is_expected, trace).sub() | |
1a4d82fc JJ |
686 | } |
687 | ||
c34b1796 AL |
688 | // public so that it can be used from the rustc_driver unit tests |
689 | pub fn lub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) | |
690 | -> lub::Lub<'a, 'tcx> | |
691 | { | |
692 | self.combine_fields(a_is_expected, trace).lub() | |
1a4d82fc JJ |
693 | } |
694 | ||
c34b1796 AL |
695 | // public so that it can be used from the rustc_driver unit tests |
696 | pub fn glb(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) | |
697 | -> glb::Glb<'a, 'tcx> | |
698 | { | |
699 | self.combine_fields(a_is_expected, trace).glb() | |
1a4d82fc JJ |
700 | } |
701 | ||
702 | fn start_snapshot(&self) -> CombinedSnapshot { | |
703 | CombinedSnapshot { | |
704 | type_snapshot: self.type_variables.borrow_mut().snapshot(), | |
705 | int_snapshot: self.int_unification_table.borrow_mut().snapshot(), | |
706 | float_snapshot: self.float_unification_table.borrow_mut().snapshot(), | |
707 | region_vars_snapshot: self.region_vars.start_snapshot(), | |
708 | } | |
709 | } | |
710 | ||
c1a9b12d SL |
711 | fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot) { |
712 | debug!("rollback_to(cause={})", cause); | |
1a4d82fc JJ |
713 | let CombinedSnapshot { type_snapshot, |
714 | int_snapshot, | |
715 | float_snapshot, | |
716 | region_vars_snapshot } = snapshot; | |
717 | ||
718 | self.type_variables | |
719 | .borrow_mut() | |
720 | .rollback_to(type_snapshot); | |
721 | self.int_unification_table | |
722 | .borrow_mut() | |
723 | .rollback_to(int_snapshot); | |
724 | self.float_unification_table | |
725 | .borrow_mut() | |
726 | .rollback_to(float_snapshot); | |
727 | self.region_vars | |
728 | .rollback_to(region_vars_snapshot); | |
729 | } | |
730 | ||
731 | fn commit_from(&self, snapshot: CombinedSnapshot) { | |
732 | debug!("commit_from!"); | |
733 | let CombinedSnapshot { type_snapshot, | |
734 | int_snapshot, | |
735 | float_snapshot, | |
736 | region_vars_snapshot } = snapshot; | |
737 | ||
738 | self.type_variables | |
739 | .borrow_mut() | |
740 | .commit(type_snapshot); | |
741 | self.int_unification_table | |
742 | .borrow_mut() | |
743 | .commit(int_snapshot); | |
744 | self.float_unification_table | |
745 | .borrow_mut() | |
746 | .commit(float_snapshot); | |
747 | self.region_vars | |
748 | .commit(region_vars_snapshot); | |
749 | } | |
750 | ||
751 | /// Execute `f` and commit the bindings | |
752 | pub fn commit_unconditionally<R, F>(&self, f: F) -> R where | |
753 | F: FnOnce() -> R, | |
754 | { | |
755 | debug!("commit()"); | |
756 | let snapshot = self.start_snapshot(); | |
757 | let r = f(); | |
758 | self.commit_from(snapshot); | |
759 | r | |
760 | } | |
761 | ||
c34b1796 | 762 | /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)` |
1a4d82fc | 763 | pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where |
c34b1796 | 764 | F: FnOnce(&CombinedSnapshot) -> Result<T, E> |
1a4d82fc | 765 | { |
c34b1796 AL |
766 | debug!("commit_if_ok()"); |
767 | let snapshot = self.start_snapshot(); | |
768 | let r = f(&snapshot); | |
769 | debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); | |
770 | match r { | |
771 | Ok(_) => { self.commit_from(snapshot); } | |
c1a9b12d | 772 | Err(_) => { self.rollback_to("commit_if_ok -- error", snapshot); } |
c34b1796 AL |
773 | } |
774 | r | |
1a4d82fc JJ |
775 | } |
776 | ||
85aaf69f SL |
777 | /// Execute `f` and commit only the region bindings if successful. |
778 | /// The function f must be very careful not to leak any non-region | |
779 | /// variables that get created. | |
780 | pub fn commit_regions_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where | |
781 | F: FnOnce() -> Result<T, E> | |
782 | { | |
783 | debug!("commit_regions_if_ok()"); | |
784 | let CombinedSnapshot { type_snapshot, | |
785 | int_snapshot, | |
786 | float_snapshot, | |
787 | region_vars_snapshot } = self.start_snapshot(); | |
788 | ||
c34b1796 | 789 | let r = self.commit_if_ok(|_| f()); |
85aaf69f | 790 | |
c1a9b12d SL |
791 | debug!("commit_regions_if_ok: rolling back everything but regions"); |
792 | ||
85aaf69f SL |
793 | // Roll back any non-region bindings - they should be resolved |
794 | // inside `f`, with, e.g. `resolve_type_vars_if_possible`. | |
795 | self.type_variables | |
796 | .borrow_mut() | |
797 | .rollback_to(type_snapshot); | |
798 | self.int_unification_table | |
799 | .borrow_mut() | |
800 | .rollback_to(int_snapshot); | |
801 | self.float_unification_table | |
802 | .borrow_mut() | |
803 | .rollback_to(float_snapshot); | |
804 | ||
805 | // Commit region vars that may escape through resolved types. | |
806 | self.region_vars | |
807 | .commit(region_vars_snapshot); | |
808 | ||
809 | r | |
810 | } | |
811 | ||
1a4d82fc JJ |
812 | /// Execute `f` then unroll any bindings it creates |
813 | pub fn probe<R, F>(&self, f: F) -> R where | |
814 | F: FnOnce(&CombinedSnapshot) -> R, | |
815 | { | |
816 | debug!("probe()"); | |
817 | let snapshot = self.start_snapshot(); | |
818 | let r = f(&snapshot); | |
c1a9b12d | 819 | self.rollback_to("probe", snapshot); |
1a4d82fc JJ |
820 | r |
821 | } | |
822 | ||
823 | pub fn add_given(&self, | |
824 | sub: ty::FreeRegion, | |
825 | sup: ty::RegionVid) | |
826 | { | |
827 | self.region_vars.add_given(sub, sup); | |
828 | } | |
829 | ||
830 | pub fn sub_types(&self, | |
831 | a_is_expected: bool, | |
832 | origin: TypeOrigin, | |
833 | a: Ty<'tcx>, | |
834 | b: Ty<'tcx>) | |
c34b1796 | 835 | -> UnitResult<'tcx> |
1a4d82fc | 836 | { |
62682a34 | 837 | debug!("sub_types({:?} <: {:?})", a, b); |
c34b1796 | 838 | self.commit_if_ok(|_| { |
85aaf69f | 839 | let trace = TypeTrace::types(origin, a_is_expected, a, b); |
c34b1796 | 840 | self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ()) |
1a4d82fc JJ |
841 | }) |
842 | } | |
843 | ||
844 | pub fn eq_types(&self, | |
845 | a_is_expected: bool, | |
846 | origin: TypeOrigin, | |
847 | a: Ty<'tcx>, | |
848 | b: Ty<'tcx>) | |
c34b1796 | 849 | -> UnitResult<'tcx> |
1a4d82fc | 850 | { |
c34b1796 | 851 | self.commit_if_ok(|_| { |
85aaf69f | 852 | let trace = TypeTrace::types(origin, a_is_expected, a, b); |
c34b1796 | 853 | self.equate(a_is_expected, trace).relate(&a, &b).map(|_| ()) |
1a4d82fc JJ |
854 | }) |
855 | } | |
856 | ||
857 | pub fn sub_trait_refs(&self, | |
858 | a_is_expected: bool, | |
859 | origin: TypeOrigin, | |
d9579d0f AL |
860 | a: ty::TraitRef<'tcx>, |
861 | b: ty::TraitRef<'tcx>) | |
c34b1796 | 862 | -> UnitResult<'tcx> |
1a4d82fc | 863 | { |
62682a34 SL |
864 | debug!("sub_trait_refs({:?} <: {:?})", |
865 | a, | |
866 | b); | |
c34b1796 | 867 | self.commit_if_ok(|_| { |
1a4d82fc JJ |
868 | let trace = TypeTrace { |
869 | origin: origin, | |
870 | values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone())) | |
871 | }; | |
d9579d0f | 872 | self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ()) |
1a4d82fc JJ |
873 | }) |
874 | } | |
875 | ||
876 | pub fn sub_poly_trait_refs(&self, | |
877 | a_is_expected: bool, | |
878 | origin: TypeOrigin, | |
879 | a: ty::PolyTraitRef<'tcx>, | |
880 | b: ty::PolyTraitRef<'tcx>) | |
c34b1796 | 881 | -> UnitResult<'tcx> |
1a4d82fc | 882 | { |
62682a34 SL |
883 | debug!("sub_poly_trait_refs({:?} <: {:?})", |
884 | a, | |
885 | b); | |
c34b1796 | 886 | self.commit_if_ok(|_| { |
1a4d82fc JJ |
887 | let trace = TypeTrace { |
888 | origin: origin, | |
889 | values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone())) | |
890 | }; | |
c34b1796 | 891 | self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ()) |
1a4d82fc JJ |
892 | }) |
893 | } | |
894 | ||
895 | pub fn skolemize_late_bound_regions<T>(&self, | |
896 | value: &ty::Binder<T>, | |
897 | snapshot: &CombinedSnapshot) | |
898 | -> (T, SkolemizationMap) | |
62682a34 | 899 | where T : TypeFoldable<'tcx> |
1a4d82fc JJ |
900 | { |
901 | /*! See `higher_ranked::skolemize_late_bound_regions` */ | |
902 | ||
903 | higher_ranked::skolemize_late_bound_regions(self, value, snapshot) | |
904 | } | |
905 | ||
906 | pub fn leak_check(&self, | |
907 | skol_map: &SkolemizationMap, | |
908 | snapshot: &CombinedSnapshot) | |
c34b1796 | 909 | -> UnitResult<'tcx> |
1a4d82fc JJ |
910 | { |
911 | /*! See `higher_ranked::leak_check` */ | |
912 | ||
913 | match higher_ranked::leak_check(self, skol_map, snapshot) { | |
914 | Ok(()) => Ok(()), | |
c1a9b12d | 915 | Err((br, r)) => Err(TypeError::RegionsInsufficientlyPolymorphic(br, r)) |
1a4d82fc JJ |
916 | } |
917 | } | |
918 | ||
919 | pub fn plug_leaks<T>(&self, | |
920 | skol_map: SkolemizationMap, | |
921 | snapshot: &CombinedSnapshot, | |
922 | value: &T) | |
923 | -> T | |
e9174d1e | 924 | where T : TypeFoldable<'tcx> + HasTypeFlags |
1a4d82fc JJ |
925 | { |
926 | /*! See `higher_ranked::plug_leaks` */ | |
927 | ||
928 | higher_ranked::plug_leaks(self, skol_map, snapshot, value) | |
929 | } | |
930 | ||
931 | pub fn equality_predicate(&self, | |
932 | span: Span, | |
933 | predicate: &ty::PolyEquatePredicate<'tcx>) | |
c34b1796 AL |
934 | -> UnitResult<'tcx> { |
935 | self.commit_if_ok(|snapshot| { | |
1a4d82fc JJ |
936 | let (ty::EquatePredicate(a, b), skol_map) = |
937 | self.skolemize_late_bound_regions(predicate, snapshot); | |
938 | let origin = EquatePredicate(span); | |
939 | let () = try!(mk_eqty(self, false, origin, a, b)); | |
940 | self.leak_check(&skol_map, snapshot) | |
941 | }) | |
942 | } | |
943 | ||
944 | pub fn region_outlives_predicate(&self, | |
945 | span: Span, | |
946 | predicate: &ty::PolyRegionOutlivesPredicate) | |
c34b1796 AL |
947 | -> UnitResult<'tcx> { |
948 | self.commit_if_ok(|snapshot| { | |
1a4d82fc JJ |
949 | let (ty::OutlivesPredicate(r_a, r_b), skol_map) = |
950 | self.skolemize_late_bound_regions(predicate, snapshot); | |
951 | let origin = RelateRegionParamBound(span); | |
952 | let () = mk_subr(self, origin, r_b, r_a); // `b : a` ==> `a <= b` | |
953 | self.leak_check(&skol_map, snapshot) | |
954 | }) | |
955 | } | |
956 | ||
957 | pub fn next_ty_var_id(&self, diverging: bool) -> TyVid { | |
958 | self.type_variables | |
959 | .borrow_mut() | |
c1a9b12d | 960 | .new_var(diverging, None) |
1a4d82fc JJ |
961 | } |
962 | ||
963 | pub fn next_ty_var(&self) -> Ty<'tcx> { | |
c1a9b12d SL |
964 | self.tcx.mk_var(self.next_ty_var_id(false)) |
965 | } | |
966 | ||
967 | pub fn next_ty_var_with_default(&self, | |
968 | default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> { | |
969 | let ty_var_id = self.type_variables | |
970 | .borrow_mut() | |
971 | .new_var(false, default); | |
972 | ||
973 | self.tcx.mk_var(ty_var_id) | |
1a4d82fc JJ |
974 | } |
975 | ||
976 | pub fn next_diverging_ty_var(&self) -> Ty<'tcx> { | |
c1a9b12d | 977 | self.tcx.mk_var(self.next_ty_var_id(true)) |
1a4d82fc JJ |
978 | } |
979 | ||
c34b1796 | 980 | pub fn next_ty_vars(&self, n: usize) -> Vec<Ty<'tcx>> { |
85aaf69f | 981 | (0..n).map(|_i| self.next_ty_var()).collect() |
1a4d82fc JJ |
982 | } |
983 | ||
984 | pub fn next_int_var_id(&self) -> IntVid { | |
985 | self.int_unification_table | |
986 | .borrow_mut() | |
987 | .new_key(None) | |
988 | } | |
989 | ||
990 | pub fn next_float_var_id(&self) -> FloatVid { | |
991 | self.float_unification_table | |
992 | .borrow_mut() | |
993 | .new_key(None) | |
994 | } | |
995 | ||
c34b1796 | 996 | pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region { |
e9174d1e | 997 | ty::ReVar(self.region_vars.new_region_var(origin)) |
1a4d82fc JJ |
998 | } |
999 | ||
1000 | pub fn region_vars_for_defs(&self, | |
1001 | span: Span, | |
1002 | defs: &[ty::RegionParameterDef]) | |
1003 | -> Vec<ty::Region> { | |
1004 | defs.iter() | |
1005 | .map(|d| self.next_region_var(EarlyBoundRegion(span, d.name))) | |
1006 | .collect() | |
1007 | } | |
1008 | ||
c1a9b12d SL |
1009 | // We have to take `&mut Substs` in order to provide the correct substitutions for defaults |
1010 | // along the way, for this reason we don't return them. | |
1011 | pub fn type_vars_for_defs(&self, | |
1012 | span: Span, | |
1013 | space: subst::ParamSpace, | |
1014 | substs: &mut Substs<'tcx>, | |
1015 | defs: &[ty::TypeParameterDef<'tcx>]) { | |
1016 | ||
1017 | let mut vars = Vec::with_capacity(defs.len()); | |
1018 | ||
1019 | for def in defs.iter() { | |
1020 | let default = def.default.map(|default| { | |
1021 | type_variable::Default { | |
1022 | ty: default.subst_spanned(self.tcx, substs, Some(span)), | |
1023 | origin_span: span, | |
1024 | def_id: def.default_def_id | |
1025 | } | |
1026 | }); | |
1027 | ||
1028 | let ty_var = self.next_ty_var_with_default(default); | |
1029 | substs.types.push(space, ty_var); | |
1030 | vars.push(ty_var) | |
1031 | } | |
1032 | } | |
1033 | ||
1a4d82fc JJ |
1034 | /// Given a set of generics defined on a type or impl, returns a substitution mapping each |
1035 | /// type/region parameter to a fresh inference variable. | |
1036 | pub fn fresh_substs_for_generics(&self, | |
1037 | span: Span, | |
1038 | generics: &ty::Generics<'tcx>) | |
1039 | -> subst::Substs<'tcx> | |
1040 | { | |
c1a9b12d SL |
1041 | let type_params = subst::VecPerParamSpace::empty(); |
1042 | ||
1a4d82fc JJ |
1043 | let region_params = |
1044 | generics.regions.map( | |
1045 | |d| self.next_region_var(EarlyBoundRegion(span, d.name))); | |
c1a9b12d SL |
1046 | |
1047 | let mut substs = subst::Substs::new(type_params, region_params); | |
1048 | ||
1049 | for space in subst::ParamSpace::all().iter() { | |
1050 | self.type_vars_for_defs( | |
1051 | span, | |
1052 | *space, | |
1053 | &mut substs, | |
1054 | generics.types.get_slice(*space)); | |
1055 | } | |
1056 | ||
1057 | return substs; | |
1a4d82fc JJ |
1058 | } |
1059 | ||
1060 | /// Given a set of generics defined on a trait, returns a substitution mapping each output | |
1061 | /// type/region parameter to a fresh inference variable, and mapping the self type to | |
1062 | /// `self_ty`. | |
1063 | pub fn fresh_substs_for_trait(&self, | |
1064 | span: Span, | |
1065 | generics: &ty::Generics<'tcx>, | |
1066 | self_ty: Ty<'tcx>) | |
1067 | -> subst::Substs<'tcx> | |
1068 | { | |
1069 | ||
1070 | assert!(generics.types.len(subst::SelfSpace) == 1); | |
1071 | assert!(generics.types.len(subst::FnSpace) == 0); | |
1072 | assert!(generics.regions.len(subst::SelfSpace) == 0); | |
1073 | assert!(generics.regions.len(subst::FnSpace) == 0); | |
1074 | ||
c1a9b12d | 1075 | let type_params = Vec::new(); |
1a4d82fc JJ |
1076 | |
1077 | let region_param_defs = generics.regions.get_slice(subst::TypeSpace); | |
1078 | let regions = self.region_vars_for_defs(span, region_param_defs); | |
1079 | ||
c1a9b12d SL |
1080 | let mut substs = subst::Substs::new_trait(type_params, regions, self_ty); |
1081 | ||
1082 | let type_parameter_defs = generics.types.get_slice(subst::TypeSpace); | |
1083 | self.type_vars_for_defs(span, subst::TypeSpace, &mut substs, type_parameter_defs); | |
1084 | ||
1085 | return substs; | |
1a4d82fc JJ |
1086 | } |
1087 | ||
1088 | pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region { | |
1089 | self.region_vars.new_bound(debruijn) | |
1090 | } | |
1091 | ||
c1a9b12d SL |
1092 | /// Apply `adjustment` to the type of `expr` |
1093 | pub fn adjust_expr_ty(&self, | |
e9174d1e SL |
1094 | expr: &hir::Expr, |
1095 | adjustment: Option<&adjustment::AutoAdjustment<'tcx>>) | |
c1a9b12d SL |
1096 | -> Ty<'tcx> |
1097 | { | |
1098 | let raw_ty = self.expr_ty(expr); | |
1099 | let raw_ty = self.shallow_resolve(raw_ty); | |
1100 | let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty); | |
1101 | raw_ty.adjust(self.tcx, | |
1102 | expr.span, | |
1103 | expr.id, | |
1104 | adjustment, | |
1105 | |method_call| self.tables | |
1106 | .borrow() | |
1107 | .method_map | |
1108 | .get(&method_call) | |
1109 | .map(|method| resolve_ty(method.ty))) | |
1110 | } | |
1111 | ||
1112 | pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> { | |
1113 | match self.tables.borrow().node_types.get(&id) { | |
1114 | Some(&t) => t, | |
1115 | // FIXME | |
1116 | None if self.tcx.sess.err_count() - self.err_count_on_creation != 0 => | |
1117 | self.tcx.types.err, | |
1118 | None => { | |
1119 | self.tcx.sess.bug( | |
1120 | &format!("no type for node {}: {} in fcx", | |
1121 | id, self.tcx.map.node_to_string(id))); | |
1122 | } | |
1123 | } | |
1124 | } | |
1125 | ||
e9174d1e | 1126 | pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> { |
c1a9b12d SL |
1127 | match self.tables.borrow().node_types.get(&ex.id) { |
1128 | Some(&t) => t, | |
1129 | None => { | |
1130 | self.tcx.sess.bug(&format!("no type for expr in fcx")); | |
1131 | } | |
1132 | } | |
1133 | } | |
1134 | ||
bd371182 AL |
1135 | pub fn resolve_regions_and_report_errors(&self, |
1136 | free_regions: &FreeRegionMap, | |
1137 | subject_node_id: ast::NodeId) { | |
1138 | let errors = self.region_vars.resolve_regions(free_regions, subject_node_id); | |
1a4d82fc JJ |
1139 | self.report_region_errors(&errors); // see error_reporting.rs |
1140 | } | |
1141 | ||
1142 | pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { | |
62682a34 | 1143 | self.resolve_type_vars_if_possible(&t).to_string() |
1a4d82fc JJ |
1144 | } |
1145 | ||
1146 | pub fn tys_to_string(&self, ts: &[Ty<'tcx>]) -> String { | |
1147 | let tstrs: Vec<String> = ts.iter().map(|t| self.ty_to_string(*t)).collect(); | |
c1a9b12d | 1148 | format!("({})", tstrs.join(", ")) |
1a4d82fc JJ |
1149 | } |
1150 | ||
d9579d0f | 1151 | pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String { |
62682a34 | 1152 | self.resolve_type_vars_if_possible(t).to_string() |
1a4d82fc JJ |
1153 | } |
1154 | ||
1155 | pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> { | |
1156 | match typ.sty { | |
62682a34 | 1157 | ty::TyInfer(ty::TyVar(v)) => { |
1a4d82fc JJ |
1158 | // Not entirely obvious: if `typ` is a type variable, |
1159 | // it can be resolved to an int/float variable, which | |
1160 | // can then be recursively resolved, hence the | |
1161 | // recursion. Note though that we prevent type | |
1162 | // variables from unifying to other type variables | |
1163 | // directly (though they may be embedded | |
1164 | // structurally), and we prevent cycles in any case, | |
1165 | // so this recursion should always be of very limited | |
1166 | // depth. | |
1167 | self.type_variables.borrow() | |
1168 | .probe(v) | |
1169 | .map(|t| self.shallow_resolve(t)) | |
1170 | .unwrap_or(typ) | |
1171 | } | |
1172 | ||
62682a34 | 1173 | ty::TyInfer(ty::IntVar(v)) => { |
c34b1796 AL |
1174 | self.int_unification_table |
1175 | .borrow_mut() | |
1176 | .probe(v) | |
1177 | .map(|v| v.to_type(self.tcx)) | |
1a4d82fc JJ |
1178 | .unwrap_or(typ) |
1179 | } | |
1180 | ||
62682a34 | 1181 | ty::TyInfer(ty::FloatVar(v)) => { |
c34b1796 AL |
1182 | self.float_unification_table |
1183 | .borrow_mut() | |
1184 | .probe(v) | |
1185 | .map(|v| v.to_type(self.tcx)) | |
1a4d82fc JJ |
1186 | .unwrap_or(typ) |
1187 | } | |
1188 | ||
1189 | _ => { | |
1190 | typ | |
1191 | } | |
1192 | } | |
1193 | } | |
1194 | ||
e9174d1e SL |
1195 | pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T |
1196 | where T: TypeFoldable<'tcx> + HasTypeFlags | |
1197 | { | |
1a4d82fc JJ |
1198 | /*! |
1199 | * Where possible, replaces type/int/float variables in | |
1200 | * `value` with their final value. Note that region variables | |
1201 | * are unaffected. If a type variable has not been unified, it | |
1202 | * is left as is. This is an idempotent operation that does | |
1203 | * not affect inference state in any way and so you can do it | |
1204 | * at will. | |
1205 | */ | |
1206 | ||
e9174d1e SL |
1207 | if !value.needs_infer() { |
1208 | return value.clone(); // avoid duplicated subst-folding | |
1209 | } | |
1a4d82fc JJ |
1210 | let mut r = resolve::OpportunisticTypeResolver::new(self); |
1211 | value.fold_with(&mut r) | |
1212 | } | |
1213 | ||
c1a9b12d SL |
1214 | /// Resolves all type variables in `t` and then, if any were left |
1215 | /// unresolved, substitutes an error type. This is used after the | |
1216 | /// main checking when doing a second pass before writeback. The | |
1217 | /// justification is that writeback will produce an error for | |
1218 | /// these unconstrained type variables. | |
1219 | fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> { | |
1220 | let ty = self.resolve_type_vars_if_possible(t); | |
1221 | if ty.references_error() || ty.is_ty_var() { | |
1222 | debug!("resolve_type_vars_or_error: error from {:?}", ty); | |
1223 | Err(()) | |
1224 | } else { | |
1225 | Ok(ty) | |
1226 | } | |
1227 | } | |
1228 | ||
1229 | pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> { | |
1a4d82fc JJ |
1230 | /*! |
1231 | * Attempts to resolve all type/region variables in | |
1232 | * `value`. Region inference must have been run already (e.g., | |
1233 | * by calling `resolve_regions_and_report_errors`). If some | |
1234 | * variable was never unified, an `Err` results. | |
1235 | * | |
1236 | * This method is idempotent, but it not typically not invoked | |
1237 | * except during the writeback phase. | |
1238 | */ | |
1239 | ||
1240 | resolve::fully_resolve(self, value) | |
1241 | } | |
1242 | ||
1243 | // [Note-Type-error-reporting] | |
62682a34 | 1244 | // An invariant is that anytime the expected or actual type is TyError (the special |
1a4d82fc JJ |
1245 | // error type, meaning that an error occurred when typechecking this expression), |
1246 | // this is a derived error. The error cascaded from another error (that was already | |
1247 | // reported), so it's not useful to display it to the user. | |
1248 | // The following four methods -- type_error_message_str, type_error_message_str_with_expected, | |
1249 | // type_error_message, and report_mismatched_types -- implement this logic. | |
62682a34 | 1250 | // They check if either the actual or expected type is TyError, and don't print the error |
1a4d82fc JJ |
1251 | // in this case. The typechecker should only ever report type errors involving mismatched |
1252 | // types using one of these four methods, and should not call span_err directly for such | |
1253 | // errors. | |
1254 | pub fn type_error_message_str<M>(&self, | |
1255 | sp: Span, | |
1256 | mk_msg: M, | |
1257 | actual_ty: String, | |
e9174d1e | 1258 | err: Option<&TypeError<'tcx>>) where |
1a4d82fc JJ |
1259 | M: FnOnce(Option<String>, String) -> String, |
1260 | { | |
1261 | self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err) | |
1262 | } | |
1263 | ||
1264 | pub fn type_error_message_str_with_expected<M>(&self, | |
1265 | sp: Span, | |
1266 | mk_msg: M, | |
1267 | expected_ty: Option<Ty<'tcx>>, | |
1268 | actual_ty: String, | |
e9174d1e | 1269 | err: Option<&TypeError<'tcx>>) where |
1a4d82fc JJ |
1270 | M: FnOnce(Option<String>, String) -> String, |
1271 | { | |
1272 | debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty); | |
1273 | ||
1274 | let resolved_expected = expected_ty.map(|e_ty| self.resolve_type_vars_if_possible(&e_ty)); | |
1275 | ||
c1a9b12d SL |
1276 | if !resolved_expected.references_error() { |
1277 | let error_str = err.map_or("".to_string(), |t_err| { | |
1278 | format!(" ({})", t_err) | |
1279 | }); | |
1a4d82fc | 1280 | |
c1a9b12d SL |
1281 | self.tcx.sess.span_err(sp, &format!("{}{}", |
1282 | mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty), | |
1283 | error_str)); | |
1a4d82fc | 1284 | |
c1a9b12d SL |
1285 | if let Some(err) = err { |
1286 | self.tcx.note_and_explain_type_err(err, sp) | |
1a4d82fc JJ |
1287 | } |
1288 | } | |
1289 | } | |
1290 | ||
1291 | pub fn type_error_message<M>(&self, | |
1292 | sp: Span, | |
1293 | mk_msg: M, | |
1294 | actual_ty: Ty<'tcx>, | |
e9174d1e | 1295 | err: Option<&TypeError<'tcx>>) where |
1a4d82fc JJ |
1296 | M: FnOnce(String) -> String, |
1297 | { | |
1298 | let actual_ty = self.resolve_type_vars_if_possible(&actual_ty); | |
1299 | ||
62682a34 | 1300 | // Don't report an error if actual type is TyError. |
c1a9b12d | 1301 | if actual_ty.references_error() { |
1a4d82fc JJ |
1302 | return; |
1303 | } | |
1304 | ||
1305 | self.type_error_message_str(sp, | |
1306 | move |_e, a| { mk_msg(a) }, | |
1307 | self.ty_to_string(actual_ty), err); | |
1308 | } | |
1309 | ||
1310 | pub fn report_mismatched_types(&self, | |
1311 | span: Span, | |
1312 | expected: Ty<'tcx>, | |
1313 | actual: Ty<'tcx>, | |
e9174d1e | 1314 | err: &TypeError<'tcx>) { |
1a4d82fc JJ |
1315 | let trace = TypeTrace { |
1316 | origin: Misc(span), | |
e9174d1e | 1317 | values: Types(ExpectedFound { |
1a4d82fc JJ |
1318 | expected: expected, |
1319 | found: actual | |
1320 | }) | |
1321 | }; | |
1322 | self.report_and_explain_type_error(trace, err); | |
1323 | } | |
1324 | ||
c1a9b12d SL |
1325 | pub fn report_conflicting_default_types(&self, |
1326 | span: Span, | |
1327 | expected: type_variable::Default<'tcx>, | |
1328 | actual: type_variable::Default<'tcx>) { | |
1329 | let trace = TypeTrace { | |
1330 | origin: Misc(span), | |
e9174d1e | 1331 | values: Types(ExpectedFound { |
c1a9b12d SL |
1332 | expected: expected.ty, |
1333 | found: actual.ty | |
1334 | }) | |
1335 | }; | |
1336 | ||
1337 | self.report_and_explain_type_error(trace, | |
e9174d1e | 1338 | &TypeError::TyParamDefaultMismatch(ExpectedFound { |
c1a9b12d SL |
1339 | expected: expected, |
1340 | found: actual | |
1341 | })); | |
1342 | } | |
1343 | ||
1a4d82fc JJ |
1344 | pub fn replace_late_bound_regions_with_fresh_var<T>( |
1345 | &self, | |
1346 | span: Span, | |
1347 | lbrct: LateBoundRegionConversionTime, | |
1348 | value: &ty::Binder<T>) | |
1349 | -> (T, FnvHashMap<ty::BoundRegion,ty::Region>) | |
62682a34 | 1350 | where T : TypeFoldable<'tcx> |
1a4d82fc | 1351 | { |
e9174d1e | 1352 | self.tcx.replace_late_bound_regions( |
1a4d82fc JJ |
1353 | value, |
1354 | |br| self.next_region_var(LateBoundRegion(span, br, lbrct))) | |
1355 | } | |
1356 | ||
1357 | /// See `verify_generic_bound` method in `region_inference` | |
1358 | pub fn verify_generic_bound(&self, | |
1359 | origin: SubregionOrigin<'tcx>, | |
1360 | kind: GenericKind<'tcx>, | |
1361 | a: ty::Region, | |
e9174d1e | 1362 | bound: VerifyBound) { |
62682a34 SL |
1363 | debug!("verify_generic_bound({:?}, {:?} <: {:?})", |
1364 | kind, | |
1365 | a, | |
e9174d1e | 1366 | bound); |
1a4d82fc | 1367 | |
e9174d1e | 1368 | self.region_vars.verify_generic_bound(origin, kind, a, bound); |
1a4d82fc JJ |
1369 | } |
1370 | ||
c34b1796 | 1371 | pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> UnitResult<'tcx> |
62682a34 | 1372 | where T: Relate<'b,'tcx> + fmt::Debug |
1a4d82fc | 1373 | { |
62682a34 | 1374 | debug!("can_equate({:?}, {:?})", a, b); |
1a4d82fc JJ |
1375 | self.probe(|_| { |
1376 | // Gin up a dummy trace, since this won't be committed | |
1377 | // anyhow. We should make this typetrace stuff more | |
1378 | // generic so we don't have to do anything quite this | |
1379 | // terrible. | |
1380 | let e = self.tcx.types.err; | |
1381 | let trace = TypeTrace { origin: Misc(codemap::DUMMY_SP), | |
1382 | values: Types(expected_found(true, e, e)) }; | |
c34b1796 AL |
1383 | self.equate(true, trace).relate(a, b) |
1384 | }).map(|_| ()) | |
1a4d82fc | 1385 | } |
c1a9b12d SL |
1386 | |
1387 | pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> { | |
1388 | let ty = self.node_type(id); | |
1389 | self.resolve_type_vars_or_error(&ty) | |
1390 | } | |
1391 | ||
e9174d1e | 1392 | pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> { |
c1a9b12d SL |
1393 | let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id)); |
1394 | self.resolve_type_vars_or_error(&ty) | |
1395 | } | |
1396 | ||
e9174d1e SL |
1397 | pub fn tables_are_tcx_tables(&self) -> bool { |
1398 | let tables: &RefCell<ty::Tables> = &self.tables; | |
1399 | let tcx_tables: &RefCell<ty::Tables> = &self.tcx.tables; | |
1400 | tables as *const _ == tcx_tables as *const _ | |
1401 | } | |
1402 | ||
c1a9b12d SL |
1403 | pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { |
1404 | let ty = self.resolve_type_vars_if_possible(&ty); | |
e9174d1e SL |
1405 | if ty.needs_infer() || |
1406 | (ty.has_closure_types() && !self.tables_are_tcx_tables()) { | |
1407 | // this can get called from typeck (by euv), and moves_by_default | |
1408 | // rightly refuses to work with inference variables, but | |
1409 | // moves_by_default has a cache, which we want to use in other | |
1410 | // cases. | |
1411 | !traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span) | |
1412 | } else { | |
1413 | ty.moves_by_default(&self.parameter_environment, span) | |
1414 | } | |
c1a9b12d SL |
1415 | } |
1416 | ||
1417 | pub fn node_method_ty(&self, method_call: ty::MethodCall) | |
1418 | -> Option<Ty<'tcx>> { | |
1419 | self.tables | |
1420 | .borrow() | |
1421 | .method_map | |
1422 | .get(&method_call) | |
1423 | .map(|method| method.ty) | |
1424 | .map(|ty| self.resolve_type_vars_if_possible(&ty)) | |
1425 | } | |
1426 | ||
1427 | pub fn node_method_id(&self, method_call: ty::MethodCall) | |
e9174d1e | 1428 | -> Option<DefId> { |
c1a9b12d SL |
1429 | self.tables |
1430 | .borrow() | |
1431 | .method_map | |
1432 | .get(&method_call) | |
1433 | .map(|method| method.def_id) | |
1434 | } | |
1435 | ||
e9174d1e | 1436 | pub fn adjustments(&self) -> Ref<NodeMap<adjustment::AutoAdjustment<'tcx>>> { |
c1a9b12d | 1437 | fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) |
e9174d1e | 1438 | -> &'a NodeMap<adjustment::AutoAdjustment<'tcx>> { |
c1a9b12d SL |
1439 | &tables.adjustments |
1440 | } | |
1441 | ||
1442 | Ref::map(self.tables.borrow(), project_adjustments) | |
1443 | } | |
1444 | ||
1445 | pub fn is_method_call(&self, id: ast::NodeId) -> bool { | |
1446 | self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) | |
1447 | } | |
1448 | ||
1449 | pub fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> { | |
1450 | self.tcx.region_maps.temporary_scope(rvalue_id) | |
1451 | } | |
1452 | ||
1453 | pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { | |
1454 | self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() | |
1455 | } | |
1456 | ||
1457 | pub fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> { | |
1458 | &self.parameter_environment | |
1459 | } | |
1460 | ||
1461 | pub fn closure_kind(&self, | |
e9174d1e | 1462 | def_id: DefId) |
c1a9b12d SL |
1463 | -> Option<ty::ClosureKind> |
1464 | { | |
1465 | self.tables.borrow().closure_kinds.get(&def_id).cloned() | |
1466 | } | |
1467 | ||
1468 | pub fn closure_type(&self, | |
e9174d1e | 1469 | def_id: DefId, |
c1a9b12d SL |
1470 | substs: &ty::ClosureSubsts<'tcx>) |
1471 | -> ty::ClosureTy<'tcx> | |
1472 | { | |
1473 | let closure_ty = self.tables | |
1474 | .borrow() | |
1475 | .closure_tys | |
1476 | .get(&def_id) | |
1477 | .unwrap() | |
1478 | .subst(self.tcx, &substs.func_substs); | |
1479 | ||
1480 | if self.normalize { | |
1481 | normalize_associated_type(&self.tcx, &closure_ty) | |
1482 | } else { | |
1483 | closure_ty | |
1484 | } | |
1485 | } | |
1a4d82fc JJ |
1486 | } |
1487 | ||
1488 | impl<'tcx> TypeTrace<'tcx> { | |
1489 | pub fn span(&self) -> Span { | |
1490 | self.origin.span() | |
1491 | } | |
1492 | ||
85aaf69f SL |
1493 | pub fn types(origin: TypeOrigin, |
1494 | a_is_expected: bool, | |
1495 | a: Ty<'tcx>, | |
1496 | b: Ty<'tcx>) | |
1497 | -> TypeTrace<'tcx> { | |
1498 | TypeTrace { | |
1499 | origin: origin, | |
1500 | values: Types(expected_found(a_is_expected, a, b)) | |
1501 | } | |
1502 | } | |
1503 | ||
1a4d82fc JJ |
1504 | pub fn dummy(tcx: &ty::ctxt<'tcx>) -> TypeTrace<'tcx> { |
1505 | TypeTrace { | |
1506 | origin: Misc(codemap::DUMMY_SP), | |
e9174d1e | 1507 | values: Types(ExpectedFound { |
1a4d82fc JJ |
1508 | expected: tcx.types.err, |
1509 | found: tcx.types.err, | |
1510 | }) | |
1511 | } | |
1512 | } | |
1513 | } | |
1514 | ||
62682a34 SL |
1515 | impl<'tcx> fmt::Debug for TypeTrace<'tcx> { |
1516 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
1517 | write!(f, "TypeTrace({:?})", self.origin) | |
1a4d82fc JJ |
1518 | } |
1519 | } | |
1520 | ||
1521 | impl TypeOrigin { | |
1522 | pub fn span(&self) -> Span { | |
1523 | match *self { | |
1524 | MethodCompatCheck(span) => span, | |
1525 | ExprAssignable(span) => span, | |
1526 | Misc(span) => span, | |
1527 | RelateTraitRefs(span) => span, | |
1528 | RelateSelfType(span) => span, | |
1529 | RelateOutputImplTypes(span) => span, | |
1530 | MatchExpressionArm(match_span, _) => match_span, | |
1531 | IfExpression(span) => span, | |
1532 | IfExpressionWithNoElse(span) => span, | |
1533 | RangeExpression(span) => span, | |
1534 | EquatePredicate(span) => span, | |
1535 | } | |
1536 | } | |
1537 | } | |
1538 | ||
1a4d82fc JJ |
1539 | impl<'tcx> SubregionOrigin<'tcx> { |
1540 | pub fn span(&self) -> Span { | |
1541 | match *self { | |
e9174d1e | 1542 | RFC1214Subregion(ref a) => a.span(), |
1a4d82fc JJ |
1543 | Subtype(ref a) => a.span(), |
1544 | InfStackClosure(a) => a, | |
1545 | InvokeClosure(a) => a, | |
1546 | DerefPointer(a) => a, | |
1547 | FreeVariable(a, _) => a, | |
1548 | IndexSlice(a) => a, | |
1549 | RelateObjectBound(a) => a, | |
1550 | RelateParamBound(a, _) => a, | |
1551 | RelateRegionParamBound(a) => a, | |
1552 | RelateDefaultParamBound(a, _) => a, | |
1553 | Reborrow(a) => a, | |
1554 | ReborrowUpvar(a, _) => a, | |
e9174d1e | 1555 | DataBorrowed(_, a) => a, |
1a4d82fc | 1556 | ReferenceOutlivesReferent(_, a) => a, |
e9174d1e | 1557 | ParameterInScope(_, a) => a, |
1a4d82fc JJ |
1558 | ExprTypeIsNotInScope(_, a) => a, |
1559 | BindingTypeIsNotValidAtDecl(a) => a, | |
1560 | CallRcvr(a) => a, | |
1561 | CallArg(a) => a, | |
1562 | CallReturn(a) => a, | |
85aaf69f | 1563 | Operand(a) => a, |
1a4d82fc JJ |
1564 | AddrOf(a) => a, |
1565 | AutoBorrow(a) => a, | |
85aaf69f | 1566 | SafeDestructor(a) => a, |
1a4d82fc JJ |
1567 | } |
1568 | } | |
1569 | } | |
1570 | ||
c34b1796 | 1571 | impl RegionVariableOrigin { |
1a4d82fc JJ |
1572 | pub fn span(&self) -> Span { |
1573 | match *self { | |
1574 | MiscVariable(a) => a, | |
1575 | PatternRegion(a) => a, | |
1576 | AddrOfRegion(a) => a, | |
1a4d82fc | 1577 | Autoref(a) => a, |
c34b1796 | 1578 | Coercion(a) => a, |
1a4d82fc JJ |
1579 | EarlyBoundRegion(a, _) => a, |
1580 | LateBoundRegion(a, _, _) => a, | |
1581 | BoundRegionInCoherence(_) => codemap::DUMMY_SP, | |
1582 | UpvarRegion(_, a) => a | |
1583 | } | |
1584 | } | |
1585 | } |