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.
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.
11 //! See the Book for more information.
13 #![allow(non_camel_case_types)]
15 pub use self::LateBoundRegionConversionTime
::*;
16 pub use self::RegionVariableOrigin
::*;
17 pub use self::SubregionOrigin
::*;
18 pub use self::TypeOrigin
::*;
19 pub use self::ValuePairs
::*;
20 pub use self::fixup_err
::*;
21 pub use middle
::ty
::IntVarValue
;
22 pub use self::freshen
::TypeFreshener
;
23 pub use self::region_inference
::GenericKind
;
25 use middle
::free_region
::FreeRegionMap
;
27 use middle
::subst
::Substs
;
28 use middle
::ty
::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric}
;
29 use middle
::ty
::{self, Ty}
;
30 use middle
::ty_fold
::{self, TypeFolder, TypeFoldable}
;
31 use middle
::ty_relate
::{Relate, RelateResult, TypeRelation}
;
32 use rustc_data_structures
::unify
::{self, UnificationTable}
;
33 use std
::cell
::{RefCell}
;
37 use syntax
::codemap
::Span
;
38 use util
::nodemap
::FnvHashMap
;
40 use self::combine
::CombineFields
;
41 use self::region_inference
::{RegionVarBindings, RegionSnapshot}
;
42 use self::error_reporting
::ErrorReporting
;
43 use self::unify_key
::ToType
;
48 pub mod error_reporting
;
53 pub mod region_inference
;
57 pub mod type_variable
;
60 pub type Bound
<T
> = Option
<T
>;
61 pub type UnitResult
<'tcx
> = RelateResult
<'tcx
, ()>; // "unify result"
62 pub type fres
<T
> = Result
<T
, fixup_err
>; // "fixup result"
64 pub struct InferCtxt
<'a
, 'tcx
: 'a
> {
65 pub tcx
: &'a ty
::ctxt
<'tcx
>,
67 // We instantiate UnificationTable with bounds<Ty> because the
68 // types that might instantiate a general type variable have an
69 // order, represented by its upper and lower bounds.
70 type_variables
: RefCell
<type_variable
::TypeVariableTable
<'tcx
>>,
72 // Map from integral variable to the kind of integer it represents
73 int_unification_table
: RefCell
<UnificationTable
<ty
::IntVid
>>,
75 // Map from floating variable to the kind of float it represents
76 float_unification_table
: RefCell
<UnificationTable
<ty
::FloatVid
>>,
78 // For region variables.
79 region_vars
: RegionVarBindings
<'a
, 'tcx
>,
82 /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
83 /// region that each late-bound region was replaced with.
84 pub type SkolemizationMap
= FnvHashMap
<ty
::BoundRegion
,ty
::Region
>;
86 /// Why did we require that the two types be related?
88 /// See `error_reporting.rs` for more details
89 #[derive(Clone, Copy, Debug)]
91 // Not yet categorized in a better way
94 // Checking that method of impl is compatible with trait
95 MethodCompatCheck(Span
),
97 // Checking that this expression can be assigned where it needs to be
98 // FIXME(eddyb) #11161 is the original Expr required?
101 // Relating trait refs when resolving vtables
102 RelateTraitRefs(Span
),
104 // Relating self types when resolving vtables
105 RelateSelfType(Span
),
107 // Relating trait type parameters to those found in impl etc
108 RelateOutputImplTypes(Span
),
110 // Computing common supertype in the arms of a match expression
111 MatchExpressionArm(Span
, Span
),
113 // Computing common supertype in an if expression
116 // Computing common supertype of an if expression with no else counter-part
117 IfExpressionWithNoElse(Span
),
119 // Computing common supertype in a range expression
120 RangeExpression(Span
),
123 EquatePredicate(Span
),
127 fn as_str(&self) -> &'
static str {
129 &TypeOrigin
::Misc(_
) |
130 &TypeOrigin
::RelateSelfType(_
) |
131 &TypeOrigin
::RelateOutputImplTypes(_
) |
132 &TypeOrigin
::ExprAssignable(_
) => "mismatched types",
133 &TypeOrigin
::RelateTraitRefs(_
) => "mismatched traits",
134 &TypeOrigin
::MethodCompatCheck(_
) => "method not compatible with trait",
135 &TypeOrigin
::MatchExpressionArm(_
, _
) => "match arms have incompatible types",
136 &TypeOrigin
::IfExpression(_
) => "if and else have incompatible types",
137 &TypeOrigin
::IfExpressionWithNoElse(_
) => "if may be missing an else clause",
138 &TypeOrigin
::RangeExpression(_
) => "start and end of range have incompatible types",
139 &TypeOrigin
::EquatePredicate(_
) => "equality predicate not satisfied",
144 impl fmt
::Display
for TypeOrigin
{
145 fn fmt(&self, f
: &mut fmt
::Formatter
) -> Result
<(),fmt
::Error
> {
146 fmt
::Display
::fmt(self.as_str(), f
)
150 /// See `error_reporting.rs` for more details
151 #[derive(Clone, Debug)]
152 pub enum ValuePairs
<'tcx
> {
153 Types(ty
::expected_found
<Ty
<'tcx
>>),
154 TraitRefs(ty
::expected_found
<ty
::TraitRef
<'tcx
>>),
155 PolyTraitRefs(ty
::expected_found
<ty
::PolyTraitRef
<'tcx
>>),
158 /// The trace designates the path through inference that we took to
159 /// encounter an error or subtyping constraint.
161 /// See `error_reporting.rs` for more details.
163 pub struct TypeTrace
<'tcx
> {
165 values
: ValuePairs
<'tcx
>,
168 /// The origin of a `r1 <= r2` constraint.
170 /// See `error_reporting.rs` for more details
171 #[derive(Clone, Debug)]
172 pub enum SubregionOrigin
<'tcx
> {
173 // Arose from a subtyping relation
174 Subtype(TypeTrace
<'tcx
>),
176 // Arose from a subtyping relation
177 DefaultExistentialBound(TypeTrace
<'tcx
>),
179 // Stack-allocated closures cannot outlive innermost loop
180 // or function so as to ensure we only require finite stack
181 InfStackClosure(Span
),
183 // Invocation of closure must be within its lifetime
186 // Dereference of reference must be within its lifetime
189 // Closure bound must not outlive captured free variables
190 FreeVariable(Span
, ast
::NodeId
),
192 // Index into slice must be within its lifetime
195 // When casting `&'a T` to an `&'b Trait` object,
196 // relating `'a` to `'b`
197 RelateObjectBound(Span
),
199 // Some type parameter was instantiated with the given type,
200 // and that type must outlive some region.
201 RelateParamBound(Span
, Ty
<'tcx
>),
203 // The given region parameter was instantiated with a region
204 // that must outlive some other region.
205 RelateRegionParamBound(Span
),
207 // A bound placed on type parameters that states that must outlive
208 // the moment of their instantiation.
209 RelateDefaultParamBound(Span
, Ty
<'tcx
>),
211 // Creating a pointer `b` to contents of another reference
214 // Creating a pointer `b` to contents of an upvar
215 ReborrowUpvar(Span
, ty
::UpvarId
),
217 // (&'a &'b T) where a >= b
218 ReferenceOutlivesReferent(Ty
<'tcx
>, Span
),
220 // The type T of an expression E must outlive the lifetime for E.
221 ExprTypeIsNotInScope(Ty
<'tcx
>, Span
),
223 // A `ref b` whose region does not enclose the decl site
224 BindingTypeIsNotValidAtDecl(Span
),
226 // Regions appearing in a method receiver must outlive method call
229 // Regions appearing in a function argument must outlive func call
232 // Region in return type of invoked fn must enclose call
235 // Operands must be in scope
238 // Region resulting from a `&` expr must enclose the `&` expr
241 // An auto-borrow that does not enclose the expr where it occurs
244 // Region constraint arriving from destructor safety
245 SafeDestructor(Span
),
248 /// Times when we replace late-bound regions with variables:
249 #[derive(Clone, Copy, Debug)]
250 pub enum LateBoundRegionConversionTime
{
251 /// when a fn is called
254 /// when two higher-ranked types are compared
257 /// when projecting an associated type
258 AssocTypeProjection(ast
::Name
),
261 /// Reasons to create a region inference variable
263 /// See `error_reporting.rs` for more details
264 #[derive(Clone, Debug)]
265 pub enum RegionVariableOrigin
{
266 // Region variables created for ill-categorized reasons,
267 // mostly indicates places in need of refactoring
270 // Regions created by a `&P` or `[...]` pattern
273 // Regions created by `&` operator
276 // Regions created as part of an autoref of a method receiver
279 // Regions created as part of an automatic coercion
282 // Region variables created as the values for early-bound regions
283 EarlyBoundRegion(Span
, ast
::Name
),
285 // Region variables created for bound regions
286 // in a function or method that is called
287 LateBoundRegion(Span
, ty
::BoundRegion
, LateBoundRegionConversionTime
),
289 UpvarRegion(ty
::UpvarId
, Span
),
291 BoundRegionInCoherence(ast
::Name
),
294 #[derive(Copy, Clone, Debug)]
296 unresolved_int_ty(IntVid
),
297 unresolved_float_ty(FloatVid
),
301 pub fn fixup_err_to_string(f
: fixup_err
) -> String
{
303 unresolved_int_ty(_
) => {
304 "cannot determine the type of this integer; add a suffix to \
305 specify the type explicitly".to_string()
307 unresolved_float_ty(_
) => {
308 "cannot determine the type of this number; add a suffix to specify \
309 the type explicitly".to_string()
311 unresolved_ty(_
) => "unconstrained type".to_string(),
315 pub fn new_infer_ctxt
<'a
, 'tcx
>(tcx
: &'a ty
::ctxt
<'tcx
>)
316 -> InferCtxt
<'a
, 'tcx
> {
319 type_variables
: RefCell
::new(type_variable
::TypeVariableTable
::new()),
320 int_unification_table
: RefCell
::new(UnificationTable
::new()),
321 float_unification_table
: RefCell
::new(UnificationTable
::new()),
322 region_vars
: RegionVarBindings
::new(tcx
),
326 /// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and
328 pub fn common_supertype
<'a
, 'tcx
>(cx
: &InferCtxt
<'a
, 'tcx
>,
335 debug
!("common_supertype({:?}, {:?})",
338 let trace
= TypeTrace
{
340 values
: Types(expected_found(a_is_expected
, a
, b
))
343 let result
= cx
.commit_if_ok(|_
| cx
.lub(a_is_expected
, trace
.clone()).relate(&a
, &b
));
347 cx
.report_and_explain_type_error(trace
, err
);
353 pub fn mk_subty
<'a
, 'tcx
>(cx
: &InferCtxt
<'a
, 'tcx
>,
360 debug
!("mk_subty({:?} <: {:?})", a
, b
);
361 cx
.sub_types(a_is_expected
, origin
, a
, b
)
364 pub fn can_mk_subty
<'a
, 'tcx
>(cx
: &InferCtxt
<'a
, 'tcx
>,
367 -> UnitResult
<'tcx
> {
368 debug
!("can_mk_subty({:?} <: {:?})", a
, b
);
370 let trace
= TypeTrace
{
371 origin
: Misc(codemap
::DUMMY_SP
),
372 values
: Types(expected_found(true, a
, b
))
374 cx
.sub(true, trace
).relate(&a
, &b
).map(|_
| ())
378 pub fn can_mk_eqty
<'a
, 'tcx
>(cx
: &InferCtxt
<'a
, 'tcx
>, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>)
381 cx
.can_equate(&a
, &b
)
384 pub fn mk_subr
<'a
, 'tcx
>(cx
: &InferCtxt
<'a
, 'tcx
>,
385 origin
: SubregionOrigin
<'tcx
>,
388 debug
!("mk_subr({:?} <: {:?})", a
, b
);
389 let snapshot
= cx
.region_vars
.start_snapshot();
390 cx
.region_vars
.make_subregion(origin
, a
, b
);
391 cx
.region_vars
.commit(snapshot
);
394 pub fn mk_eqty
<'a
, 'tcx
>(cx
: &InferCtxt
<'a
, 'tcx
>,
401 debug
!("mk_eqty({:?} <: {:?})", a
, b
);
402 cx
.commit_if_ok(|_
| cx
.eq_types(a_is_expected
, origin
, a
, b
))
405 pub fn mk_sub_poly_trait_refs
<'a
, 'tcx
>(cx
: &InferCtxt
<'a
, 'tcx
>,
408 a
: ty
::PolyTraitRef
<'tcx
>,
409 b
: ty
::PolyTraitRef
<'tcx
>)
412 debug
!("mk_sub_trait_refs({:?} <: {:?})",
414 cx
.commit_if_ok(|_
| cx
.sub_poly_trait_refs(a_is_expected
, origin
, a
.clone(), b
.clone()))
417 fn expected_found
<T
>(a_is_expected
: bool
,
420 -> ty
::expected_found
<T
>
423 ty
::expected_found {expected: a, found: b}
425 ty
::expected_found {expected: b, found: a}
429 #[must_use = "once you start a snapshot, you should always consume it"]
430 pub struct CombinedSnapshot
{
431 type_snapshot
: type_variable
::Snapshot
,
432 int_snapshot
: unify
::Snapshot
<ty
::IntVid
>,
433 float_snapshot
: unify
::Snapshot
<ty
::FloatVid
>,
434 region_vars_snapshot
: RegionSnapshot
,
437 impl<'a
, 'tcx
> InferCtxt
<'a
, 'tcx
> {
438 pub fn freshen
<T
:TypeFoldable
<'tcx
>>(&self, t
: T
) -> T
{
439 t
.fold_with(&mut self.freshener())
442 pub fn type_var_diverges(&'a
self, ty
: Ty
) -> bool
{
444 ty
::TyInfer(ty
::TyVar(vid
)) => self.type_variables
.borrow().var_diverges(vid
),
449 pub fn freshener
<'b
>(&'b
self) -> TypeFreshener
<'b
, 'tcx
> {
450 freshen
::TypeFreshener
::new(self)
453 pub fn type_is_unconstrained_numeric(&'a
self, ty
: Ty
) -> UnconstrainedNumeric
{
454 use middle
::ty
::UnconstrainedNumeric
::{Neither, UnconstrainedInt, UnconstrainedFloat}
;
456 ty
::TyInfer(ty
::IntVar(vid
)) => {
457 if self.int_unification_table
.borrow_mut().has_value(vid
) {
463 ty
::TyInfer(ty
::FloatVar(vid
)) => {
464 if self.float_unification_table
.borrow_mut().has_value(vid
) {
474 fn combine_fields(&'a
self, a_is_expected
: bool
, trace
: TypeTrace
<'tcx
>)
475 -> CombineFields
<'a
, 'tcx
> {
476 CombineFields
{infcx
: self,
477 a_is_expected
: a_is_expected
,
482 // public so that it can be used from the rustc_driver unit tests
483 pub fn equate(&'a
self, a_is_expected
: bool
, trace
: TypeTrace
<'tcx
>)
484 -> equate
::Equate
<'a
, 'tcx
>
486 self.combine_fields(a_is_expected
, trace
).equate()
489 // public so that it can be used from the rustc_driver unit tests
490 pub fn sub(&'a
self, a_is_expected
: bool
, trace
: TypeTrace
<'tcx
>)
491 -> sub
::Sub
<'a
, 'tcx
>
493 self.combine_fields(a_is_expected
, trace
).sub()
496 // public so that it can be used from the rustc_driver unit tests
497 pub fn lub(&'a
self, a_is_expected
: bool
, trace
: TypeTrace
<'tcx
>)
498 -> lub
::Lub
<'a
, 'tcx
>
500 self.combine_fields(a_is_expected
, trace
).lub()
503 // public so that it can be used from the rustc_driver unit tests
504 pub fn glb(&'a
self, a_is_expected
: bool
, trace
: TypeTrace
<'tcx
>)
505 -> glb
::Glb
<'a
, 'tcx
>
507 self.combine_fields(a_is_expected
, trace
).glb()
510 fn start_snapshot(&self) -> CombinedSnapshot
{
512 type_snapshot
: self.type_variables
.borrow_mut().snapshot(),
513 int_snapshot
: self.int_unification_table
.borrow_mut().snapshot(),
514 float_snapshot
: self.float_unification_table
.borrow_mut().snapshot(),
515 region_vars_snapshot
: self.region_vars
.start_snapshot(),
519 fn rollback_to(&self, snapshot
: CombinedSnapshot
) {
521 let CombinedSnapshot
{ type_snapshot
,
524 region_vars_snapshot
} = snapshot
;
528 .rollback_to(type_snapshot
);
529 self.int_unification_table
531 .rollback_to(int_snapshot
);
532 self.float_unification_table
534 .rollback_to(float_snapshot
);
536 .rollback_to(region_vars_snapshot
);
539 fn commit_from(&self, snapshot
: CombinedSnapshot
) {
540 debug
!("commit_from!");
541 let CombinedSnapshot
{ type_snapshot
,
544 region_vars_snapshot
} = snapshot
;
548 .commit(type_snapshot
);
549 self.int_unification_table
551 .commit(int_snapshot
);
552 self.float_unification_table
554 .commit(float_snapshot
);
556 .commit(region_vars_snapshot
);
559 /// Execute `f` and commit the bindings
560 pub fn commit_unconditionally
<R
, F
>(&self, f
: F
) -> R
where
564 let snapshot
= self.start_snapshot();
566 self.commit_from(snapshot
);
570 /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`
571 pub fn commit_if_ok
<T
, E
, F
>(&self, f
: F
) -> Result
<T
, E
> where
572 F
: FnOnce(&CombinedSnapshot
) -> Result
<T
, E
>
574 debug
!("commit_if_ok()");
575 let snapshot
= self.start_snapshot();
576 let r
= f(&snapshot
);
577 debug
!("commit_if_ok() -- r.is_ok() = {}", r
.is_ok());
579 Ok(_
) => { self.commit_from(snapshot); }
580 Err(_
) => { self.rollback_to(snapshot); }
585 /// Execute `f` and commit only the region bindings if successful.
586 /// The function f must be very careful not to leak any non-region
587 /// variables that get created.
588 pub fn commit_regions_if_ok
<T
, E
, F
>(&self, f
: F
) -> Result
<T
, E
> where
589 F
: FnOnce() -> Result
<T
, E
>
591 debug
!("commit_regions_if_ok()");
592 let CombinedSnapshot
{ type_snapshot
,
595 region_vars_snapshot
} = self.start_snapshot();
597 let r
= self.commit_if_ok(|_
| f());
599 // Roll back any non-region bindings - they should be resolved
600 // inside `f`, with, e.g. `resolve_type_vars_if_possible`.
603 .rollback_to(type_snapshot
);
604 self.int_unification_table
606 .rollback_to(int_snapshot
);
607 self.float_unification_table
609 .rollback_to(float_snapshot
);
611 // Commit region vars that may escape through resolved types.
613 .commit(region_vars_snapshot
);
618 /// Execute `f` then unroll any bindings it creates
619 pub fn probe
<R
, F
>(&self, f
: F
) -> R
where
620 F
: FnOnce(&CombinedSnapshot
) -> R
,
623 let snapshot
= self.start_snapshot();
624 let r
= f(&snapshot
);
625 self.rollback_to(snapshot
);
629 pub fn add_given(&self,
633 self.region_vars
.add_given(sub
, sup
);
636 pub fn sub_types(&self,
643 debug
!("sub_types({:?} <: {:?})", a
, b
);
644 self.commit_if_ok(|_
| {
645 let trace
= TypeTrace
::types(origin
, a_is_expected
, a
, b
);
646 self.sub(a_is_expected
, trace
).relate(&a
, &b
).map(|_
| ())
650 pub fn eq_types(&self,
657 self.commit_if_ok(|_
| {
658 let trace
= TypeTrace
::types(origin
, a_is_expected
, a
, b
);
659 self.equate(a_is_expected
, trace
).relate(&a
, &b
).map(|_
| ())
663 pub fn sub_trait_refs(&self,
666 a
: ty
::TraitRef
<'tcx
>,
667 b
: ty
::TraitRef
<'tcx
>)
670 debug
!("sub_trait_refs({:?} <: {:?})",
673 self.commit_if_ok(|_
| {
674 let trace
= TypeTrace
{
676 values
: TraitRefs(expected_found(a_is_expected
, a
.clone(), b
.clone()))
678 self.sub(a_is_expected
, trace
).relate(&a
, &b
).map(|_
| ())
682 pub fn sub_poly_trait_refs(&self,
685 a
: ty
::PolyTraitRef
<'tcx
>,
686 b
: ty
::PolyTraitRef
<'tcx
>)
689 debug
!("sub_poly_trait_refs({:?} <: {:?})",
692 self.commit_if_ok(|_
| {
693 let trace
= TypeTrace
{
695 values
: PolyTraitRefs(expected_found(a_is_expected
, a
.clone(), b
.clone()))
697 self.sub(a_is_expected
, trace
).relate(&a
, &b
).map(|_
| ())
701 pub fn construct_skolemized_subst(&self,
702 generics
: &ty
::Generics
<'tcx
>,
703 snapshot
: &CombinedSnapshot
)
704 -> (subst
::Substs
<'tcx
>, SkolemizationMap
) {
705 /*! See `higher_ranked::construct_skolemized_subst` */
707 higher_ranked
::construct_skolemized_substs(self, generics
, snapshot
)
710 pub fn skolemize_late_bound_regions
<T
>(&self,
711 value
: &ty
::Binder
<T
>,
712 snapshot
: &CombinedSnapshot
)
713 -> (T
, SkolemizationMap
)
714 where T
: TypeFoldable
<'tcx
>
716 /*! See `higher_ranked::skolemize_late_bound_regions` */
718 higher_ranked
::skolemize_late_bound_regions(self, value
, snapshot
)
721 pub fn leak_check(&self,
722 skol_map
: &SkolemizationMap
,
723 snapshot
: &CombinedSnapshot
)
726 /*! See `higher_ranked::leak_check` */
728 match higher_ranked
::leak_check(self, skol_map
, snapshot
) {
730 Err((br
, r
)) => Err(ty
::terr_regions_insufficiently_polymorphic(br
, r
))
734 pub fn plug_leaks
<T
>(&self,
735 skol_map
: SkolemizationMap
,
736 snapshot
: &CombinedSnapshot
,
739 where T
: TypeFoldable
<'tcx
>
741 /*! See `higher_ranked::plug_leaks` */
743 higher_ranked
::plug_leaks(self, skol_map
, snapshot
, value
)
746 pub fn equality_predicate(&self,
748 predicate
: &ty
::PolyEquatePredicate
<'tcx
>)
749 -> UnitResult
<'tcx
> {
750 self.commit_if_ok(|snapshot
| {
751 let (ty
::EquatePredicate(a
, b
), skol_map
) =
752 self.skolemize_late_bound_regions(predicate
, snapshot
);
753 let origin
= EquatePredicate(span
);
754 let () = try
!(mk_eqty(self, false, origin
, a
, b
));
755 self.leak_check(&skol_map
, snapshot
)
759 pub fn region_outlives_predicate(&self,
761 predicate
: &ty
::PolyRegionOutlivesPredicate
)
762 -> UnitResult
<'tcx
> {
763 self.commit_if_ok(|snapshot
| {
764 let (ty
::OutlivesPredicate(r_a
, r_b
), skol_map
) =
765 self.skolemize_late_bound_regions(predicate
, snapshot
);
766 let origin
= RelateRegionParamBound(span
);
767 let () = mk_subr(self, origin
, r_b
, r_a
); // `b : a` ==> `a <= b`
768 self.leak_check(&skol_map
, snapshot
)
772 pub fn next_ty_var_id(&self, diverging
: bool
) -> TyVid
{
778 pub fn next_ty_var(&self) -> Ty
<'tcx
> {
779 ty
::mk_var(self.tcx
, self.next_ty_var_id(false))
782 pub fn next_diverging_ty_var(&self) -> Ty
<'tcx
> {
783 ty
::mk_var(self.tcx
, self.next_ty_var_id(true))
786 pub fn next_ty_vars(&self, n
: usize) -> Vec
<Ty
<'tcx
>> {
787 (0..n
).map(|_i
| self.next_ty_var()).collect()
790 pub fn next_int_var_id(&self) -> IntVid
{
791 self.int_unification_table
796 pub fn next_float_var_id(&self) -> FloatVid
{
797 self.float_unification_table
802 pub fn next_region_var(&self, origin
: RegionVariableOrigin
) -> ty
::Region
{
803 ty
::ReInfer(ty
::ReVar(self.region_vars
.new_region_var(origin
)))
806 pub fn region_vars_for_defs(&self,
808 defs
: &[ty
::RegionParameterDef
])
811 .map(|d
| self.next_region_var(EarlyBoundRegion(span
, d
.name
)))
815 /// Given a set of generics defined on a type or impl, returns a substitution mapping each
816 /// type/region parameter to a fresh inference variable.
817 pub fn fresh_substs_for_generics(&self,
819 generics
: &ty
::Generics
<'tcx
>)
820 -> subst
::Substs
<'tcx
>
824 |_
| self.next_ty_var());
826 generics
.regions
.map(
827 |d
| self.next_region_var(EarlyBoundRegion(span
, d
.name
)));
828 subst
::Substs
::new(type_params
, region_params
)
831 /// Given a set of generics defined on a trait, returns a substitution mapping each output
832 /// type/region parameter to a fresh inference variable, and mapping the self type to
834 pub fn fresh_substs_for_trait(&self,
836 generics
: &ty
::Generics
<'tcx
>,
838 -> subst
::Substs
<'tcx
>
841 assert
!(generics
.types
.len(subst
::SelfSpace
) == 1);
842 assert
!(generics
.types
.len(subst
::FnSpace
) == 0);
843 assert
!(generics
.regions
.len(subst
::SelfSpace
) == 0);
844 assert
!(generics
.regions
.len(subst
::FnSpace
) == 0);
846 let type_parameter_count
= generics
.types
.len(subst
::TypeSpace
);
847 let type_parameters
= self.next_ty_vars(type_parameter_count
);
849 let region_param_defs
= generics
.regions
.get_slice(subst
::TypeSpace
);
850 let regions
= self.region_vars_for_defs(span
, region_param_defs
);
852 subst
::Substs
::new_trait(type_parameters
, regions
, self_ty
)
855 pub fn fresh_bound_region(&self, debruijn
: ty
::DebruijnIndex
) -> ty
::Region
{
856 self.region_vars
.new_bound(debruijn
)
859 pub fn resolve_regions_and_report_errors(&self,
860 free_regions
: &FreeRegionMap
,
861 subject_node_id
: ast
::NodeId
) {
862 let errors
= self.region_vars
.resolve_regions(free_regions
, subject_node_id
);
863 self.report_region_errors(&errors
); // see error_reporting.rs
866 pub fn ty_to_string(&self, t
: Ty
<'tcx
>) -> String
{
867 self.resolve_type_vars_if_possible(&t
).to_string()
870 pub fn tys_to_string(&self, ts
: &[Ty
<'tcx
>]) -> String
{
871 let tstrs
: Vec
<String
> = ts
.iter().map(|t
| self.ty_to_string(*t
)).collect();
872 format
!("({})", tstrs
.connect(", "))
875 pub fn trait_ref_to_string(&self, t
: &ty
::TraitRef
<'tcx
>) -> String
{
876 self.resolve_type_vars_if_possible(t
).to_string()
879 pub fn shallow_resolve(&self, typ
: Ty
<'tcx
>) -> Ty
<'tcx
> {
881 ty
::TyInfer(ty
::TyVar(v
)) => {
882 // Not entirely obvious: if `typ` is a type variable,
883 // it can be resolved to an int/float variable, which
884 // can then be recursively resolved, hence the
885 // recursion. Note though that we prevent type
886 // variables from unifying to other type variables
887 // directly (though they may be embedded
888 // structurally), and we prevent cycles in any case,
889 // so this recursion should always be of very limited
891 self.type_variables
.borrow()
893 .map(|t
| self.shallow_resolve(t
))
897 ty
::TyInfer(ty
::IntVar(v
)) => {
898 self.int_unification_table
901 .map(|v
| v
.to_type(self.tcx
))
905 ty
::TyInfer(ty
::FloatVar(v
)) => {
906 self.float_unification_table
909 .map(|v
| v
.to_type(self.tcx
))
919 pub fn resolve_type_vars_if_possible
<T
:TypeFoldable
<'tcx
>>(&self, value
: &T
) -> T
{
921 * Where possible, replaces type/int/float variables in
922 * `value` with their final value. Note that region variables
923 * are unaffected. If a type variable has not been unified, it
924 * is left as is. This is an idempotent operation that does
925 * not affect inference state in any way and so you can do it
929 let mut r
= resolve
::OpportunisticTypeResolver
::new(self);
930 value
.fold_with(&mut r
)
933 pub fn fully_resolve
<T
:TypeFoldable
<'tcx
>>(&self, value
: &T
) -> fres
<T
> {
935 * Attempts to resolve all type/region variables in
936 * `value`. Region inference must have been run already (e.g.,
937 * by calling `resolve_regions_and_report_errors`). If some
938 * variable was never unified, an `Err` results.
940 * This method is idempotent, but it not typically not invoked
941 * except during the writeback phase.
944 resolve
::fully_resolve(self, value
)
947 // [Note-Type-error-reporting]
948 // An invariant is that anytime the expected or actual type is TyError (the special
949 // error type, meaning that an error occurred when typechecking this expression),
950 // this is a derived error. The error cascaded from another error (that was already
951 // reported), so it's not useful to display it to the user.
952 // The following four methods -- type_error_message_str, type_error_message_str_with_expected,
953 // type_error_message, and report_mismatched_types -- implement this logic.
954 // They check if either the actual or expected type is TyError, and don't print the error
955 // in this case. The typechecker should only ever report type errors involving mismatched
956 // types using one of these four methods, and should not call span_err directly for such
958 pub fn type_error_message_str
<M
>(&self,
962 err
: Option
<&ty
::type_err
<'tcx
>>) where
963 M
: FnOnce(Option
<String
>, String
) -> String
,
965 self.type_error_message_str_with_expected(sp
, mk_msg
, None
, actual_ty
, err
)
968 pub fn type_error_message_str_with_expected
<M
>(&self,
971 expected_ty
: Option
<Ty
<'tcx
>>,
973 err
: Option
<&ty
::type_err
<'tcx
>>) where
974 M
: FnOnce(Option
<String
>, String
) -> String
,
976 debug
!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty
, actual_ty
);
978 let resolved_expected
= expected_ty
.map(|e_ty
| self.resolve_type_vars_if_possible(&e_ty
));
980 match resolved_expected
{
981 Some(t
) if ty
::type_is_error(t
) => (),
983 let error_str
= err
.map_or("".to_string(), |t_err
| {
984 format
!(" ({})", t_err
)
987 self.tcx
.sess
.span_err(sp
, &format
!("{}{}",
988 mk_msg(resolved_expected
.map(|t
| self.ty_to_string(t
)), actual_ty
),
991 if let Some(err
) = err
{
992 ty
::note_and_explain_type_err(self.tcx
, err
, sp
)
998 pub fn type_error_message
<M
>(&self,
1001 actual_ty
: Ty
<'tcx
>,
1002 err
: Option
<&ty
::type_err
<'tcx
>>) where
1003 M
: FnOnce(String
) -> String
,
1005 let actual_ty
= self.resolve_type_vars_if_possible(&actual_ty
);
1007 // Don't report an error if actual type is TyError.
1008 if ty
::type_is_error(actual_ty
) {
1012 self.type_error_message_str(sp
,
1013 move |_e
, a
| { mk_msg(a) }
,
1014 self.ty_to_string(actual_ty
), err
);
1017 pub fn report_mismatched_types(&self,
1021 err
: &ty
::type_err
<'tcx
>) {
1022 let trace
= TypeTrace
{
1024 values
: Types(ty
::expected_found
{
1029 self.report_and_explain_type_error(trace
, err
);
1032 pub fn replace_late_bound_regions_with_fresh_var
<T
>(
1035 lbrct
: LateBoundRegionConversionTime
,
1036 value
: &ty
::Binder
<T
>)
1037 -> (T
, FnvHashMap
<ty
::BoundRegion
,ty
::Region
>)
1038 where T
: TypeFoldable
<'tcx
>
1040 ty_fold
::replace_late_bound_regions(
1043 |br
| self.next_region_var(LateBoundRegion(span
, br
, lbrct
)))
1046 /// See `verify_generic_bound` method in `region_inference`
1047 pub fn verify_generic_bound(&self,
1048 origin
: SubregionOrigin
<'tcx
>,
1049 kind
: GenericKind
<'tcx
>,
1051 bs
: Vec
<ty
::Region
>) {
1052 debug
!("verify_generic_bound({:?}, {:?} <: {:?})",
1057 self.region_vars
.verify_generic_bound(origin
, kind
, a
, bs
);
1060 pub fn can_equate
<'b
,T
>(&'b
self, a
: &T
, b
: &T
) -> UnitResult
<'tcx
>
1061 where T
: Relate
<'b
,'tcx
> + fmt
::Debug
1063 debug
!("can_equate({:?}, {:?})", a
, b
);
1065 // Gin up a dummy trace, since this won't be committed
1066 // anyhow. We should make this typetrace stuff more
1067 // generic so we don't have to do anything quite this
1069 let e
= self.tcx
.types
.err
;
1070 let trace
= TypeTrace
{ origin
: Misc(codemap
::DUMMY_SP
),
1071 values
: Types(expected_found(true, e
, e
)) };
1072 self.equate(true, trace
).relate(a
, b
)
1077 impl<'tcx
> TypeTrace
<'tcx
> {
1078 pub fn span(&self) -> Span
{
1082 pub fn types(origin
: TypeOrigin
,
1083 a_is_expected
: bool
,
1086 -> TypeTrace
<'tcx
> {
1089 values
: Types(expected_found(a_is_expected
, a
, b
))
1093 pub fn dummy(tcx
: &ty
::ctxt
<'tcx
>) -> TypeTrace
<'tcx
> {
1095 origin
: Misc(codemap
::DUMMY_SP
),
1096 values
: Types(ty
::expected_found
{
1097 expected
: tcx
.types
.err
,
1098 found
: tcx
.types
.err
,
1104 impl<'tcx
> fmt
::Debug
for TypeTrace
<'tcx
> {
1105 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1106 write
!(f
, "TypeTrace({:?})", self.origin
)
1111 pub fn span(&self) -> Span
{
1113 MethodCompatCheck(span
) => span
,
1114 ExprAssignable(span
) => span
,
1116 RelateTraitRefs(span
) => span
,
1117 RelateSelfType(span
) => span
,
1118 RelateOutputImplTypes(span
) => span
,
1119 MatchExpressionArm(match_span
, _
) => match_span
,
1120 IfExpression(span
) => span
,
1121 IfExpressionWithNoElse(span
) => span
,
1122 RangeExpression(span
) => span
,
1123 EquatePredicate(span
) => span
,
1128 impl<'tcx
> SubregionOrigin
<'tcx
> {
1129 pub fn span(&self) -> Span
{
1131 Subtype(ref a
) => a
.span(),
1132 DefaultExistentialBound(ref a
) => a
.span(),
1133 InfStackClosure(a
) => a
,
1134 InvokeClosure(a
) => a
,
1135 DerefPointer(a
) => a
,
1136 FreeVariable(a
, _
) => a
,
1138 RelateObjectBound(a
) => a
,
1139 RelateParamBound(a
, _
) => a
,
1140 RelateRegionParamBound(a
) => a
,
1141 RelateDefaultParamBound(a
, _
) => a
,
1143 ReborrowUpvar(a
, _
) => a
,
1144 ReferenceOutlivesReferent(_
, a
) => a
,
1145 ExprTypeIsNotInScope(_
, a
) => a
,
1146 BindingTypeIsNotValidAtDecl(a
) => a
,
1153 SafeDestructor(a
) => a
,
1158 impl RegionVariableOrigin
{
1159 pub fn span(&self) -> Span
{
1161 MiscVariable(a
) => a
,
1162 PatternRegion(a
) => a
,
1163 AddrOfRegion(a
) => a
,
1166 EarlyBoundRegion(a
, _
) => a
,
1167 LateBoundRegion(a
, _
, _
) => a
,
1168 BoundRegionInCoherence(_
) => codemap
::DUMMY_SP
,
1169 UpvarRegion(_
, a
) => a