2014-02-10 15:36:31 +01:00
|
|
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2015-02-09 20:23:16 -05:00
|
|
|
//! See the Book for more information.
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2014-11-17 15:25:37 -05:00
|
|
|
pub use self::LateBoundRegionConversionTime::*;
|
|
|
|
pub use self::RegionVariableOrigin::*;
|
|
|
|
pub use self::SubregionOrigin::*;
|
2014-11-06 00:05:53 -08:00
|
|
|
pub use self::ValuePairs::*;
|
2016-03-22 17:30:57 +02:00
|
|
|
pub use ty::IntVarValue;
|
2014-12-12 06:13:42 -05:00
|
|
|
pub use self::freshen::TypeFreshener;
|
2015-08-07 10:33:18 -04:00
|
|
|
pub use self::region_inference::{GenericKind, VerifyBound};
|
2013-01-29 16:26:16 -08:00
|
|
|
|
2016-03-29 12:54:26 +03:00
|
|
|
use hir::def_id::DefId;
|
2016-03-29 08:50:44 +03:00
|
|
|
use hir;
|
2015-04-18 11:23:14 -04:00
|
|
|
use middle::free_region::FreeRegionMap;
|
2015-06-25 13:08:10 -07:00
|
|
|
use middle::mem_categorization as mc;
|
|
|
|
use middle::mem_categorization::McResult;
|
2016-11-13 19:42:15 -07:00
|
|
|
use middle::lang_items;
|
2016-05-11 04:14:41 +03:00
|
|
|
use mir::tcx::LvalueTy;
|
2016-10-09 11:36:12 -07:00
|
|
|
use ty::subst::{Kind, Subst, Substs};
|
2016-03-22 17:30:57 +02:00
|
|
|
use ty::{TyVid, IntVid, FloatVid};
|
|
|
|
use ty::{self, Ty, TyCtxt};
|
|
|
|
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
|
2016-07-16 19:38:17 +03:00
|
|
|
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
2016-03-22 17:30:57 +02:00
|
|
|
use ty::relate::{Relate, RelateResult, TypeRelation};
|
2016-11-07 13:25:06 -05:00
|
|
|
use traits::{self, ObligationCause, PredicateObligations, Reveal};
|
2015-04-07 06:12:21 -04:00
|
|
|
use rustc_data_structures::unify::{self, UnificationTable};
|
2016-05-11 04:14:41 +03:00
|
|
|
use std::cell::{Cell, RefCell, Ref, RefMut};
|
2015-03-19 14:49:28 -07:00
|
|
|
use std::fmt;
|
2017-01-06 21:54:24 +02:00
|
|
|
use std::ops::Deref;
|
2013-01-08 19:37:25 -08:00
|
|
|
use syntax::ast;
|
2016-06-21 18:08:13 -04:00
|
|
|
use errors::DiagnosticBuilder;
|
|
|
|
use syntax_pos::{self, Span, DUMMY_SP};
|
2017-01-06 21:54:24 +02:00
|
|
|
use util::nodemap::{FxHashMap, FxHashSet};
|
2016-12-23 20:48:21 -07:00
|
|
|
use arena::DroplessArena;
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2015-03-22 15:11:56 -04:00
|
|
|
use self::combine::CombineFields;
|
2016-05-21 08:16:07 -04:00
|
|
|
use self::higher_ranked::HrMatchResult;
|
2014-10-09 17:19:50 -04:00
|
|
|
use self::region_inference::{RegionVarBindings, RegionSnapshot};
|
2016-11-28 10:08:08 -08:00
|
|
|
use self::type_variable::TypeVariableOrigin;
|
2015-04-07 06:12:21 -04:00
|
|
|
use self::unify_key::ToType;
|
2014-10-09 17:19:50 -04:00
|
|
|
|
2016-07-25 13:08:48 -07:00
|
|
|
mod bivariate;
|
|
|
|
mod combine;
|
|
|
|
mod equate;
|
2014-07-22 07:46:36 -04:00
|
|
|
pub mod error_reporting;
|
2016-11-08 16:18:44 -05:00
|
|
|
mod fudge;
|
2016-07-25 13:08:48 -07:00
|
|
|
mod glb;
|
2014-12-12 14:55:07 -05:00
|
|
|
mod higher_ranked;
|
2013-01-29 16:26:16 -08:00
|
|
|
pub mod lattice;
|
2016-07-25 13:08:48 -07:00
|
|
|
mod lub;
|
2013-01-29 16:26:16 -08:00
|
|
|
pub mod region_inference;
|
|
|
|
pub mod resolve;
|
2014-12-12 06:13:42 -05:00
|
|
|
mod freshen;
|
2016-07-25 13:08:48 -07:00
|
|
|
mod sub;
|
2014-07-22 07:46:36 -04:00
|
|
|
pub mod type_variable;
|
2015-04-07 06:12:21 -04:00
|
|
|
pub mod unify_key;
|
2013-01-29 16:26:16 -08:00
|
|
|
|
2016-05-21 08:16:07 -04:00
|
|
|
#[must_use]
|
2016-03-29 20:06:42 -07:00
|
|
|
pub struct InferOk<'tcx, T> {
|
|
|
|
pub value: T,
|
|
|
|
pub obligations: PredicateObligations<'tcx>,
|
|
|
|
}
|
|
|
|
pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>;
|
|
|
|
|
2013-01-29 16:26:16 -08:00
|
|
|
pub type Bound<T> = Option<T>;
|
2015-03-22 15:11:56 -04:00
|
|
|
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
|
2015-07-10 19:16:35 -07:00
|
|
|
pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
|
2013-01-29 16:26:16 -08:00
|
|
|
|
2017-01-25 16:24:00 -05:00
|
|
|
/// A version of &ty::TypeckTables which can be `Missing` (not needed),
|
2017-01-06 21:54:24 +02:00
|
|
|
/// `InProgress` (during typeck) or `Interned` (result of typeck).
|
|
|
|
/// Only the `InProgress` version supports `borrow_mut`.
|
2016-05-11 04:14:41 +03:00
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
2017-01-25 16:24:00 -05:00
|
|
|
Interned(&'a ty::TypeckTables<'gcx>),
|
|
|
|
InProgress(&'a RefCell<ty::TypeckTables<'tcx>>),
|
2017-01-06 21:54:24 +02:00
|
|
|
Missing
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum InferTablesRef<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
2017-01-25 16:24:00 -05:00
|
|
|
Interned(&'a ty::TypeckTables<'gcx>),
|
|
|
|
InProgress(Ref<'a, ty::TypeckTables<'tcx>>)
|
2017-01-06 21:54:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'gcx, 'tcx> Deref for InferTablesRef<'a, 'gcx, 'tcx> {
|
2017-01-25 16:24:00 -05:00
|
|
|
type Target = ty::TypeckTables<'tcx>;
|
2017-01-06 21:54:24 +02:00
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
match *self {
|
|
|
|
InferTablesRef::Interned(tables) => tables,
|
|
|
|
InferTablesRef::InProgress(ref tables) => tables
|
|
|
|
}
|
|
|
|
}
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> {
|
2017-01-06 21:54:24 +02:00
|
|
|
pub fn borrow(self) -> InferTablesRef<'a, 'gcx, 'tcx> {
|
2016-05-11 04:14:41 +03:00
|
|
|
match self {
|
2017-01-06 21:54:24 +02:00
|
|
|
InferTables::Interned(tables) => InferTablesRef::Interned(tables),
|
|
|
|
InferTables::InProgress(tables) => InferTablesRef::InProgress(tables.borrow()),
|
|
|
|
InferTables::Missing => {
|
|
|
|
bug!("InferTables: infcx.tables.borrow() with no tables")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:24:00 -05:00
|
|
|
pub fn expect_interned(self) -> &'a ty::TypeckTables<'gcx> {
|
2017-01-06 21:54:24 +02:00
|
|
|
match self {
|
|
|
|
InferTables::Interned(tables) => tables,
|
|
|
|
InferTables::InProgress(_) => {
|
|
|
|
bug!("InferTables: infcx.tables.expect_interned() during type-checking");
|
|
|
|
}
|
|
|
|
InferTables::Missing => {
|
|
|
|
bug!("InferTables: infcx.tables.expect_interned() with no tables")
|
|
|
|
}
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:24:00 -05:00
|
|
|
pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> {
|
2016-05-11 04:14:41 +03:00
|
|
|
match self {
|
2017-01-06 21:54:24 +02:00
|
|
|
InferTables::Interned(_) => {
|
2016-05-11 04:14:41 +03:00
|
|
|
bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking");
|
|
|
|
}
|
2017-01-06 21:54:24 +02:00
|
|
|
InferTables::InProgress(tables) => tables.borrow_mut(),
|
|
|
|
InferTables::Missing => {
|
|
|
|
bug!("InferTables: infcx.tables.borrow_mut() with no tables")
|
|
|
|
}
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-03 05:23:22 +03:00
|
|
|
pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|
|
|
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2016-05-11 04:14:41 +03:00
|
|
|
pub tables: InferTables<'a, 'gcx, 'tcx>,
|
2015-06-25 13:08:10 -07:00
|
|
|
|
2016-05-21 08:18:52 -04:00
|
|
|
// Cache for projections. This cache is snapshotted along with the
|
|
|
|
// infcx.
|
|
|
|
//
|
|
|
|
// Public so that `traits::project` can use it.
|
|
|
|
pub projection_cache: RefCell<traits::ProjectionCache<'tcx>>,
|
|
|
|
|
2014-09-13 21:09:25 +03:00
|
|
|
// We instantiate UnificationTable with bounds<Ty> because the
|
2012-11-29 16:41:39 -08:00
|
|
|
// types that might instantiate a general type variable have an
|
|
|
|
// order, represented by its upper and lower bounds.
|
2016-11-28 10:08:08 -08:00
|
|
|
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2013-01-22 07:02:40 -08:00
|
|
|
// Map from integral variable to the kind of integer it represents
|
2015-01-21 20:25:24 -05:00
|
|
|
int_unification_table: RefCell<UnificationTable<ty::IntVid>>,
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2013-01-22 07:02:40 -08:00
|
|
|
// Map from floating variable to the kind of float it represents
|
2015-01-21 20:25:24 -05:00
|
|
|
float_unification_table: RefCell<UnificationTable<ty::FloatVid>>,
|
2012-11-29 16:41:39 -08:00
|
|
|
|
|
|
|
// For region variables.
|
2016-05-02 18:07:47 +03:00
|
|
|
region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
|
2015-06-24 13:40:54 -07:00
|
|
|
|
2016-03-25 05:22:52 +02:00
|
|
|
pub parameter_environment: ty::ParameterEnvironment<'gcx>,
|
2015-06-24 13:40:54 -07:00
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
/// Caches the results of trait selection. This cache is used
|
|
|
|
/// for things that have to do with the parameters in scope.
|
|
|
|
pub selection_cache: traits::SelectionCache<'tcx>,
|
|
|
|
|
|
|
|
/// Caches the results of trait evaluation.
|
|
|
|
pub evaluation_cache: traits::EvaluationCache<'tcx>,
|
|
|
|
|
2015-09-24 19:58:00 +03:00
|
|
|
// the set of predicates on which errors have been reported, to
|
|
|
|
// avoid reporting the same error twice.
|
2016-11-08 14:02:55 +11:00
|
|
|
pub reported_trait_errors: RefCell<FxHashSet<traits::TraitErrorKey<'tcx>>>,
|
2015-09-24 19:58:00 +03:00
|
|
|
|
2016-02-23 12:47:09 -08:00
|
|
|
// Sadly, the behavior of projection varies a bit depending on the
|
|
|
|
// stage of compilation. The specifics are given in the
|
2016-06-30 21:22:47 +03:00
|
|
|
// documentation for `Reveal`.
|
|
|
|
projection_mode: Reveal,
|
2016-02-23 12:47:09 -08:00
|
|
|
|
2016-03-15 04:49:10 -04:00
|
|
|
// When an error occurs, we want to avoid reporting "derived"
|
|
|
|
// errors that are due to this original failure. Normally, we
|
|
|
|
// handle this with the `err_count_on_creation` count, which
|
|
|
|
// basically just tracks how many errors were reported when we
|
|
|
|
// started type-checking a fn and checks to see if any new errors
|
|
|
|
// have been reported since then. Not great, but it works.
|
|
|
|
//
|
|
|
|
// However, when errors originated in other passes -- notably
|
|
|
|
// resolve -- this heuristic breaks down. Therefore, we have this
|
|
|
|
// auxiliary flag that one can set whenever one creates a
|
|
|
|
// type-error that is due to an error in a prior pass.
|
|
|
|
//
|
|
|
|
// Don't read this flag directly, call `is_tainted_by_errors()`
|
|
|
|
// and `set_tainted_by_errors()`.
|
|
|
|
tainted_by_errors_flag: Cell<bool>,
|
|
|
|
|
|
|
|
// Track how many errors were reported when this infcx is created.
|
|
|
|
// If the number of errors increases, that's also a sign (line
|
|
|
|
// `tained_by_errors`) to avoid reporting certain kinds of errors.
|
2015-06-25 13:08:10 -07:00
|
|
|
err_count_on_creation: usize,
|
2016-05-25 21:12:35 +03:00
|
|
|
|
|
|
|
// This flag is used for debugging, and is set to true if there are
|
|
|
|
// any obligations set during the current snapshot. In that case, the
|
|
|
|
// snapshot can't be rolled back.
|
|
|
|
pub obligations_in_snapshot: Cell<bool>,
|
2013-01-08 14:00:45 -08:00
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2014-12-12 14:55:07 -05:00
|
|
|
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
|
2014-12-12 06:37:42 -05:00
|
|
|
/// region that each late-bound region was replaced with.
|
2016-11-08 14:02:55 +11:00
|
|
|
pub type SkolemizationMap<'tcx> = FxHashMap<ty::BoundRegion, &'tcx ty::Region>;
|
2014-12-12 06:37:42 -05:00
|
|
|
|
2013-05-23 21:37:37 -04:00
|
|
|
/// See `error_reporting.rs` for more details
|
2015-01-28 08:34:18 -05:00
|
|
|
#[derive(Clone, Debug)]
|
2014-09-29 22:11:30 +03:00
|
|
|
pub enum ValuePairs<'tcx> {
|
2015-09-06 21:51:58 +03:00
|
|
|
Types(ExpectedFound<Ty<'tcx>>),
|
|
|
|
TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
|
|
|
|
PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// The trace designates the path through inference that we took to
|
|
|
|
/// encounter an error or subtyping constraint.
|
|
|
|
///
|
|
|
|
/// See `error_reporting.rs` for more details.
|
2015-06-18 08:51:23 +03:00
|
|
|
#[derive(Clone)]
|
2014-09-29 22:11:30 +03:00
|
|
|
pub struct TypeTrace<'tcx> {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: ObligationCause<'tcx>,
|
2014-09-29 22:11:30 +03:00
|
|
|
values: ValuePairs<'tcx>,
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// The origin of a `r1 <= r2` constraint.
|
|
|
|
///
|
|
|
|
/// See `error_reporting.rs` for more details
|
2015-01-28 08:34:18 -05:00
|
|
|
#[derive(Clone, Debug)]
|
2014-09-29 22:11:30 +03:00
|
|
|
pub enum SubregionOrigin<'tcx> {
|
2013-05-23 21:37:37 -04:00
|
|
|
// Arose from a subtyping relation
|
2014-09-29 22:11:30 +03:00
|
|
|
Subtype(TypeTrace<'tcx>),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
2013-06-25 12:04:50 -04:00
|
|
|
// Stack-allocated closures cannot outlive innermost loop
|
|
|
|
// or function so as to ensure we only require finite stack
|
2013-08-31 18:13:04 +02:00
|
|
|
InfStackClosure(Span),
|
2013-06-25 12:04:50 -04:00
|
|
|
|
2013-05-23 21:37:37 -04:00
|
|
|
// Invocation of closure must be within its lifetime
|
2013-08-31 18:13:04 +02:00
|
|
|
InvokeClosure(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
2014-01-07 18:49:13 -08:00
|
|
|
// Dereference of reference must be within its lifetime
|
2013-08-31 18:13:04 +02:00
|
|
|
DerefPointer(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Closure bound must not outlive captured free variables
|
2014-02-07 14:43:48 -05:00
|
|
|
FreeVariable(Span, ast::NodeId),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Index into slice must be within its lifetime
|
2013-08-31 18:13:04 +02:00
|
|
|
IndexSlice(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// When casting `&'a T` to an `&'b Trait` object,
|
|
|
|
// relating `'a` to `'b`
|
2013-08-31 18:13:04 +02:00
|
|
|
RelateObjectBound(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
2014-11-15 17:25:05 -05:00
|
|
|
// Some type parameter was instantiated with the given type,
|
2014-08-27 21:46:52 -04:00
|
|
|
// and that type must outlive some region.
|
2014-09-29 22:11:30 +03:00
|
|
|
RelateParamBound(Span, Ty<'tcx>),
|
2014-08-27 21:46:52 -04:00
|
|
|
|
|
|
|
// The given region parameter was instantiated with a region
|
|
|
|
// that must outlive some other region.
|
|
|
|
RelateRegionParamBound(Span),
|
|
|
|
|
|
|
|
// A bound placed on type parameters that states that must outlive
|
|
|
|
// the moment of their instantiation.
|
2014-09-29 22:11:30 +03:00
|
|
|
RelateDefaultParamBound(Span, Ty<'tcx>),
|
2014-08-27 21:46:52 -04:00
|
|
|
|
2014-01-07 18:49:13 -08:00
|
|
|
// Creating a pointer `b` to contents of another reference
|
2013-08-31 18:13:04 +02:00
|
|
|
Reborrow(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
2014-02-07 14:43:48 -05:00
|
|
|
// Creating a pointer `b` to contents of an upvar
|
|
|
|
ReborrowUpvar(Span, ty::UpvarId),
|
|
|
|
|
2015-08-07 10:28:51 -04:00
|
|
|
// Data with type `Ty<'tcx>` was borrowed
|
|
|
|
DataBorrowed(Ty<'tcx>, Span),
|
|
|
|
|
2013-05-23 21:37:37 -04:00
|
|
|
// (&'a &'b T) where a >= b
|
2014-09-29 22:11:30 +03:00
|
|
|
ReferenceOutlivesReferent(Ty<'tcx>, Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
2015-08-07 10:28:51 -04:00
|
|
|
// Type or region parameters must be in scope.
|
|
|
|
ParameterInScope(ParameterOrigin, Span),
|
|
|
|
|
2014-08-27 21:46:52 -04:00
|
|
|
// The type T of an expression E must outlive the lifetime for E.
|
2014-09-29 22:11:30 +03:00
|
|
|
ExprTypeIsNotInScope(Ty<'tcx>, Span),
|
2014-08-27 21:46:52 -04:00
|
|
|
|
2013-05-23 21:37:37 -04:00
|
|
|
// A `ref b` whose region does not enclose the decl site
|
2013-08-31 18:13:04 +02:00
|
|
|
BindingTypeIsNotValidAtDecl(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Regions appearing in a method receiver must outlive method call
|
2013-08-31 18:13:04 +02:00
|
|
|
CallRcvr(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Regions appearing in a function argument must outlive func call
|
2013-08-31 18:13:04 +02:00
|
|
|
CallArg(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Region in return type of invoked fn must enclose call
|
2013-08-31 18:13:04 +02:00
|
|
|
CallReturn(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
2015-02-12 12:48:54 -05:00
|
|
|
// Operands must be in scope
|
|
|
|
Operand(Span),
|
|
|
|
|
2013-05-23 21:37:37 -04:00
|
|
|
// Region resulting from a `&` expr must enclose the `&` expr
|
2013-08-31 18:13:04 +02:00
|
|
|
AddrOf(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// An auto-borrow that does not enclose the expr where it occurs
|
2013-08-31 18:13:04 +02:00
|
|
|
AutoBorrow(Span),
|
2014-10-27 12:55:16 +01:00
|
|
|
|
|
|
|
// Region constraint arriving from destructor safety
|
|
|
|
SafeDestructor(Span),
|
2016-10-05 10:17:14 -04:00
|
|
|
|
|
|
|
// Comparing the signature and requirements of an impl method against
|
|
|
|
// the containing trait.
|
|
|
|
CompareImplMethodObligation {
|
|
|
|
span: Span,
|
|
|
|
item_name: ast::Name,
|
|
|
|
impl_item_def_id: DefId,
|
|
|
|
trait_item_def_id: DefId,
|
2016-10-12 16:38:58 -04:00
|
|
|
|
|
|
|
// this is `Some(_)` if this error arises from the bug fix for
|
|
|
|
// #18937. This is a temporary measure.
|
|
|
|
lint_id: Option<ast::NodeId>,
|
2016-10-05 10:17:14 -04:00
|
|
|
},
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
|
2015-08-07 10:28:51 -04:00
|
|
|
/// Places that type/region parameters can appear.
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
pub enum ParameterOrigin {
|
|
|
|
Path, // foo::bar
|
|
|
|
MethodCall, // foo.bar() <-- parameters on impl providing bar()
|
|
|
|
OverloadedOperator, // a + b when overloaded
|
|
|
|
OverloadedDeref, // *a when overloaded
|
|
|
|
}
|
|
|
|
|
2014-11-05 22:06:04 -05:00
|
|
|
/// Times when we replace late-bound regions with variables:
|
2015-01-28 08:34:18 -05:00
|
|
|
#[derive(Clone, Copy, Debug)]
|
2014-11-05 22:06:04 -05:00
|
|
|
pub enum LateBoundRegionConversionTime {
|
|
|
|
/// when a fn is called
|
|
|
|
FnCall,
|
|
|
|
|
2014-11-15 16:22:22 -05:00
|
|
|
/// when two higher-ranked types are compared
|
|
|
|
HigherRankedType,
|
2014-12-17 14:16:28 -05:00
|
|
|
|
|
|
|
/// when projecting an associated type
|
|
|
|
AssocTypeProjection(ast::Name),
|
2014-11-05 22:06:04 -05:00
|
|
|
}
|
|
|
|
|
2013-05-23 21:37:37 -04:00
|
|
|
/// Reasons to create a region inference variable
|
|
|
|
///
|
|
|
|
/// See `error_reporting.rs` for more details
|
2015-01-28 08:34:18 -05:00
|
|
|
#[derive(Clone, Debug)]
|
2015-03-10 07:02:27 -04:00
|
|
|
pub enum RegionVariableOrigin {
|
2013-05-23 21:37:37 -04:00
|
|
|
// Region variables created for ill-categorized reasons,
|
|
|
|
// mostly indicates places in need of refactoring
|
2013-08-31 18:13:04 +02:00
|
|
|
MiscVariable(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Regions created by a `&P` or `[...]` pattern
|
2013-08-31 18:13:04 +02:00
|
|
|
PatternRegion(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Regions created by `&` operator
|
2013-08-31 18:13:04 +02:00
|
|
|
AddrOfRegion(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Regions created as part of an autoref of a method receiver
|
2013-08-31 18:13:04 +02:00
|
|
|
Autoref(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
|
|
|
// Regions created as part of an automatic coercion
|
2015-03-10 07:02:27 -04:00
|
|
|
Coercion(Span),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
2014-03-07 08:43:39 +01:00
|
|
|
// Region variables created as the values for early-bound regions
|
2017-01-06 14:35:23 -05:00
|
|
|
EarlyBoundRegion(Span, ast::Name, Option<ty::Issue32330>),
|
2014-03-07 08:43:39 +01:00
|
|
|
|
2013-05-23 21:37:37 -04:00
|
|
|
// Region variables created for bound regions
|
|
|
|
// in a function or method that is called
|
2014-11-05 22:06:04 -05:00
|
|
|
LateBoundRegion(Span, ty::BoundRegion, LateBoundRegionConversionTime),
|
2013-05-23 21:37:37 -04:00
|
|
|
|
2014-02-07 14:43:48 -05:00
|
|
|
UpvarRegion(ty::UpvarId, Span),
|
|
|
|
|
2014-03-07 08:43:39 +01:00
|
|
|
BoundRegionInCoherence(ast::Name),
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
2015-07-10 19:16:35 -07:00
|
|
|
pub enum FixupError {
|
|
|
|
UnresolvedIntTy(IntVid),
|
|
|
|
UnresolvedFloatTy(FloatVid),
|
|
|
|
UnresolvedTy(TyVid)
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-03-17 00:15:31 +02:00
|
|
|
impl fmt::Display for FixupError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
use self::FixupError::*;
|
|
|
|
|
|
|
|
match *self {
|
|
|
|
UnresolvedIntTy(_) => {
|
|
|
|
write!(f, "cannot determine the type of this integer; \
|
|
|
|
add a suffix to specify the type explicitly")
|
|
|
|
}
|
|
|
|
UnresolvedFloatTy(_) => {
|
|
|
|
write!(f, "cannot determine the type of this number; \
|
|
|
|
add a suffix to specify the type explicitly")
|
|
|
|
}
|
|
|
|
UnresolvedTy(_) => write!(f, "unconstrained type")
|
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-06 21:54:24 +02:00
|
|
|
pub trait InferEnv<'a, 'tcx> {
|
|
|
|
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
2017-01-25 16:24:00 -05:00
|
|
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
|
|
Option<ty::TypeckTables<'tcx>>,
|
2017-01-06 21:54:24 +02:00
|
|
|
Option<ty::ParameterEnvironment<'tcx>>);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
|
|
|
|
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
2017-01-25 16:24:00 -05:00
|
|
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
|
|
Option<ty::TypeckTables<'tcx>>,
|
2017-01-06 21:54:24 +02:00
|
|
|
Option<ty::ParameterEnvironment<'tcx>>) {
|
|
|
|
(None, None, None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParameterEnvironment<'tcx> {
|
|
|
|
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
2017-01-25 16:24:00 -05:00
|
|
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
|
|
Option<ty::TypeckTables<'tcx>>,
|
2017-01-06 21:54:24 +02:00
|
|
|
Option<ty::ParameterEnvironment<'tcx>>) {
|
|
|
|
(None, None, Some(self))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:24:00 -05:00
|
|
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
|
2017-01-06 21:54:24 +02:00
|
|
|
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
2017-01-25 16:24:00 -05:00
|
|
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
|
|
Option<ty::TypeckTables<'tcx>>,
|
2017-01-06 21:54:24 +02:00
|
|
|
Option<ty::ParameterEnvironment<'tcx>>) {
|
|
|
|
(Some(self.0), None, Some(self.1))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:24:00 -05:00
|
|
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
|
2017-01-06 21:54:24 +02:00
|
|
|
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
2017-01-25 16:24:00 -05:00
|
|
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
|
|
Option<ty::TypeckTables<'tcx>>,
|
2017-01-06 21:54:24 +02:00
|
|
|
Option<ty::ParameterEnvironment<'tcx>>) {
|
|
|
|
(None, Some(self.0), Some(self.1))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
|
|
|
|
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
2017-01-25 16:24:00 -05:00
|
|
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
|
|
Option<ty::TypeckTables<'tcx>>,
|
2017-01-06 21:54:24 +02:00
|
|
|
Option<ty::ParameterEnvironment<'tcx>>) {
|
2017-01-26 02:41:06 +02:00
|
|
|
let item_id = tcx.hir.body_owner(self);
|
|
|
|
(Some(tcx.item_tables(tcx.hir.local_def_id(item_id))),
|
2017-01-06 21:54:24 +02:00
|
|
|
None,
|
|
|
|
Some(ty::ParameterEnvironment::for_item(tcx, item_id)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 04:14:41 +03:00
|
|
|
/// Helper type of a temporary returned by tcx.infer_ctxt(...).
|
|
|
|
/// Necessary because we can't write the following bound:
|
|
|
|
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
|
|
|
|
pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|
|
|
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
2016-12-23 20:48:21 -07:00
|
|
|
arena: DroplessArena,
|
2017-01-25 16:24:00 -05:00
|
|
|
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
|
|
|
|
tables: Option<&'a ty::TypeckTables<'gcx>>,
|
2016-05-11 04:14:41 +03:00
|
|
|
param_env: Option<ty::ParameterEnvironment<'gcx>>,
|
2016-06-30 21:22:47 +03:00
|
|
|
projection_mode: Reveal,
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
2017-01-06 21:54:24 +02:00
|
|
|
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self,
|
|
|
|
env: E,
|
|
|
|
projection_mode: Reveal)
|
|
|
|
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
|
|
|
let (tables, fresh_tables, param_env) = env.to_parts(self);
|
2016-05-11 04:14:41 +03:00
|
|
|
InferCtxtBuilder {
|
|
|
|
global_tcx: self,
|
2016-12-23 20:48:21 -07:00
|
|
|
arena: DroplessArena::new(),
|
2017-01-06 21:54:24 +02:00
|
|
|
fresh_tables: fresh_tables.map(RefCell::new),
|
|
|
|
tables: tables,
|
2016-05-11 04:14:41 +03:00
|
|
|
param_env: param_env,
|
|
|
|
projection_mode: projection_mode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck
|
|
|
|
/// for MemCategorizationContext/ExprUseVisitor.
|
|
|
|
/// If any inference functionality is used, ICEs will occur.
|
2017-01-06 21:54:24 +02:00
|
|
|
pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId)
|
2016-05-11 04:14:41 +03:00
|
|
|
-> InferCtxt<'a, 'gcx, 'gcx> {
|
2017-01-06 21:54:24 +02:00
|
|
|
let (tables, _, param_env) = body.to_parts(self);
|
2016-05-11 04:14:41 +03:00
|
|
|
InferCtxt {
|
|
|
|
tcx: self,
|
2017-01-06 21:54:24 +02:00
|
|
|
tables: InferTables::Interned(tables.unwrap()),
|
2016-05-11 04:14:41 +03:00
|
|
|
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
|
|
|
|
int_unification_table: RefCell::new(UnificationTable::new()),
|
|
|
|
float_unification_table: RefCell::new(UnificationTable::new()),
|
|
|
|
region_vars: RegionVarBindings::new(self),
|
2017-01-06 21:54:24 +02:00
|
|
|
parameter_environment: param_env.unwrap(),
|
2016-05-11 04:14:41 +03:00
|
|
|
selection_cache: traits::SelectionCache::new(),
|
|
|
|
evaluation_cache: traits::EvaluationCache::new(),
|
2016-05-21 08:18:52 -04:00
|
|
|
projection_cache: RefCell::new(traits::ProjectionCache::new()),
|
2016-11-08 14:02:55 +11:00
|
|
|
reported_trait_errors: RefCell::new(FxHashSet()),
|
2016-06-30 21:22:47 +03:00
|
|
|
projection_mode: Reveal::NotSpecializable,
|
2016-05-11 04:14:41 +03:00
|
|
|
tainted_by_errors_flag: Cell::new(false),
|
2016-05-25 21:12:35 +03:00
|
|
|
err_count_on_creation: self.sess.err_count(),
|
|
|
|
obligations_in_snapshot: Cell::new(false),
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
|
|
|
pub fn enter<F, R>(&'tcx mut self, f: F) -> R
|
|
|
|
where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R
|
2016-03-25 05:22:44 +02:00
|
|
|
{
|
2016-05-11 04:14:41 +03:00
|
|
|
let InferCtxtBuilder {
|
|
|
|
global_tcx,
|
2016-12-23 20:48:21 -07:00
|
|
|
ref arena,
|
2017-01-06 21:54:24 +02:00
|
|
|
ref fresh_tables,
|
|
|
|
tables,
|
2016-05-11 04:14:41 +03:00
|
|
|
ref mut param_env,
|
|
|
|
projection_mode,
|
|
|
|
} = *self;
|
2017-01-06 21:54:24 +02:00
|
|
|
let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
|
|
|
|
fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
|
|
|
|
});
|
2016-05-11 04:14:41 +03:00
|
|
|
let param_env = param_env.take().unwrap_or_else(|| {
|
|
|
|
global_tcx.empty_parameter_environment()
|
|
|
|
});
|
2016-12-23 20:48:21 -07:00
|
|
|
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
|
2016-03-11 02:31:38 +02:00
|
|
|
tcx: tcx,
|
|
|
|
tables: tables,
|
2016-05-21 08:18:52 -04:00
|
|
|
projection_cache: RefCell::new(traits::ProjectionCache::new()),
|
2016-03-11 02:31:38 +02:00
|
|
|
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
|
|
|
|
int_unification_table: RefCell::new(UnificationTable::new()),
|
|
|
|
float_unification_table: RefCell::new(UnificationTable::new()),
|
|
|
|
region_vars: RegionVarBindings::new(tcx),
|
2016-05-11 04:14:41 +03:00
|
|
|
parameter_environment: param_env,
|
2016-04-29 06:00:23 +03:00
|
|
|
selection_cache: traits::SelectionCache::new(),
|
|
|
|
evaluation_cache: traits::EvaluationCache::new(),
|
2016-11-08 14:02:55 +11:00
|
|
|
reported_trait_errors: RefCell::new(FxHashSet()),
|
2016-03-11 02:31:38 +02:00
|
|
|
projection_mode: projection_mode,
|
2016-05-11 04:14:41 +03:00
|
|
|
tainted_by_errors_flag: Cell::new(false),
|
2016-05-25 21:12:35 +03:00
|
|
|
err_count_on_creation: tcx.sess.err_count(),
|
|
|
|
obligations_in_snapshot: Cell::new(false),
|
2016-05-11 04:14:41 +03:00
|
|
|
}))
|
2016-03-11 02:31:38 +02:00
|
|
|
}
|
2015-06-27 22:04:15 -07:00
|
|
|
}
|
|
|
|
|
2016-03-17 00:15:31 +02:00
|
|
|
impl<T> ExpectedFound<T> {
|
|
|
|
fn new(a_is_expected: bool, a: T, b: T) -> Self {
|
|
|
|
if a_is_expected {
|
|
|
|
ExpectedFound {expected: a, found: b}
|
|
|
|
} else {
|
|
|
|
ExpectedFound {expected: b, found: a}
|
|
|
|
}
|
2016-02-26 10:51:10 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-17 00:15:31 +02:00
|
|
|
impl<'tcx, T> InferOk<'tcx, T> {
|
2016-04-20 19:51:56 -04:00
|
|
|
pub fn unit(self) -> InferOk<'tcx, ()> {
|
2016-03-17 00:15:31 +02:00
|
|
|
InferOk { value: (), obligations: self.obligations }
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-01 10:11:59 -05:00
|
|
|
#[must_use = "once you start a snapshot, you should always consume it"]
|
2014-06-20 06:35:06 -04:00
|
|
|
pub struct CombinedSnapshot {
|
2016-05-21 08:18:52 -04:00
|
|
|
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
|
2014-07-22 07:46:36 -04:00
|
|
|
type_snapshot: type_variable::Snapshot,
|
|
|
|
int_snapshot: unify::Snapshot<ty::IntVid>,
|
|
|
|
float_snapshot: unify::Snapshot<ty::FloatVid>,
|
2014-06-20 06:35:06 -04:00
|
|
|
region_vars_snapshot: RegionSnapshot,
|
2016-05-25 21:12:35 +03:00
|
|
|
obligations_in_snapshot: bool,
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-05-11 04:14:41 +03:00
|
|
|
/// Helper trait for shortening the lifetimes inside a
|
|
|
|
/// value for post-type-checking normalization.
|
|
|
|
pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> {
|
|
|
|
fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self;
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! items { ($($item:item)+) => ($($item)+) }
|
|
|
|
macro_rules! impl_trans_normalize {
|
|
|
|
($lt_gcx:tt, $($ty:ty),+) => {
|
|
|
|
items!($(impl<$lt_gcx> TransNormalize<$lt_gcx> for $ty {
|
|
|
|
fn trans_normalize<'a, 'tcx>(&self,
|
|
|
|
infcx: &InferCtxt<'a, $lt_gcx, 'tcx>)
|
|
|
|
-> Self {
|
|
|
|
infcx.normalize_projections_in(self)
|
|
|
|
}
|
|
|
|
})+);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl_trans_normalize!('gcx,
|
|
|
|
Ty<'gcx>,
|
|
|
|
&'gcx Substs<'gcx>,
|
|
|
|
ty::FnSig<'gcx>,
|
|
|
|
&'gcx ty::BareFnTy<'gcx>,
|
|
|
|
ty::ClosureSubsts<'gcx>,
|
2016-10-13 00:08:11 +03:00
|
|
|
ty::PolyTraitRef<'gcx>,
|
|
|
|
ty::ExistentialTraitRef<'gcx>
|
2016-05-11 04:14:41 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> {
|
|
|
|
fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self {
|
|
|
|
match *self {
|
|
|
|
LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx) },
|
|
|
|
LvalueTy::Downcast { adt_def, substs, variant_index } => {
|
|
|
|
LvalueTy::Downcast {
|
|
|
|
adt_def: adt_def,
|
|
|
|
substs: substs.trans_normalize(infcx),
|
|
|
|
variant_index: variant_index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-23 12:47:09 -08:00
|
|
|
// NOTE: Callable from trans only!
|
2016-05-03 05:23:22 +03:00
|
|
|
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
2016-10-13 00:08:11 +03:00
|
|
|
/// Currently, higher-ranked type bounds inhibit normalization. Therefore,
|
|
|
|
/// each time we erase them in translation, we need to normalize
|
|
|
|
/// the contents.
|
|
|
|
pub fn erase_late_bound_regions_and_normalize<T>(self, value: &ty::Binder<T>)
|
|
|
|
-> T
|
|
|
|
where T: TransNormalize<'tcx>
|
|
|
|
{
|
|
|
|
assert!(!value.needs_subst());
|
|
|
|
let value = self.erase_late_bound_regions(value);
|
|
|
|
self.normalize_associated_type(&value)
|
|
|
|
}
|
|
|
|
|
2016-05-03 04:56:42 +03:00
|
|
|
pub fn normalize_associated_type<T>(self, value: &T) -> T
|
2016-05-11 04:14:41 +03:00
|
|
|
where T: TransNormalize<'tcx>
|
2016-03-11 02:33:20 +02:00
|
|
|
{
|
|
|
|
debug!("normalize_associated_type(t={:?})", value);
|
2015-06-27 22:04:15 -07:00
|
|
|
|
2016-03-11 02:33:20 +02:00
|
|
|
let value = self.erase_regions(value);
|
2015-06-27 22:04:15 -07:00
|
|
|
|
2016-03-11 02:33:20 +02:00
|
|
|
if !value.has_projection_types() {
|
|
|
|
return value;
|
|
|
|
}
|
2015-06-27 22:04:15 -07:00
|
|
|
|
2017-01-06 21:54:24 +02:00
|
|
|
self.infer_ctxt((), Reveal::All).enter(|infcx| {
|
2016-05-11 04:14:41 +03:00
|
|
|
value.trans_normalize(&infcx)
|
2016-04-29 06:00:23 +03:00
|
|
|
})
|
|
|
|
}
|
2016-05-17 02:26:18 +03:00
|
|
|
|
|
|
|
pub fn normalize_associated_type_in_env<T>(
|
|
|
|
self, value: &T, env: &'a ty::ParameterEnvironment<'tcx>
|
|
|
|
) -> T
|
|
|
|
where T: TransNormalize<'tcx>
|
|
|
|
{
|
|
|
|
debug!("normalize_associated_type_in_env(t={:?})", value);
|
|
|
|
|
|
|
|
let value = self.erase_regions(value);
|
|
|
|
|
|
|
|
if !value.has_projection_types() {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2017-01-06 21:54:24 +02:00
|
|
|
self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| {
|
2016-05-17 02:26:18 +03:00
|
|
|
value.trans_normalize(&infcx)
|
|
|
|
})
|
|
|
|
}
|
2016-04-29 06:00:23 +03:00
|
|
|
}
|
2015-06-27 22:04:15 -07:00
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
2016-05-11 04:14:41 +03:00
|
|
|
fn normalize_projections_in<T>(&self, value: &T) -> T::Lifted
|
|
|
|
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
|
2016-04-29 06:00:23 +03:00
|
|
|
{
|
|
|
|
let mut selcx = traits::SelectionContext::new(self);
|
|
|
|
let cause = traits::ObligationCause::dummy();
|
|
|
|
let traits::Normalized { value: result, obligations } =
|
|
|
|
traits::normalize(&mut selcx, cause, value);
|
2015-06-27 22:04:15 -07:00
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
debug!("normalize_projections_in: result={:?} obligations={:?}",
|
|
|
|
result, obligations);
|
2015-06-27 22:04:15 -07:00
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
let mut fulfill_cx = traits::FulfillmentContext::new();
|
2015-06-27 22:04:15 -07:00
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
for obligation in obligations {
|
|
|
|
fulfill_cx.register_predicate_obligation(self, obligation);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
|
2016-03-11 02:33:20 +02:00
|
|
|
}
|
2015-06-27 22:04:15 -07:00
|
|
|
|
2016-08-08 09:40:12 -04:00
|
|
|
/// Finishes processes any obligations that remain in the
|
|
|
|
/// fulfillment context, and then returns the result with all type
|
|
|
|
/// variables removed and regions erased. Because this is intended
|
|
|
|
/// for use after type-check has completed, if any errors occur,
|
|
|
|
/// it will panic. It is used during normalization and other cases
|
|
|
|
/// where processing the obligations in `fulfill_cx` may cause
|
|
|
|
/// type inference variables that appear in `result` to be
|
|
|
|
/// unified, and hence we need to process those obligations to get
|
|
|
|
/// the complete picture of the type.
|
2016-05-11 08:48:12 +03:00
|
|
|
pub fn drain_fulfillment_cx_or_panic<T>(&self,
|
|
|
|
span: Span,
|
|
|
|
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
|
|
|
|
result: &T)
|
|
|
|
-> T::Lifted
|
|
|
|
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
|
|
|
|
{
|
2016-05-21 05:41:40 -04:00
|
|
|
debug!("drain_fulfillment_cx_or_panic()");
|
|
|
|
|
2016-08-08 09:40:12 -04:00
|
|
|
// In principle, we only need to do this so long as `result`
|
|
|
|
// contains unbound type parameters. It could be a slight
|
|
|
|
// optimization to stop iterating early.
|
|
|
|
match fulfill_cx.select_all_or_error(self) {
|
|
|
|
Ok(()) => { }
|
2016-05-11 08:48:12 +03:00
|
|
|
Err(errors) => {
|
2016-08-08 09:40:12 -04:00
|
|
|
span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
|
|
|
|
errors);
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2016-08-08 09:40:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
let result = self.resolve_type_vars_if_possible(result);
|
|
|
|
let result = self.tcx.erase_regions(&result);
|
2016-05-11 04:14:41 +03:00
|
|
|
|
2016-08-08 09:40:12 -04:00
|
|
|
match self.tcx.lift_to_global(&result) {
|
|
|
|
Some(result) => result,
|
2016-05-11 08:48:12 +03:00
|
|
|
None => {
|
2016-08-08 09:40:12 -04:00
|
|
|
span_bug!(span, "Uninferred types/regions in `{:?}`", result);
|
2016-05-11 08:48:12 +03:00
|
|
|
}
|
2015-06-27 22:04:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-30 21:22:47 +03:00
|
|
|
pub fn projection_mode(&self) -> Reveal {
|
2016-02-23 12:47:09 -08:00
|
|
|
self.projection_mode
|
|
|
|
}
|
|
|
|
|
2014-12-12 06:13:42 -05:00
|
|
|
pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
|
|
|
|
t.fold_with(&mut self.freshener())
|
2014-10-09 17:19:50 -04:00
|
|
|
}
|
|
|
|
|
2014-09-13 21:09:25 +03:00
|
|
|
pub fn type_var_diverges(&'a self, ty: Ty) -> bool {
|
2014-10-31 10:51:16 +02:00
|
|
|
match ty.sty {
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
|
2014-10-24 21:14:37 +02:00
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'gcx, 'tcx> {
|
2014-12-12 06:13:42 -05:00
|
|
|
freshen::TypeFreshener::new(self)
|
2014-09-18 11:08:04 -04:00
|
|
|
}
|
|
|
|
|
2014-12-15 09:45:28 -05:00
|
|
|
pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
|
2016-03-22 17:30:57 +02:00
|
|
|
use ty::error::UnconstrainedNumeric::Neither;
|
|
|
|
use ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
|
2014-12-15 09:45:28 -05:00
|
|
|
match ty.sty {
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyInfer(ty::IntVar(vid)) => {
|
2015-02-16 05:07:22 -05:00
|
|
|
if self.int_unification_table.borrow_mut().has_value(vid) {
|
|
|
|
Neither
|
|
|
|
} else {
|
|
|
|
UnconstrainedInt
|
2014-12-15 09:45:28 -05:00
|
|
|
}
|
|
|
|
},
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyInfer(ty::FloatVar(vid)) => {
|
2015-02-16 05:07:22 -05:00
|
|
|
if self.float_unification_table.borrow_mut().has_value(vid) {
|
|
|
|
Neither
|
|
|
|
} else {
|
|
|
|
UnconstrainedFloat
|
2014-12-15 09:45:28 -05:00
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => Neither,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-09 12:15:48 -07:00
|
|
|
/// Returns a type variable's default fallback if any exists. A default
|
|
|
|
/// must be attached to the variable when created, if it is created
|
|
|
|
/// without a default, this will return None.
|
|
|
|
///
|
2015-07-16 11:26:02 -07:00
|
|
|
/// This code does not apply to integral or floating point variables,
|
|
|
|
/// only to use declared defaults.
|
|
|
|
///
|
2015-07-09 12:15:48 -07:00
|
|
|
/// See `new_ty_var_with_default` to create a type variable with a default.
|
|
|
|
/// See `type_variable::Default` for details about what a default entails.
|
|
|
|
pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> {
|
|
|
|
match ty.sty {
|
|
|
|
ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid),
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-07 15:50:02 -07:00
|
|
|
pub fn unsolved_variables(&self) -> Vec<ty::Ty<'tcx>> {
|
|
|
|
let mut variables = Vec::new();
|
|
|
|
|
|
|
|
let unbound_ty_vars = self.type_variables
|
2016-03-03 10:43:52 +01:00
|
|
|
.borrow_mut()
|
2015-07-07 15:50:02 -07:00
|
|
|
.unsolved_variables()
|
2015-07-09 12:15:48 -07:00
|
|
|
.into_iter()
|
|
|
|
.map(|t| self.tcx.mk_var(t));
|
2015-07-07 15:50:02 -07:00
|
|
|
|
|
|
|
let unbound_int_vars = self.int_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.unsolved_variables()
|
2015-07-09 12:15:48 -07:00
|
|
|
.into_iter()
|
|
|
|
.map(|v| self.tcx.mk_int_var(v));
|
2015-07-07 15:50:02 -07:00
|
|
|
|
|
|
|
let unbound_float_vars = self.float_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.unsolved_variables()
|
2015-07-09 12:15:48 -07:00
|
|
|
.into_iter()
|
|
|
|
.map(|v| self.tcx.mk_float_var(v));
|
2015-07-07 15:50:02 -07:00
|
|
|
|
|
|
|
variables.extend(unbound_ty_vars);
|
|
|
|
variables.extend(unbound_int_vars);
|
|
|
|
variables.extend(unbound_float_vars);
|
2015-07-12 20:33:17 -07:00
|
|
|
|
2015-07-07 15:50:02 -07:00
|
|
|
return variables;
|
|
|
|
}
|
|
|
|
|
2016-07-25 15:07:57 -07:00
|
|
|
fn combine_fields(&'a self, trace: TypeTrace<'tcx>)
|
2016-04-29 06:00:23 +03:00
|
|
|
-> CombineFields<'a, 'gcx, 'tcx> {
|
2016-03-29 20:06:42 -07:00
|
|
|
CombineFields {
|
|
|
|
infcx: self,
|
|
|
|
trace: trace,
|
|
|
|
cause: None,
|
|
|
|
obligations: PredicateObligations::new(),
|
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-03-28 21:56:19 -07:00
|
|
|
pub fn equate<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, T>
|
2016-04-29 06:00:23 +03:00
|
|
|
where T: Relate<'tcx>
|
2015-03-22 15:11:56 -04:00
|
|
|
{
|
2016-07-25 16:37:30 -07:00
|
|
|
let mut fields = self.combine_fields(trace);
|
|
|
|
let result = fields.equate(a_is_expected).relate(a, b);
|
|
|
|
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
2014-07-22 07:46:36 -04:00
|
|
|
}
|
|
|
|
|
2016-03-28 21:56:19 -07:00
|
|
|
pub fn sub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, T>
|
2016-04-29 06:00:23 +03:00
|
|
|
where T: Relate<'tcx>
|
2015-03-22 15:11:56 -04:00
|
|
|
{
|
2016-07-25 16:37:30 -07:00
|
|
|
let mut fields = self.combine_fields(trace);
|
|
|
|
let result = fields.sub(a_is_expected).relate(a, b);
|
|
|
|
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-03-28 21:56:19 -07:00
|
|
|
pub fn lub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, T>
|
2016-04-29 06:00:23 +03:00
|
|
|
where T: Relate<'tcx>
|
2015-03-22 15:11:56 -04:00
|
|
|
{
|
2016-07-25 16:37:30 -07:00
|
|
|
let mut fields = self.combine_fields(trace);
|
|
|
|
let result = fields.lub(a_is_expected).relate(a, b);
|
|
|
|
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
2015-03-22 15:11:56 -04:00
|
|
|
}
|
|
|
|
|
2016-03-28 21:56:19 -07:00
|
|
|
pub fn glb<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, T>
|
2016-04-29 06:00:23 +03:00
|
|
|
where T: Relate<'tcx>
|
2015-03-22 15:11:56 -04:00
|
|
|
{
|
2016-07-25 16:37:30 -07:00
|
|
|
let mut fields = self.combine_fields(trace);
|
|
|
|
let result = fields.glb(a_is_expected).relate(a, b);
|
|
|
|
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
2013-06-05 21:04:07 -04:00
|
|
|
}
|
|
|
|
|
2016-09-13 18:31:26 -04:00
|
|
|
// Clear the "obligations in snapshot" flag, invoke the closure,
|
|
|
|
// then restore the flag to its original value. This flag is a
|
|
|
|
// debugging measure designed to detect cases where we start a
|
|
|
|
// snapshot, create type variables, register obligations involving
|
|
|
|
// those type variables in the fulfillment cx, and then have to
|
|
|
|
// unroll the snapshot, leaving "dangling type variables" behind.
|
|
|
|
// In such cases, the flag will be set by the fulfillment cx, and
|
|
|
|
// an assertion will fail when rolling the snapshot back. Very
|
|
|
|
// useful, much better than grovelling through megabytes of
|
|
|
|
// RUST_LOG output.
|
|
|
|
//
|
|
|
|
// HOWEVER, in some cases the flag is wrong. In particular, we
|
|
|
|
// sometimes create a "mini-fulfilment-cx" in which we enroll
|
|
|
|
// obligations. As long as this fulfillment cx is fully drained
|
|
|
|
// before we return, this is not a problem, as there won't be any
|
|
|
|
// escaping obligations in the main cx. In those cases, you can
|
|
|
|
// use this function.
|
|
|
|
pub fn save_and_restore_obligations_in_snapshot_flag<F, R>(&self, func: F) -> R
|
|
|
|
where F: FnOnce(&Self) -> R
|
|
|
|
{
|
|
|
|
let flag = self.obligations_in_snapshot.get();
|
|
|
|
self.obligations_in_snapshot.set(false);
|
|
|
|
let result = func(self);
|
|
|
|
self.obligations_in_snapshot.set(flag);
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2014-06-20 06:35:06 -04:00
|
|
|
fn start_snapshot(&self) -> CombinedSnapshot {
|
2016-05-21 05:41:40 -04:00
|
|
|
debug!("start_snapshot()");
|
|
|
|
|
2016-05-25 21:12:35 +03:00
|
|
|
let obligations_in_snapshot = self.obligations_in_snapshot.get();
|
|
|
|
self.obligations_in_snapshot.set(false);
|
|
|
|
|
2014-06-20 06:35:06 -04:00
|
|
|
CombinedSnapshot {
|
2016-05-21 08:18:52 -04:00
|
|
|
projection_cache_snapshot: self.projection_cache.borrow_mut().snapshot(),
|
2014-07-22 07:46:36 -04:00
|
|
|
type_snapshot: self.type_variables.borrow_mut().snapshot(),
|
2014-06-20 06:35:06 -04:00
|
|
|
int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
|
|
|
|
float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
|
2013-12-19 20:35:14 -08:00
|
|
|
region_vars_snapshot: self.region_vars.start_snapshot(),
|
2016-05-25 21:12:35 +03:00
|
|
|
obligations_in_snapshot: obligations_in_snapshot,
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-24 10:23:35 -04:00
|
|
|
fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot) {
|
|
|
|
debug!("rollback_to(cause={})", cause);
|
2016-05-21 08:18:52 -04:00
|
|
|
let CombinedSnapshot { projection_cache_snapshot,
|
|
|
|
type_snapshot,
|
2014-06-20 06:35:06 -04:00
|
|
|
int_snapshot,
|
|
|
|
float_snapshot,
|
2016-05-25 21:12:35 +03:00
|
|
|
region_vars_snapshot,
|
|
|
|
obligations_in_snapshot } = snapshot;
|
|
|
|
|
|
|
|
assert!(!self.obligations_in_snapshot.get());
|
|
|
|
self.obligations_in_snapshot.set(obligations_in_snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
|
2016-05-21 08:18:52 -04:00
|
|
|
self.projection_cache
|
|
|
|
.borrow_mut()
|
|
|
|
.rollback_to(projection_cache_snapshot);
|
2014-07-22 07:46:36 -04:00
|
|
|
self.type_variables
|
2014-06-20 06:35:06 -04:00
|
|
|
.borrow_mut()
|
2014-07-22 07:40:51 -04:00
|
|
|
.rollback_to(type_snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
self.int_unification_table
|
|
|
|
.borrow_mut()
|
2014-07-22 07:40:51 -04:00
|
|
|
.rollback_to(int_snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
self.float_unification_table
|
|
|
|
.borrow_mut()
|
2014-07-22 07:40:51 -04:00
|
|
|
.rollback_to(float_snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
self.region_vars
|
|
|
|
.rollback_to(region_vars_snapshot);
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2014-06-20 06:35:06 -04:00
|
|
|
fn commit_from(&self, snapshot: CombinedSnapshot) {
|
2016-05-21 05:41:40 -04:00
|
|
|
debug!("commit_from()");
|
2016-05-21 08:18:52 -04:00
|
|
|
let CombinedSnapshot { projection_cache_snapshot,
|
|
|
|
type_snapshot,
|
2014-06-20 06:35:06 -04:00
|
|
|
int_snapshot,
|
|
|
|
float_snapshot,
|
2016-05-25 21:12:35 +03:00
|
|
|
region_vars_snapshot,
|
|
|
|
obligations_in_snapshot } = snapshot;
|
|
|
|
|
|
|
|
self.obligations_in_snapshot.set(obligations_in_snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
|
2016-05-21 08:18:52 -04:00
|
|
|
self.projection_cache
|
|
|
|
.borrow_mut()
|
|
|
|
.commit(projection_cache_snapshot);
|
2014-07-22 07:46:36 -04:00
|
|
|
self.type_variables
|
2014-06-20 06:35:06 -04:00
|
|
|
.borrow_mut()
|
|
|
|
.commit(type_snapshot);
|
|
|
|
self.int_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.commit(int_snapshot);
|
|
|
|
self.float_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.commit(float_snapshot);
|
|
|
|
self.region_vars
|
|
|
|
.commit(region_vars_snapshot);
|
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2014-06-20 06:35:06 -04:00
|
|
|
/// Execute `f` and commit the bindings
|
2014-12-08 20:26:43 -05:00
|
|
|
pub fn commit_unconditionally<R, F>(&self, f: F) -> R where
|
|
|
|
F: FnOnce() -> R,
|
|
|
|
{
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("commit()");
|
2014-06-20 06:35:06 -04:00
|
|
|
let snapshot = self.start_snapshot();
|
|
|
|
let r = f();
|
|
|
|
self.commit_from(snapshot);
|
|
|
|
r
|
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2015-03-10 07:02:27 -04:00
|
|
|
/// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`
|
2014-12-08 20:26:43 -05:00
|
|
|
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
|
2015-03-10 07:02:27 -04:00
|
|
|
F: FnOnce(&CombinedSnapshot) -> Result<T, E>
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
2015-03-10 07:02:27 -04:00
|
|
|
debug!("commit_if_ok()");
|
|
|
|
let snapshot = self.start_snapshot();
|
|
|
|
let r = f(&snapshot);
|
|
|
|
debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok());
|
|
|
|
match r {
|
|
|
|
Ok(_) => { self.commit_from(snapshot); }
|
2015-07-24 10:23:35 -04:00
|
|
|
Err(_) => { self.rollback_to("commit_if_ok -- error", snapshot); }
|
2015-03-10 07:02:27 -04:00
|
|
|
}
|
|
|
|
r
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-05-01 17:19:11 +03:00
|
|
|
// Execute `f` in a snapshot, and commit the bindings it creates
|
|
|
|
pub fn in_snapshot<T, F>(&self, f: F) -> T where
|
|
|
|
F: FnOnce(&CombinedSnapshot) -> T
|
|
|
|
{
|
|
|
|
debug!("in_snapshot()");
|
|
|
|
let snapshot = self.start_snapshot();
|
|
|
|
let r = f(&snapshot);
|
|
|
|
self.commit_from(snapshot);
|
|
|
|
r
|
|
|
|
}
|
|
|
|
|
2012-11-29 16:41:39 -08:00
|
|
|
/// Execute `f` then unroll any bindings it creates
|
2014-12-08 20:26:43 -05:00
|
|
|
pub fn probe<R, F>(&self, f: F) -> R where
|
2014-12-14 07:17:23 -05:00
|
|
|
F: FnOnce(&CombinedSnapshot) -> R,
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("probe()");
|
2014-06-20 06:35:06 -04:00
|
|
|
let snapshot = self.start_snapshot();
|
2014-12-14 07:17:23 -05:00
|
|
|
let r = f(&snapshot);
|
2015-07-24 10:23:35 -04:00
|
|
|
self.rollback_to("probe", snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
r
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
2014-08-27 21:46:52 -04:00
|
|
|
|
|
|
|
pub fn add_given(&self,
|
|
|
|
sub: ty::FreeRegion,
|
|
|
|
sup: ty::RegionVid)
|
|
|
|
{
|
|
|
|
self.region_vars.add_given(sub, sup);
|
|
|
|
}
|
2014-09-12 10:53:35 -04:00
|
|
|
|
|
|
|
pub fn sub_types(&self,
|
|
|
|
a_is_expected: bool,
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: &ObligationCause<'tcx>,
|
2014-09-29 22:11:30 +03:00
|
|
|
a: Ty<'tcx>,
|
|
|
|
b: Ty<'tcx>)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, ()>
|
2014-09-12 10:53:35 -04:00
|
|
|
{
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("sub_types({:?} <: {:?})", a, b);
|
2015-03-10 07:02:27 -04:00
|
|
|
self.commit_if_ok(|_| {
|
2016-11-07 13:25:06 -05:00
|
|
|
let trace = TypeTrace::types(cause, a_is_expected, a, b);
|
2016-04-04 12:41:05 -07:00
|
|
|
self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
|
2014-10-09 17:19:50 -04:00
|
|
|
})
|
2014-09-12 10:53:35 -04:00
|
|
|
}
|
|
|
|
|
2016-03-17 00:15:31 +02:00
|
|
|
pub fn can_sub_types(&self,
|
|
|
|
a: Ty<'tcx>,
|
|
|
|
b: Ty<'tcx>)
|
|
|
|
-> UnitResult<'tcx>
|
|
|
|
{
|
|
|
|
self.probe(|_| {
|
2016-11-07 13:25:06 -05:00
|
|
|
let origin = &ObligationCause::dummy();
|
2016-03-17 00:15:31 +02:00
|
|
|
let trace = TypeTrace::types(origin, true, a, b);
|
2016-10-04 02:19:40 +03:00
|
|
|
self.sub(true, trace, &a, &b).map(|InferOk { obligations, .. }| {
|
|
|
|
// FIXME(#32730) propagate obligations
|
|
|
|
assert!(obligations.is_empty());
|
|
|
|
})
|
2016-03-17 00:15:31 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-09-12 10:53:35 -04:00
|
|
|
pub fn eq_types(&self,
|
|
|
|
a_is_expected: bool,
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: &ObligationCause<'tcx>,
|
2014-09-29 22:11:30 +03:00
|
|
|
a: Ty<'tcx>,
|
|
|
|
b: Ty<'tcx>)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, ()>
|
2014-09-12 10:53:35 -04:00
|
|
|
{
|
2015-03-10 07:02:27 -04:00
|
|
|
self.commit_if_ok(|_| {
|
2016-11-07 13:25:06 -05:00
|
|
|
let trace = TypeTrace::types(cause, a_is_expected, a, b);
|
2016-04-04 12:41:05 -07:00
|
|
|
self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
|
2014-10-09 17:19:50 -04:00
|
|
|
})
|
2014-09-12 10:53:35 -04:00
|
|
|
}
|
|
|
|
|
2015-11-20 09:34:33 -08:00
|
|
|
pub fn eq_trait_refs(&self,
|
2014-12-14 07:17:23 -05:00
|
|
|
a_is_expected: bool,
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: &ObligationCause<'tcx>,
|
2015-04-21 18:59:58 +03:00
|
|
|
a: ty::TraitRef<'tcx>,
|
|
|
|
b: ty::TraitRef<'tcx>)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, ()>
|
2014-12-14 07:17:23 -05:00
|
|
|
{
|
2016-03-17 00:15:31 +02:00
|
|
|
debug!("eq_trait_refs({:?} = {:?})", a, b);
|
2015-03-10 07:02:27 -04:00
|
|
|
self.commit_if_ok(|_| {
|
2014-12-14 07:17:23 -05:00
|
|
|
let trace = TypeTrace {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: cause.clone(),
|
2016-03-17 00:15:31 +02:00
|
|
|
values: TraitRefs(ExpectedFound::new(a_is_expected, a, b))
|
2014-12-14 07:17:23 -05:00
|
|
|
};
|
2016-04-04 12:41:05 -07:00
|
|
|
self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
|
2014-12-14 07:17:23 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-03-17 00:15:31 +02:00
|
|
|
pub fn eq_impl_headers(&self,
|
|
|
|
a_is_expected: bool,
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: &ObligationCause<'tcx>,
|
2016-03-17 00:15:31 +02:00
|
|
|
a: &ty::ImplHeader<'tcx>,
|
|
|
|
b: &ty::ImplHeader<'tcx>)
|
|
|
|
-> InferResult<'tcx, ()>
|
|
|
|
{
|
|
|
|
debug!("eq_impl_header({:?} = {:?})", a, b);
|
|
|
|
match (a.trait_ref, b.trait_ref) {
|
2016-11-07 13:25:06 -05:00
|
|
|
(Some(a_ref), Some(b_ref)) => self.eq_trait_refs(a_is_expected, cause, a_ref, b_ref),
|
|
|
|
(None, None) => self.eq_types(a_is_expected, cause, a.self_ty, b.self_ty),
|
2016-03-17 00:15:31 +02:00
|
|
|
_ => bug!("mk_eq_impl_headers given mismatched impl kinds"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-11 13:37:37 -05:00
|
|
|
pub fn sub_poly_trait_refs(&self,
|
|
|
|
a_is_expected: bool,
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: ObligationCause<'tcx>,
|
2014-12-17 14:16:28 -05:00
|
|
|
a: ty::PolyTraitRef<'tcx>,
|
|
|
|
b: ty::PolyTraitRef<'tcx>)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, ()>
|
2014-09-12 10:53:35 -04:00
|
|
|
{
|
2016-03-17 00:15:31 +02:00
|
|
|
debug!("sub_poly_trait_refs({:?} <: {:?})", a, b);
|
2015-03-10 07:02:27 -04:00
|
|
|
self.commit_if_ok(|_| {
|
2014-10-09 17:19:50 -04:00
|
|
|
let trace = TypeTrace {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: cause,
|
2016-03-17 00:15:31 +02:00
|
|
|
values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b))
|
2014-10-09 17:19:50 -04:00
|
|
|
};
|
2016-04-04 12:41:05 -07:00
|
|
|
self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
|
2014-10-09 17:19:50 -04:00
|
|
|
})
|
2014-09-12 10:53:35 -04:00
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2016-03-17 00:15:31 +02:00
|
|
|
pub fn sub_regions(&self,
|
|
|
|
origin: SubregionOrigin<'tcx>,
|
2016-08-25 23:58:52 +03:00
|
|
|
a: &'tcx ty::Region,
|
|
|
|
b: &'tcx ty::Region) {
|
2016-03-17 00:15:31 +02:00
|
|
|
debug!("sub_regions({:?} <: {:?})", a, b);
|
|
|
|
self.region_vars.make_subregion(origin, a, b);
|
2014-12-14 07:17:23 -05:00
|
|
|
}
|
|
|
|
|
2014-12-13 05:34:34 -05:00
|
|
|
pub fn equality_predicate(&self,
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: &ObligationCause<'tcx>,
|
2014-12-13 05:34:34 -05:00
|
|
|
predicate: &ty::PolyEquatePredicate<'tcx>)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> InferResult<'tcx, ()>
|
|
|
|
{
|
2015-03-10 07:02:27 -04:00
|
|
|
self.commit_if_ok(|snapshot| {
|
2014-12-13 05:34:34 -05:00
|
|
|
let (ty::EquatePredicate(a, b), skol_map) =
|
|
|
|
self.skolemize_late_bound_regions(predicate, snapshot);
|
2016-11-07 13:25:06 -05:00
|
|
|
let cause_span = cause.span;
|
|
|
|
let eqty_ok = self.eq_types(false, cause, a, b)?;
|
|
|
|
self.leak_check(false, cause_span, &skol_map, snapshot)?;
|
2016-04-20 19:51:56 -04:00
|
|
|
self.pop_skolemized(skol_map, snapshot);
|
|
|
|
Ok(eqty_ok.unit())
|
2014-12-13 05:34:34 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn region_outlives_predicate(&self,
|
2016-10-05 10:17:14 -04:00
|
|
|
cause: &traits::ObligationCause<'tcx>,
|
2016-08-25 23:58:52 +03:00
|
|
|
predicate: &ty::PolyRegionOutlivesPredicate<'tcx>)
|
2016-03-29 20:06:42 -07:00
|
|
|
-> UnitResult<'tcx>
|
|
|
|
{
|
2015-03-10 07:02:27 -04:00
|
|
|
self.commit_if_ok(|snapshot| {
|
2014-12-13 05:34:34 -05:00
|
|
|
let (ty::OutlivesPredicate(r_a, r_b), skol_map) =
|
|
|
|
self.skolemize_late_bound_regions(predicate, snapshot);
|
2016-10-19 10:45:49 -04:00
|
|
|
let origin =
|
|
|
|
SubregionOrigin::from_obligation_cause(cause,
|
|
|
|
|| RelateRegionParamBound(cause.span));
|
2016-03-17 00:15:31 +02:00
|
|
|
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
|
2016-10-05 10:17:14 -04:00
|
|
|
self.leak_check(false, cause.span, &skol_map, snapshot)?;
|
2016-04-20 19:51:56 -04:00
|
|
|
Ok(self.pop_skolemized(skol_map, snapshot))
|
2014-12-13 05:34:34 -05:00
|
|
|
})
|
2014-12-12 06:37:42 -05:00
|
|
|
}
|
|
|
|
|
2016-11-28 10:08:08 -08:00
|
|
|
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
|
2014-07-22 07:46:36 -04:00
|
|
|
self.type_variables
|
2014-06-20 06:35:06 -04:00
|
|
|
.borrow_mut()
|
2016-11-28 10:08:08 -08:00
|
|
|
.new_var(diverging, origin, None)
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-11-28 10:08:08 -08:00
|
|
|
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
|
|
|
self.tcx.mk_var(self.next_ty_var_id(false, origin))
|
2014-10-24 21:14:37 +02:00
|
|
|
}
|
|
|
|
|
2016-11-28 10:08:08 -08:00
|
|
|
pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
|
|
|
self.tcx.mk_var(self.next_ty_var_id(true, origin))
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2013-12-20 16:29:57 -08:00
|
|
|
pub fn next_int_var_id(&self) -> IntVid {
|
2014-06-20 06:35:06 -04:00
|
|
|
self.int_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.new_key(None)
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2013-12-20 16:29:57 -08:00
|
|
|
pub fn next_float_var_id(&self) -> FloatVid {
|
2014-06-20 06:35:06 -04:00
|
|
|
self.float_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.new_key(None)
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-08-25 23:58:52 +03:00
|
|
|
pub fn next_region_var(&self, origin: RegionVariableOrigin)
|
|
|
|
-> &'tcx ty::Region {
|
|
|
|
self.tcx.mk_region(ty::ReVar(self.region_vars.new_region_var(origin)))
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-08-17 03:56:18 +03:00
|
|
|
/// Create a region inference variable for the given
|
|
|
|
/// region parameter definition.
|
|
|
|
pub fn region_var_for_def(&self,
|
|
|
|
span: Span,
|
|
|
|
def: &ty::RegionParameterDef)
|
2016-08-25 23:58:52 +03:00
|
|
|
-> &'tcx ty::Region {
|
2017-01-06 14:35:23 -05:00
|
|
|
self.next_region_var(EarlyBoundRegion(span, def.name, def.issue_32330))
|
2016-08-17 03:56:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a type inference variable for the given
|
|
|
|
/// type parameter definition. The substitutions are
|
|
|
|
/// for actual parameters that may be referred to by
|
|
|
|
/// the default of this type parameter, if it exists.
|
|
|
|
/// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
|
|
|
|
/// used in a path such as `Foo::<T, U>::new()` will
|
|
|
|
/// use an inference variable for `C` with `[T, U]`
|
|
|
|
/// as the substitutions for the default, `(T, U)`.
|
|
|
|
pub fn type_var_for_def(&self,
|
|
|
|
span: Span,
|
|
|
|
def: &ty::TypeParameterDef<'tcx>,
|
2016-10-09 11:36:12 -07:00
|
|
|
substs: &[Kind<'tcx>])
|
2016-08-17 03:56:18 +03:00
|
|
|
-> Ty<'tcx> {
|
|
|
|
let default = def.default.map(|default| {
|
|
|
|
type_variable::Default {
|
|
|
|
ty: default.subst_spanned(self.tcx, substs, Some(span)),
|
|
|
|
origin_span: span,
|
|
|
|
def_id: def.default_def_id
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let ty_var_id = self.type_variables
|
|
|
|
.borrow_mut()
|
2016-11-28 10:08:08 -08:00
|
|
|
.new_var(false,
|
|
|
|
TypeVariableOrigin::TypeParameterDefinition(span, def.name),
|
|
|
|
default);
|
2016-08-17 03:56:18 +03:00
|
|
|
|
|
|
|
self.tcx.mk_var(ty_var_id)
|
|
|
|
}
|
|
|
|
|
2014-11-25 21:17:11 -05:00
|
|
|
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
|
|
|
|
/// type/region parameter to a fresh inference variable.
|
2016-08-08 23:39:49 +03:00
|
|
|
pub fn fresh_substs_for_item(&self,
|
|
|
|
span: Span,
|
|
|
|
def_id: DefId)
|
|
|
|
-> &'tcx Substs<'tcx> {
|
|
|
|
Substs::for_item(self.tcx, def_id, |def, _| {
|
2016-08-17 03:56:18 +03:00
|
|
|
self.region_var_for_def(span, def)
|
|
|
|
}, |def, substs| {
|
|
|
|
self.type_var_for_def(span, def, substs)
|
2016-08-08 23:39:49 +03:00
|
|
|
})
|
2014-05-31 18:53:13 -04:00
|
|
|
}
|
|
|
|
|
2016-08-25 23:58:52 +03:00
|
|
|
pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> &'tcx ty::Region {
|
2014-11-15 16:47:59 -05:00
|
|
|
self.region_vars.new_bound(debruijn)
|
2013-10-29 06:03:32 -04:00
|
|
|
}
|
|
|
|
|
2016-03-15 04:49:10 -04:00
|
|
|
/// True if errors have been reported since this infcx was
|
|
|
|
/// created. This is sometimes used as a heuristic to skip
|
|
|
|
/// reporting errors that often occur as a result of earlier
|
|
|
|
/// errors, but where it's hard to be 100% sure (e.g., unresolved
|
|
|
|
/// inference variables, regionck errors).
|
|
|
|
pub fn is_tainted_by_errors(&self) -> bool {
|
|
|
|
debug!("is_tainted_by_errors(err_count={}, err_count_on_creation={}, \
|
|
|
|
tainted_by_errors_flag={})",
|
|
|
|
self.tcx.sess.err_count(),
|
|
|
|
self.err_count_on_creation,
|
|
|
|
self.tainted_by_errors_flag.get());
|
|
|
|
|
|
|
|
if self.tcx.sess.err_count() > self.err_count_on_creation {
|
|
|
|
return true; // errors reported since this infcx was made
|
|
|
|
}
|
|
|
|
self.tainted_by_errors_flag.get()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the "tainted by errors" flag to true. We call this when we
|
|
|
|
/// observe an error from a prior pass.
|
|
|
|
pub fn set_tainted_by_errors(&self) {
|
|
|
|
debug!("set_tainted_by_errors()");
|
|
|
|
self.tainted_by_errors_flag.set(true)
|
2016-03-09 16:53:19 -05:00
|
|
|
}
|
|
|
|
|
2015-06-29 17:46:24 -07:00
|
|
|
pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
|
2015-06-25 13:08:10 -07:00
|
|
|
match self.tables.borrow().node_types.get(&id) {
|
|
|
|
Some(&t) => t,
|
|
|
|
// FIXME
|
2016-03-15 04:49:10 -04:00
|
|
|
None if self.is_tainted_by_errors() =>
|
2015-06-26 12:23:41 -07:00
|
|
|
self.tcx.types.err,
|
2015-06-25 13:08:10 -07:00
|
|
|
None => {
|
2016-03-25 01:14:29 +01:00
|
|
|
bug!("no type for node {}: {} in fcx",
|
2017-01-26 02:41:06 +02:00
|
|
|
id, self.tcx.hir.node_to_string(id));
|
2015-06-25 13:08:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-31 00:04:06 -07:00
|
|
|
pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
|
2015-06-25 13:08:10 -07:00
|
|
|
match self.tables.borrow().node_types.get(&ex.id) {
|
|
|
|
Some(&t) => t,
|
|
|
|
None => {
|
2016-03-25 01:14:29 +01:00
|
|
|
bug!("no type for expr in fcx");
|
2015-06-25 13:08:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-18 11:23:14 -04:00
|
|
|
pub fn resolve_regions_and_report_errors(&self,
|
|
|
|
free_regions: &FreeRegionMap,
|
|
|
|
subject_node_id: ast::NodeId) {
|
|
|
|
let errors = self.region_vars.resolve_regions(free_regions, subject_node_id);
|
2016-03-15 04:49:10 -04:00
|
|
|
if !self.is_tainted_by_errors() {
|
2016-03-09 16:53:19 -05:00
|
|
|
// As a heuristic, just skip reporting region errors
|
|
|
|
// altogether if other errors have been reported while
|
|
|
|
// this infcx was in use. This is totally hokey but
|
|
|
|
// otherwise we have a hard time separating legit region
|
|
|
|
// errors from silly ones.
|
|
|
|
self.report_region_errors(&errors); // see error_reporting.rs
|
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
|
2015-06-18 20:25:05 +03:00
|
|
|
self.resolve_type_vars_if_possible(&t).to_string()
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn tys_to_string(&self, ts: &[Ty<'tcx>]) -> String {
|
2014-06-21 03:39:03 -07:00
|
|
|
let tstrs: Vec<String> = ts.iter().map(|t| self.ty_to_string(*t)).collect();
|
2015-07-10 08:19:21 -04:00
|
|
|
format!("({})", tstrs.join(", "))
|
2013-07-18 17:20:58 -07:00
|
|
|
}
|
|
|
|
|
2015-04-21 18:59:58 +03:00
|
|
|
pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String {
|
2015-06-18 20:25:05 +03:00
|
|
|
self.resolve_type_vars_if_possible(t).to_string()
|
2013-03-27 06:16:28 -04:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
|
2014-10-31 10:51:16 +02:00
|
|
|
match typ.sty {
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyInfer(ty::TyVar(v)) => {
|
2014-12-01 12:27:27 -05:00
|
|
|
// Not entirely obvious: if `typ` is a type variable,
|
|
|
|
// it can be resolved to an int/float variable, which
|
|
|
|
// can then be recursively resolved, hence the
|
|
|
|
// recursion. Note though that we prevent type
|
|
|
|
// variables from unifying to other type variables
|
|
|
|
// directly (though they may be embedded
|
|
|
|
// structurally), and we prevent cycles in any case,
|
|
|
|
// so this recursion should always be of very limited
|
|
|
|
// depth.
|
2016-03-03 10:43:52 +01:00
|
|
|
self.type_variables.borrow_mut()
|
2014-10-09 17:19:50 -04:00
|
|
|
.probe(v)
|
2014-12-01 12:27:27 -05:00
|
|
|
.map(|t| self.shallow_resolve(t))
|
2014-10-09 17:19:50 -04:00
|
|
|
.unwrap_or(typ)
|
|
|
|
}
|
|
|
|
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyInfer(ty::IntVar(v)) => {
|
2015-02-15 15:16:45 -05:00
|
|
|
self.int_unification_table
|
|
|
|
.borrow_mut()
|
2015-03-10 15:32:25 -04:00
|
|
|
.probe(v)
|
|
|
|
.map(|v| v.to_type(self.tcx))
|
2014-10-09 17:19:50 -04:00
|
|
|
.unwrap_or(typ)
|
|
|
|
}
|
|
|
|
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyInfer(ty::FloatVar(v)) => {
|
2015-02-15 15:16:45 -05:00
|
|
|
self.float_unification_table
|
|
|
|
.borrow_mut()
|
2015-03-10 15:32:25 -04:00
|
|
|
.probe(v)
|
|
|
|
.map(|v| v.to_type(self.tcx))
|
2014-10-09 17:19:50 -04:00
|
|
|
.unwrap_or(typ)
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => {
|
|
|
|
typ
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-17 23:50:24 +03:00
|
|
|
pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
|
2015-11-18 09:38:57 +00:00
|
|
|
where T: TypeFoldable<'tcx>
|
2015-08-17 23:50:24 +03:00
|
|
|
{
|
2014-12-01 12:27:27 -05:00
|
|
|
/*!
|
|
|
|
* Where possible, replaces type/int/float variables in
|
|
|
|
* `value` with their final value. Note that region variables
|
|
|
|
* are unaffected. If a type variable has not been unified, it
|
|
|
|
* is left as is. This is an idempotent operation that does
|
|
|
|
* not affect inference state in any way and so you can do it
|
|
|
|
* at will.
|
|
|
|
*/
|
|
|
|
|
2015-08-17 23:50:24 +03:00
|
|
|
if !value.needs_infer() {
|
|
|
|
return value.clone(); // avoid duplicated subst-folding
|
|
|
|
}
|
2014-12-01 12:27:27 -05:00
|
|
|
let mut r = resolve::OpportunisticTypeResolver::new(self);
|
2014-12-01 10:11:59 -05:00
|
|
|
value.fold_with(&mut r)
|
2013-03-27 06:16:28 -04:00
|
|
|
}
|
|
|
|
|
2015-12-06 20:21:23 +02:00
|
|
|
pub fn resolve_type_and_region_vars_if_possible<T>(&self, value: &T) -> T
|
|
|
|
where T: TypeFoldable<'tcx>
|
|
|
|
{
|
|
|
|
let mut r = resolve::OpportunisticTypeAndRegionResolver::new(self);
|
|
|
|
value.fold_with(&mut r)
|
|
|
|
}
|
|
|
|
|
2015-06-25 17:11:02 -07:00
|
|
|
/// Resolves all type variables in `t` and then, if any were left
|
|
|
|
/// unresolved, substitutes an error type. This is used after the
|
|
|
|
/// main checking when doing a second pass before writeback. The
|
|
|
|
/// justification is that writeback will produce an error for
|
|
|
|
/// these unconstrained type variables.
|
2015-06-25 13:08:10 -07:00
|
|
|
fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
|
|
|
|
let ty = self.resolve_type_vars_if_possible(t);
|
2015-07-23 21:08:29 -04:00
|
|
|
if ty.references_error() || ty.is_ty_var() {
|
2015-07-17 08:21:24 -04:00
|
|
|
debug!("resolve_type_vars_or_error: error from {:?}", ty);
|
|
|
|
Err(())
|
|
|
|
} else {
|
|
|
|
Ok(ty)
|
|
|
|
}
|
2015-06-25 13:08:10 -07:00
|
|
|
}
|
|
|
|
|
2015-07-10 19:16:35 -07:00
|
|
|
pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
|
2014-12-01 12:27:27 -05:00
|
|
|
/*!
|
|
|
|
* Attempts to resolve all type/region variables in
|
|
|
|
* `value`. Region inference must have been run already (e.g.,
|
|
|
|
* by calling `resolve_regions_and_report_errors`). If some
|
|
|
|
* variable was never unified, an `Err` results.
|
|
|
|
*
|
|
|
|
* This method is idempotent, but it not typically not invoked
|
|
|
|
* except during the writeback phase.
|
|
|
|
*/
|
|
|
|
|
|
|
|
resolve::fully_resolve(self, value)
|
|
|
|
}
|
|
|
|
|
2013-08-12 16:44:07 -07:00
|
|
|
// [Note-Type-error-reporting]
|
2015-06-11 16:21:46 -07:00
|
|
|
// An invariant is that anytime the expected or actual type is TyError (the special
|
2013-08-12 16:44:07 -07:00
|
|
|
// error type, meaning that an error occurred when typechecking this expression),
|
|
|
|
// this is a derived error. The error cascaded from another error (that was already
|
|
|
|
// reported), so it's not useful to display it to the user.
|
2016-07-08 22:51:29 +03:00
|
|
|
// The following methods implement this logic.
|
2015-06-11 16:21:46 -07:00
|
|
|
// They check if either the actual or expected type is TyError, and don't print the error
|
2013-08-12 16:44:07 -07:00
|
|
|
// in this case. The typechecker should only ever report type errors involving mismatched
|
2016-07-08 22:51:29 +03:00
|
|
|
// types using one of these methods, and should not call span_err directly for such
|
2013-08-12 16:44:07 -07:00
|
|
|
// errors.
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2014-12-08 20:26:43 -05:00
|
|
|
pub fn type_error_message<M>(&self,
|
|
|
|
sp: Span,
|
|
|
|
mk_msg: M,
|
2016-07-16 23:18:20 +03:00
|
|
|
actual_ty: Ty<'tcx>)
|
2015-12-21 10:00:43 +13:00
|
|
|
where M: FnOnce(String) -> String,
|
|
|
|
{
|
2016-07-16 23:18:20 +03:00
|
|
|
self.type_error_struct(sp, mk_msg, actual_ty).emit();
|
2015-12-21 10:00:43 +13:00
|
|
|
}
|
|
|
|
|
2016-07-21 16:07:08 +02:00
|
|
|
// FIXME: this results in errors without an error code. Deprecate?
|
2015-12-21 10:00:43 +13:00
|
|
|
pub fn type_error_struct<M>(&self,
|
|
|
|
sp: Span,
|
|
|
|
mk_msg: M,
|
2016-07-16 23:18:20 +03:00
|
|
|
actual_ty: Ty<'tcx>)
|
2015-12-23 19:27:20 +13:00
|
|
|
-> DiagnosticBuilder<'tcx>
|
2015-12-21 10:00:43 +13:00
|
|
|
where M: FnOnce(String) -> String,
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
2016-07-21 16:07:08 +02:00
|
|
|
self.type_error_struct_with_diag(sp, |actual_ty| {
|
|
|
|
self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty))
|
|
|
|
}, actual_ty)
|
|
|
|
}
|
2016-07-08 22:51:29 +03:00
|
|
|
|
2016-07-21 16:07:08 +02:00
|
|
|
pub fn type_error_struct_with_diag<M>(&self,
|
|
|
|
sp: Span,
|
|
|
|
mk_diag: M,
|
|
|
|
actual_ty: Ty<'tcx>)
|
|
|
|
-> DiagnosticBuilder<'tcx>
|
|
|
|
where M: FnOnce(String) -> DiagnosticBuilder<'tcx>,
|
|
|
|
{
|
2014-12-01 10:11:59 -05:00
|
|
|
let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
|
2016-07-21 16:07:08 +02:00
|
|
|
debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
|
2013-04-17 19:36:59 -07:00
|
|
|
|
2015-06-11 16:21:46 -07:00
|
|
|
// Don't report an error if actual type is TyError.
|
2015-06-24 02:54:32 +03:00
|
|
|
if actual_ty.references_error() {
|
2015-12-23 19:27:20 +13:00
|
|
|
return self.tcx.sess.diagnostic().struct_dummy();
|
2013-04-17 19:36:59 -07:00
|
|
|
}
|
|
|
|
|
2016-07-21 16:07:08 +02:00
|
|
|
mk_diag(self.ty_to_string(actual_ty))
|
2013-04-17 19:36:59 -07:00
|
|
|
}
|
|
|
|
|
2014-02-07 00:38:33 +02:00
|
|
|
pub fn report_mismatched_types(&self,
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: &ObligationCause<'tcx>,
|
2014-09-29 22:11:30 +03:00
|
|
|
expected: Ty<'tcx>,
|
|
|
|
actual: Ty<'tcx>,
|
2016-12-02 16:36:03 -08:00
|
|
|
err: TypeError<'tcx>)
|
|
|
|
-> DiagnosticBuilder<'tcx> {
|
2016-11-07 13:25:06 -05:00
|
|
|
let trace = TypeTrace::types(cause, true, expected, actual);
|
2016-10-27 00:43:00 +02:00
|
|
|
self.report_and_explain_type_error(trace, &err)
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2015-07-07 15:50:02 -07:00
|
|
|
pub fn report_conflicting_default_types(&self,
|
2015-07-12 21:43:13 -07:00
|
|
|
span: Span,
|
2016-11-07 13:25:06 -05:00
|
|
|
body_id: ast::NodeId,
|
2015-07-12 21:43:13 -07:00
|
|
|
expected: type_variable::Default<'tcx>,
|
|
|
|
actual: type_variable::Default<'tcx>) {
|
2015-07-07 15:50:02 -07:00
|
|
|
let trace = TypeTrace {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: ObligationCause::misc(span, body_id),
|
2015-09-06 21:51:58 +03:00
|
|
|
values: Types(ExpectedFound {
|
2015-07-12 20:33:17 -07:00
|
|
|
expected: expected.ty,
|
|
|
|
found: actual.ty
|
2015-07-07 15:50:02 -07:00
|
|
|
})
|
|
|
|
};
|
|
|
|
|
2016-03-18 14:47:40 -04:00
|
|
|
self.report_and_explain_type_error(
|
|
|
|
trace,
|
2015-09-06 21:51:58 +03:00
|
|
|
&TypeError::TyParamDefaultMismatch(ExpectedFound {
|
2015-07-07 16:06:35 -07:00
|
|
|
expected: expected,
|
|
|
|
found: actual
|
2016-03-18 14:47:40 -04:00
|
|
|
}))
|
|
|
|
.emit();
|
2015-07-07 15:50:02 -07:00
|
|
|
}
|
|
|
|
|
2014-11-12 14:11:22 -05:00
|
|
|
pub fn replace_late_bound_regions_with_fresh_var<T>(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
lbrct: LateBoundRegionConversionTime,
|
2014-12-12 11:28:35 -05:00
|
|
|
value: &ty::Binder<T>)
|
2016-11-08 14:02:55 +11:00
|
|
|
-> (T, FxHashMap<ty::BoundRegion, &'tcx ty::Region>)
|
2015-06-18 08:51:23 +03:00
|
|
|
where T : TypeFoldable<'tcx>
|
2014-11-05 22:06:04 -05:00
|
|
|
{
|
2015-09-06 21:51:58 +03:00
|
|
|
self.tcx.replace_late_bound_regions(
|
2014-11-15 16:47:59 -05:00
|
|
|
value,
|
2015-01-07 14:05:32 -05:00
|
|
|
|br| self.next_region_var(LateBoundRegion(span, br, lbrct)))
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
2015-01-03 04:40:33 -05:00
|
|
|
|
2016-05-21 08:16:07 -04:00
|
|
|
/// Given a higher-ranked projection predicate like:
|
|
|
|
///
|
|
|
|
/// for<'a> <T as Fn<&'a u32>>::Output = &'a u32
|
|
|
|
///
|
|
|
|
/// and a target trait-ref like:
|
|
|
|
///
|
|
|
|
/// <T as Fn<&'x u32>>
|
|
|
|
///
|
|
|
|
/// find a substitution `S` for the higher-ranked regions (here,
|
|
|
|
/// `['a => 'x]`) such that the predicate matches the trait-ref,
|
|
|
|
/// and then return the value (here, `&'a u32`) but with the
|
|
|
|
/// substitution applied (hence, `&'x u32`).
|
|
|
|
///
|
|
|
|
/// See `higher_ranked_match` in `higher_ranked/mod.rs` for more
|
|
|
|
/// details.
|
|
|
|
pub fn match_poly_projection_predicate(&self,
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: ObligationCause<'tcx>,
|
2016-05-21 08:16:07 -04:00
|
|
|
match_a: ty::PolyProjectionPredicate<'tcx>,
|
|
|
|
match_b: ty::TraitRef<'tcx>)
|
2016-05-21 08:29:50 -04:00
|
|
|
-> InferResult<'tcx, HrMatchResult<Ty<'tcx>>>
|
2016-05-21 08:16:07 -04:00
|
|
|
{
|
2016-11-07 13:25:06 -05:00
|
|
|
let span = cause.span;
|
2016-05-21 08:16:07 -04:00
|
|
|
let match_trait_ref = match_a.skip_binder().projection_ty.trait_ref;
|
|
|
|
let trace = TypeTrace {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: cause,
|
2016-05-21 08:16:07 -04:00
|
|
|
values: TraitRefs(ExpectedFound::new(true, match_trait_ref, match_b))
|
|
|
|
};
|
|
|
|
|
|
|
|
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
|
2016-07-25 16:37:30 -07:00
|
|
|
let mut combine = self.combine_fields(trace);
|
2016-07-25 15:07:57 -07:00
|
|
|
let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
|
2016-05-21 08:29:50 -04:00
|
|
|
Ok(InferOk { value: result, obligations: combine.obligations })
|
2016-05-21 08:16:07 -04:00
|
|
|
}
|
|
|
|
|
2015-01-03 04:40:33 -05:00
|
|
|
/// See `verify_generic_bound` method in `region_inference`
|
|
|
|
pub fn verify_generic_bound(&self,
|
|
|
|
origin: SubregionOrigin<'tcx>,
|
|
|
|
kind: GenericKind<'tcx>,
|
2016-08-25 23:58:52 +03:00
|
|
|
a: &'tcx ty::Region,
|
|
|
|
bound: VerifyBound<'tcx>) {
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("verify_generic_bound({:?}, {:?} <: {:?})",
|
|
|
|
kind,
|
|
|
|
a,
|
2015-08-07 10:33:18 -04:00
|
|
|
bound);
|
2015-01-03 04:40:33 -05:00
|
|
|
|
2015-08-07 10:33:18 -04:00
|
|
|
self.region_vars.verify_generic_bound(origin, kind, a, bound);
|
2015-01-03 04:40:33 -05:00
|
|
|
}
|
2015-01-05 21:50:01 -05:00
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
pub fn can_equate<T>(&self, a: &T, b: &T) -> UnitResult<'tcx>
|
|
|
|
where T: Relate<'tcx> + fmt::Debug
|
2015-01-05 21:50:01 -05:00
|
|
|
{
|
2015-06-18 20:25:05 +03:00
|
|
|
debug!("can_equate({:?}, {:?})", a, b);
|
2015-01-05 21:50:01 -05:00
|
|
|
self.probe(|_| {
|
|
|
|
// Gin up a dummy trace, since this won't be committed
|
|
|
|
// anyhow. We should make this typetrace stuff more
|
|
|
|
// generic so we don't have to do anything quite this
|
|
|
|
// terrible.
|
2016-10-04 02:19:40 +03:00
|
|
|
let trace = TypeTrace::dummy(self.tcx);
|
|
|
|
self.equate(true, trace, a, b).map(|InferOk { obligations, .. }| {
|
|
|
|
// FIXME(#32730) propagate obligations
|
|
|
|
assert!(obligations.is_empty());
|
|
|
|
})
|
|
|
|
})
|
2015-01-05 21:50:01 -05:00
|
|
|
}
|
2015-06-30 02:18:03 -07:00
|
|
|
|
|
|
|
pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
|
|
|
|
let ty = self.node_type(id);
|
|
|
|
self.resolve_type_vars_or_error(&ty)
|
|
|
|
}
|
|
|
|
|
2015-07-31 00:04:06 -07:00
|
|
|
pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
|
2016-10-20 06:33:20 +03:00
|
|
|
let ty = self.tables.borrow().expr_ty_adjusted(expr);
|
2015-06-30 02:18:03 -07:00
|
|
|
self.resolve_type_vars_or_error(&ty)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
|
|
|
let ty = self.resolve_type_vars_if_possible(&ty);
|
2016-04-29 06:00:23 +03:00
|
|
|
if let Some(ty) = self.tcx.lift_to_global(&ty) {
|
2016-05-11 04:14:41 +03:00
|
|
|
// Even if the type may have no inference variables, during
|
|
|
|
// type-checking closure types are in local tables only.
|
|
|
|
let local_closures = match self.tables {
|
2017-01-06 21:54:24 +02:00
|
|
|
InferTables::InProgress(_) => ty.has_closure_types(),
|
|
|
|
_ => false
|
2016-05-11 04:14:41 +03:00
|
|
|
};
|
|
|
|
if !local_closures {
|
2016-04-29 06:00:23 +03:00
|
|
|
return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span);
|
|
|
|
}
|
2015-08-17 20:26:22 +03:00
|
|
|
}
|
2016-04-29 06:00:23 +03:00
|
|
|
|
2016-11-25 21:21:03 -07:00
|
|
|
let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem);
|
2016-11-13 19:42:15 -07:00
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
// this can get called from typeck (by euv), and moves_by_default
|
|
|
|
// rightly refuses to work with inference variables, but
|
|
|
|
// moves_by_default has a cache, which we want to use in other
|
|
|
|
// cases.
|
2016-11-13 19:42:15 -07:00
|
|
|
!traits::type_known_to_meet_bound(self, ty, copy_def_id, span)
|
2015-06-30 02:18:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn node_method_ty(&self, method_call: ty::MethodCall)
|
2015-07-02 08:52:36 +03:00
|
|
|
-> Option<Ty<'tcx>> {
|
2015-06-30 02:18:03 -07:00
|
|
|
self.tables
|
|
|
|
.borrow()
|
|
|
|
.method_map
|
|
|
|
.get(&method_call)
|
|
|
|
.map(|method| method.ty)
|
|
|
|
.map(|ty| self.resolve_type_vars_if_possible(&ty))
|
|
|
|
}
|
|
|
|
|
2015-07-02 08:52:36 +03:00
|
|
|
pub fn node_method_id(&self, method_call: ty::MethodCall)
|
2015-08-16 06:32:28 -04:00
|
|
|
-> Option<DefId> {
|
2015-06-30 02:18:03 -07:00
|
|
|
self.tables
|
|
|
|
.borrow()
|
|
|
|
.method_map
|
|
|
|
.get(&method_call)
|
2015-07-02 08:52:36 +03:00
|
|
|
.map(|method| method.def_id)
|
2015-06-30 02:18:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_method_call(&self, id: ast::NodeId) -> bool {
|
|
|
|
self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
|
|
|
|
}
|
|
|
|
|
2016-08-25 23:58:52 +03:00
|
|
|
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
|
2015-06-30 02:18:03 -07:00
|
|
|
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
|
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
|
2015-06-30 02:18:03 -07:00
|
|
|
&self.parameter_environment
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn closure_kind(&self,
|
2015-08-16 06:32:28 -04:00
|
|
|
def_id: DefId)
|
2015-06-30 02:18:03 -07:00
|
|
|
-> Option<ty::ClosureKind>
|
|
|
|
{
|
2017-01-06 21:54:24 +02:00
|
|
|
if let InferTables::InProgress(tables) = self.tables {
|
2017-01-26 02:41:06 +02:00
|
|
|
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
|
2017-01-06 21:54:24 +02:00
|
|
|
return tables.borrow().closure_kinds.get(&id).cloned();
|
|
|
|
}
|
2015-09-17 14:29:59 -04:00
|
|
|
}
|
2017-01-06 21:54:24 +02:00
|
|
|
|
|
|
|
// During typeck, ALL closures are local. But afterwards,
|
|
|
|
// during trans, we see closure ids from other traits.
|
|
|
|
// That may require loading the closure data out of the
|
|
|
|
// cstore.
|
|
|
|
Some(self.tcx.closure_kind(def_id))
|
2015-06-30 02:18:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn closure_type(&self,
|
2015-08-16 06:32:28 -04:00
|
|
|
def_id: DefId,
|
2016-04-29 08:30:54 +03:00
|
|
|
substs: ty::ClosureSubsts<'tcx>)
|
2015-07-16 09:46:35 -04:00
|
|
|
-> ty::ClosureTy<'tcx>
|
2015-06-30 02:18:03 -07:00
|
|
|
{
|
2017-01-06 21:54:24 +02:00
|
|
|
if let InferTables::InProgress(tables) = self.tables {
|
2017-01-26 02:41:06 +02:00
|
|
|
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
|
2017-01-06 21:54:24 +02:00
|
|
|
if let Some(ty) = tables.borrow().closure_tys.get(&id) {
|
|
|
|
return ty.subst(self.tcx, substs.substs);
|
|
|
|
}
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
}
|
2015-06-30 02:18:03 -07:00
|
|
|
|
2017-01-06 21:54:24 +02:00
|
|
|
self.tcx.closure_type(def_id, substs)
|
2015-06-30 02:18:03 -07:00
|
|
|
}
|
2013-05-02 14:32:37 -04:00
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> {
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn span(&self) -> Span {
|
2016-11-07 13:25:06 -05:00
|
|
|
self.cause.span
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
2014-11-15 20:30:33 -05:00
|
|
|
|
2016-11-07 13:25:06 -05:00
|
|
|
pub fn types(cause: &ObligationCause<'tcx>,
|
2015-01-16 05:48:15 +02:00
|
|
|
a_is_expected: bool,
|
|
|
|
a: Ty<'tcx>,
|
|
|
|
b: Ty<'tcx>)
|
|
|
|
-> TypeTrace<'tcx> {
|
|
|
|
TypeTrace {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: cause.clone(),
|
2016-03-17 00:15:31 +02:00
|
|
|
values: Types(ExpectedFound::new(a_is_expected, a, b))
|
2015-01-16 05:48:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
pub fn dummy(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> TypeTrace<'tcx> {
|
2014-11-15 20:30:33 -05:00
|
|
|
TypeTrace {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: ObligationCause::dummy(),
|
2015-09-06 21:51:58 +03:00
|
|
|
values: Types(ExpectedFound {
|
2014-12-25 07:20:48 -05:00
|
|
|
expected: tcx.types.err,
|
|
|
|
found: tcx.types.err,
|
2014-11-15 20:30:33 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
|
2015-06-18 08:51:23 +03:00
|
|
|
impl<'tcx> fmt::Debug for TypeTrace<'tcx> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2016-11-07 13:25:06 -05:00
|
|
|
write!(f, "TypeTrace({:?})", self.cause)
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> SubregionOrigin<'tcx> {
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn span(&self) -> Span {
|
2013-05-23 21:37:37 -04:00
|
|
|
match *self {
|
2014-04-22 02:21:52 +03:00
|
|
|
Subtype(ref a) => a.span(),
|
2013-06-25 12:04:50 -04:00
|
|
|
InfStackClosure(a) => a,
|
2013-05-23 21:37:37 -04:00
|
|
|
InvokeClosure(a) => a,
|
|
|
|
DerefPointer(a) => a,
|
2014-02-07 14:43:48 -05:00
|
|
|
FreeVariable(a, _) => a,
|
2013-05-23 21:37:37 -04:00
|
|
|
IndexSlice(a) => a,
|
|
|
|
RelateObjectBound(a) => a,
|
2014-11-15 17:25:05 -05:00
|
|
|
RelateParamBound(a, _) => a,
|
2014-08-27 21:46:52 -04:00
|
|
|
RelateRegionParamBound(a) => a,
|
|
|
|
RelateDefaultParamBound(a, _) => a,
|
2013-05-23 21:37:37 -04:00
|
|
|
Reborrow(a) => a,
|
2014-02-07 14:43:48 -05:00
|
|
|
ReborrowUpvar(a, _) => a,
|
2015-08-07 10:28:51 -04:00
|
|
|
DataBorrowed(_, a) => a,
|
2013-05-23 21:37:37 -04:00
|
|
|
ReferenceOutlivesReferent(_, a) => a,
|
2015-08-07 10:28:51 -04:00
|
|
|
ParameterInScope(_, a) => a,
|
2014-08-27 21:46:52 -04:00
|
|
|
ExprTypeIsNotInScope(_, a) => a,
|
2013-05-23 21:37:37 -04:00
|
|
|
BindingTypeIsNotValidAtDecl(a) => a,
|
|
|
|
CallRcvr(a) => a,
|
|
|
|
CallArg(a) => a,
|
|
|
|
CallReturn(a) => a,
|
2015-02-12 12:48:54 -05:00
|
|
|
Operand(a) => a,
|
2013-05-23 21:37:37 -04:00
|
|
|
AddrOf(a) => a,
|
|
|
|
AutoBorrow(a) => a,
|
2014-10-27 12:55:16 +01:00
|
|
|
SafeDestructor(a) => a,
|
2016-10-05 10:17:14 -04:00
|
|
|
CompareImplMethodObligation { span, .. } => span,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 10:45:49 -04:00
|
|
|
pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>,
|
|
|
|
default: F)
|
|
|
|
-> Self
|
2016-10-05 10:17:14 -04:00
|
|
|
where F: FnOnce() -> Self
|
|
|
|
{
|
|
|
|
match cause.code {
|
|
|
|
traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) =>
|
|
|
|
SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span),
|
|
|
|
|
|
|
|
traits::ObligationCauseCode::CompareImplMethodObligation { item_name,
|
|
|
|
impl_item_def_id,
|
2016-10-12 16:38:58 -04:00
|
|
|
trait_item_def_id,
|
|
|
|
lint_id } =>
|
2016-10-05 10:17:14 -04:00
|
|
|
SubregionOrigin::CompareImplMethodObligation {
|
|
|
|
span: cause.span,
|
|
|
|
item_name: item_name,
|
|
|
|
impl_item_def_id: impl_item_def_id,
|
|
|
|
trait_item_def_id: trait_item_def_id,
|
2016-10-12 16:38:58 -04:00
|
|
|
lint_id: lint_id,
|
2016-10-05 10:17:14 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
_ => default(),
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-10 07:02:27 -04:00
|
|
|
impl RegionVariableOrigin {
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn span(&self) -> Span {
|
2013-05-23 21:37:37 -04:00
|
|
|
match *self {
|
|
|
|
MiscVariable(a) => a,
|
|
|
|
PatternRegion(a) => a,
|
|
|
|
AddrOfRegion(a) => a,
|
|
|
|
Autoref(a) => a,
|
2015-03-10 07:02:27 -04:00
|
|
|
Coercion(a) => a,
|
2017-01-06 14:35:23 -05:00
|
|
|
EarlyBoundRegion(a, ..) => a,
|
2016-08-26 19:23:42 +03:00
|
|
|
LateBoundRegion(a, ..) => a,
|
2016-06-21 18:08:13 -04:00
|
|
|
BoundRegionInCoherence(_) => syntax_pos::DUMMY_SP,
|
2014-02-07 14:43:48 -05:00
|
|
|
UpvarRegion(_, a) => a
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-16 19:38:17 +03:00
|
|
|
|
|
|
|
impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
|
|
|
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
|
|
|
match *self {
|
|
|
|
ValuePairs::Types(ref ef) => {
|
|
|
|
ValuePairs::Types(ef.fold_with(folder))
|
|
|
|
}
|
|
|
|
ValuePairs::TraitRefs(ref ef) => {
|
|
|
|
ValuePairs::TraitRefs(ef.fold_with(folder))
|
|
|
|
}
|
|
|
|
ValuePairs::PolyTraitRefs(ref ef) => {
|
|
|
|
ValuePairs::PolyTraitRefs(ef.fold_with(folder))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
|
|
|
match *self {
|
|
|
|
ValuePairs::Types(ref ef) => ef.visit_with(visitor),
|
|
|
|
ValuePairs::TraitRefs(ref ef) => ef.visit_with(visitor),
|
|
|
|
ValuePairs::PolyTraitRefs(ref ef) => ef.visit_with(visitor),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> TypeFoldable<'tcx> for TypeTrace<'tcx> {
|
|
|
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
|
|
|
TypeTrace {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: self.cause.fold_with(folder),
|
2016-07-16 19:38:17 +03:00
|
|
|
values: self.values.fold_with(folder)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
2016-11-07 13:25:06 -05:00
|
|
|
self.cause.visit_with(visitor) || self.values.visit_with(visitor)
|
2016-07-16 19:38:17 +03:00
|
|
|
}
|
|
|
|
}
|