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