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
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub use self::freshen::TypeFreshener;
|
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;
|
2013-01-29 16:26:16 -08:00
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
use arena::SyncDroplessArena;
|
|
|
|
use errors::DiagnosticBuilder;
|
2016-03-29 12:54:26 +03:00
|
|
|
use hir::def_id::DefId;
|
2017-11-10 14:59:17 -05:00
|
|
|
use middle::free_region::RegionRelations;
|
2016-11-13 19:42:15 -07:00
|
|
|
use middle::lang_items;
|
2018-08-29 13:25:47 -04:00
|
|
|
use middle::region;
|
2017-07-16 07:07:51 -04:00
|
|
|
use rustc_data_structures::unify as ut;
|
2018-08-29 13:25:47 -04:00
|
|
|
use std::cell::{Cell, Ref, RefCell, RefMut};
|
2018-05-14 22:27:45 +10:00
|
|
|
use std::collections::BTreeMap;
|
2015-03-19 14:49:28 -07:00
|
|
|
use std::fmt;
|
2013-01-08 19:37:25 -08:00
|
|
|
use syntax::ast;
|
2018-04-12 21:16:26 +01:00
|
|
|
use syntax_pos::symbol::InternedString;
|
2018-08-29 13:25:47 -04:00
|
|
|
use syntax_pos::{self, Span};
|
|
|
|
use traits::{self, ObligationCause, PredicateObligations, TraitEngine};
|
|
|
|
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
|
|
|
|
use ty::fold::TypeFoldable;
|
|
|
|
use ty::relate::RelateResult;
|
|
|
|
use ty::subst::{Kind, Substs};
|
|
|
|
use ty::{self, GenericParamDefKind, Ty, TyCtxt};
|
|
|
|
use ty::{FloatVid, IntVid, TyVid};
|
2017-11-14 15:12:36 -05:00
|
|
|
use util::nodemap::FxHashMap;
|
2017-07-01 15:41:49 +02: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;
|
2017-11-05 05:48:16 -05:00
|
|
|
use self::lexical_region_resolve::LexicalRegionResolutions;
|
2017-12-01 05:07:52 -05:00
|
|
|
use self::outlives::env::OutlivesEnvironment;
|
2018-08-29 13:25:47 -04:00
|
|
|
use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
|
|
|
|
use self::region_constraints::{RegionConstraintCollector, 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
|
|
|
|
2018-08-23 13:51:32 -06:00
|
|
|
pub mod opaque_types;
|
2017-05-24 09:43:20 -04:00
|
|
|
pub mod at;
|
2018-02-09 10:39:36 -05:00
|
|
|
pub mod canonical;
|
2016-07-25 13:08:48 -07:00
|
|
|
mod combine;
|
|
|
|
mod equate;
|
2014-07-22 07:46:36 -04:00
|
|
|
pub mod error_reporting;
|
2018-08-29 13:25:47 -04:00
|
|
|
mod freshen;
|
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;
|
2017-11-15 16:58:14 -05:00
|
|
|
mod lexical_region_resolve;
|
2018-08-29 13:25:47 -04:00
|
|
|
mod lub;
|
2017-11-10 14:59:17 -05:00
|
|
|
pub mod outlives;
|
2018-08-29 13:25:47 -04:00
|
|
|
pub mod region_constraints;
|
2013-01-29 16:26:16 -08:00
|
|
|
pub mod resolve;
|
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]
|
2018-02-25 10:58:54 -05:00
|
|
|
#[derive(Debug)]
|
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
|
|
|
|
2018-09-12 15:43:26 -04:00
|
|
|
/// A flag that is given when running region resolution: if true, it
|
|
|
|
/// indicates that we should not report the region errors to the user
|
|
|
|
/// if NLL is enabled, since NLL will also detect them (and do a
|
|
|
|
/// better job of it).
|
|
|
|
///
|
|
|
|
/// Currently, NLL only runs on HIR bodies, so you should use `false`
|
|
|
|
/// unless you are region-checking a `hir::Body` (basically, a fn or
|
|
|
|
/// expression).
|
|
|
|
pub struct UnlessNll(pub bool);
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
2016-05-03 05:23:22 +03:00
|
|
|
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2017-06-09 10:55:16 +03:00
|
|
|
/// During type-checking/inference of a body, `in_progress_tables`
|
|
|
|
/// contains a reference to the tables being built up, which are
|
|
|
|
/// used for reading closure kinds/signatures as they are inferred,
|
|
|
|
/// and for error reporting logic to read arbitrary node types.
|
|
|
|
pub in_progress_tables: Option<&'a RefCell<ty::TypeckTables<'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
|
2017-07-16 07:07:51 -04:00
|
|
|
int_unification_table: RefCell<ut::UnificationTable<ut::InPlace<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
|
2017-07-16 07:07:51 -04:00
|
|
|
float_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::FloatVid>>>,
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2017-11-05 07:22:39 -05:00
|
|
|
// Tracks the set of region variables and the constraints between
|
|
|
|
// them. This is initially `Some(_)` but when
|
|
|
|
// `resolve_regions_and_report_errors` is invoked, this gets set
|
|
|
|
// to `None` -- further attempts to perform unification etc may
|
|
|
|
// fail if new region constraints would've been added.
|
|
|
|
region_constraints: RefCell<Option<RegionConstraintCollector<'tcx>>>,
|
2015-06-24 13:40:54 -07:00
|
|
|
|
2017-11-05 05:48:16 -05:00
|
|
|
// Once region inference is done, the values for each variable.
|
|
|
|
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
|
|
|
|
|
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.
|
2017-05-08 19:45:27 +03:00
|
|
|
pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>,
|
2015-09-24 19:58:00 +03: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
|
|
|
|
2017-04-15 23:51:58 +03:00
|
|
|
// This flag is true while there is an active snapshot.
|
|
|
|
in_snapshot: Cell<bool>,
|
2017-11-01 13:41:07 -04:00
|
|
|
|
|
|
|
// A set of constraints that regionck must validate. Each
|
|
|
|
// constraint has the form `T:'a`, meaning "some type `T` must
|
|
|
|
// outlive the lifetime 'a". These constraints derive from
|
|
|
|
// instantiated type parameters. So if you had a struct defined
|
|
|
|
// like
|
|
|
|
//
|
|
|
|
// struct Foo<T:'static> { ... }
|
|
|
|
//
|
|
|
|
// then in some expression `let x = Foo { ... }` it will
|
|
|
|
// instantiate the type parameter `T` with a fresh type `$0`. At
|
|
|
|
// the same time, it will record a region obligation of
|
|
|
|
// `$0:'static`. This will get checked later by regionck. (We
|
|
|
|
// can't generally check these things right away because we have
|
|
|
|
// to wait until types are resolved.)
|
|
|
|
//
|
|
|
|
// These are stored in a map keyed to the id of the innermost
|
|
|
|
// enclosing fn body / static initializer expression. This is
|
|
|
|
// because the location where the obligation was incurred can be
|
|
|
|
// relevant with respect to which sublifetime assumptions are in
|
|
|
|
// place. The reason that we store under the fn-id, and not
|
|
|
|
// something more fine-grained, is so that it is easier for
|
|
|
|
// regionck to be sure that it has found *all* the region
|
|
|
|
// obligations (otherwise, it's easy to fail to walk to a
|
|
|
|
// particular node-id).
|
2017-11-03 05:31:19 -04:00
|
|
|
//
|
|
|
|
// Before running `resolve_regions_and_report_errors`, the creator
|
|
|
|
// of the inference context is expected to invoke
|
|
|
|
// `process_region_obligations` (defined in `self::region_obligations`)
|
|
|
|
// for each body-id in this map, which will process the
|
|
|
|
// obligations within. This is expected to be done 'late enough'
|
|
|
|
// that all type inference variables have been bound and so forth.
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
|
|
|
pub region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
|
2018-02-07 10:16:44 -07:00
|
|
|
|
|
|
|
/// What is the innermost universe we have created? Starts out as
|
|
|
|
/// `UniverseIndex::root()` but grows from there as we enter
|
|
|
|
/// universal quantifiers.
|
|
|
|
///
|
|
|
|
/// NB: At present, we exclude the universal quantifiers on the
|
|
|
|
/// item we are type-checking, and just consider those names as
|
|
|
|
/// part of the root universe. So this would only get incremented
|
|
|
|
/// when we enter into a higher-ranked (`for<..>`) type or trait
|
|
|
|
/// bound.
|
2018-02-08 13:14:24 -07:00
|
|
|
universe: Cell<ty::UniverseIndex>,
|
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.
|
2018-05-14 22:27:45 +10:00
|
|
|
pub type SkolemizationMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
|
2014-12-12 06:37:42 -05:00
|
|
|
|
2017-02-27 22:09:13 +03:00
|
|
|
/// See `error_reporting` module 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>>),
|
2018-02-09 10:43:15 -05:00
|
|
|
Regions(ExpectedFound<ty::Region<'tcx>>),
|
2015-09-06 21:51:58 +03:00
|
|
|
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.
|
|
|
|
///
|
2017-02-27 22:09:13 +03:00
|
|
|
/// See `error_reporting` module 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.
|
|
|
|
///
|
2017-02-27 22:09:13 +03:00
|
|
|
/// See `error_reporting` module 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,
|
|
|
|
},
|
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 {
|
2018-08-29 13:25:47 -04:00
|
|
|
Path, // foo::bar
|
|
|
|
MethodCall, // foo.bar() <-- parameters on impl providing bar()
|
2015-08-07 10:28:51 -04:00
|
|
|
OverloadedOperator, // a + b when overloaded
|
2018-08-29 13:25:47 -04:00
|
|
|
OverloadedDeref, // *a when overloaded
|
2015-08-07 10:28:51 -04:00
|
|
|
}
|
|
|
|
|
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
|
2017-08-19 13:41:10 -07:00
|
|
|
AssocTypeProjection(DefId),
|
2014-11-05 22:06:04 -05:00
|
|
|
}
|
|
|
|
|
2013-05-23 21:37:37 -04:00
|
|
|
/// Reasons to create a region inference variable
|
|
|
|
///
|
2017-02-27 22:09:13 +03:00
|
|
|
/// See `error_reporting` module for more details
|
2017-11-06 05:21:48 -05:00
|
|
|
#[derive(Copy, 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
|
2018-04-12 21:16:26 +01:00
|
|
|
EarlyBoundRegion(Span, InternedString),
|
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),
|
2017-11-06 05:21:48 -05:00
|
|
|
|
|
|
|
// This origin is used for the inference variables that we create
|
|
|
|
// during NLL region processing.
|
|
|
|
NLL(NLLRegionVariableOrigin),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum NLLRegionVariableOrigin {
|
|
|
|
// During NLL region processing, we create variables for free
|
|
|
|
// regions that we encounter in the function signature and
|
|
|
|
// elsewhere. This origin indices we've got one of those.
|
|
|
|
FreeRegion,
|
|
|
|
|
2018-07-23 17:30:59 +03:00
|
|
|
BoundRegion(ty::UniverseIndex),
|
|
|
|
|
2018-07-22 19:42:40 +03:00
|
|
|
Existential,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl NLLRegionVariableOrigin {
|
|
|
|
pub fn is_universal(self) -> bool {
|
|
|
|
match self {
|
|
|
|
NLLRegionVariableOrigin::FreeRegion => true,
|
2018-07-23 17:30:59 +03:00
|
|
|
NLLRegionVariableOrigin::BoundRegion(..) => true,
|
2018-07-22 19:42:40 +03:00
|
|
|
NLLRegionVariableOrigin::Existential => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_existential(self) -> bool {
|
|
|
|
!self.is_universal()
|
|
|
|
}
|
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),
|
2018-08-29 13:25:47 -04:00
|
|
|
UnresolvedTy(TyVid),
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2017-11-01 13:41:07 -04:00
|
|
|
/// See the `region_obligations` field for more information.
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct RegionObligation<'tcx> {
|
|
|
|
pub sub_region: ty::Region<'tcx>,
|
|
|
|
pub sup_type: Ty<'tcx>,
|
|
|
|
pub cause: ObligationCause<'tcx>,
|
|
|
|
}
|
|
|
|
|
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 {
|
2018-08-29 13:25:47 -04:00
|
|
|
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"),
|
2016-03-17 00:15:31 +02:00
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-09 10:55:16 +03:00
|
|
|
/// Helper type of a temporary returned by tcx.infer_ctxt().
|
2016-05-11 04:14:41 +03:00
|
|
|
/// Necessary because we can't write the following bound:
|
|
|
|
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
|
2018-08-29 13:25:47 -04:00
|
|
|
pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
2016-05-11 04:14:41 +03:00
|
|
|
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
2018-04-15 16:01:38 +02:00
|
|
|
arena: SyncDroplessArena,
|
2017-01-25 16:24:00 -05:00
|
|
|
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
2017-06-09 10:55:16 +03:00
|
|
|
pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
2016-05-11 04:14:41 +03:00
|
|
|
InferCtxtBuilder {
|
|
|
|
global_tcx: self,
|
2018-04-15 16:01:38 +02:00
|
|
|
arena: SyncDroplessArena::new(),
|
2017-06-09 10:55:16 +03:00
|
|
|
fresh_tables: None,
|
2016-05-11 04:14:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
2017-06-09 10:55:16 +03:00
|
|
|
/// Used only by `rustc_typeck` during body type-checking/inference,
|
|
|
|
/// will initialize `in_progress_tables` with fresh `TypeckTables`.
|
2017-08-04 09:49:40 +02:00
|
|
|
pub fn with_fresh_in_progress_tables(mut self, table_owner: DefId) -> Self {
|
2017-08-11 11:56:26 +02:00
|
|
|
self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty(Some(table_owner))));
|
2017-06-09 10:55:16 +03:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2016-05-11 04:14:41 +03:00
|
|
|
pub fn enter<F, R>(&'tcx mut self, f: F) -> R
|
2018-08-29 13:25:47 -04:00
|
|
|
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,
|
2016-05-11 04:14:41 +03:00
|
|
|
} = *self;
|
2017-06-09 10:55:16 +03:00
|
|
|
let in_progress_tables = fresh_tables.as_ref();
|
2018-08-29 13:25:47 -04:00
|
|
|
global_tcx.enter_local(arena, |tcx| {
|
|
|
|
f(InferCtxt {
|
|
|
|
tcx,
|
|
|
|
in_progress_tables,
|
|
|
|
projection_cache: RefCell::new(traits::ProjectionCache::new()),
|
|
|
|
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
|
|
|
|
int_unification_table: RefCell::new(ut::UnificationTable::new()),
|
|
|
|
float_unification_table: RefCell::new(ut::UnificationTable::new()),
|
|
|
|
region_constraints: RefCell::new(Some(RegionConstraintCollector::new())),
|
|
|
|
lexical_region_resolutions: RefCell::new(None),
|
|
|
|
selection_cache: traits::SelectionCache::new(),
|
|
|
|
evaluation_cache: traits::EvaluationCache::new(),
|
|
|
|
reported_trait_errors: RefCell::new(FxHashMap()),
|
|
|
|
tainted_by_errors_flag: Cell::new(false),
|
|
|
|
err_count_on_creation: tcx.sess.err_count(),
|
|
|
|
in_snapshot: Cell::new(false),
|
|
|
|
region_obligations: RefCell::new(vec![]),
|
|
|
|
universe: Cell::new(ty::UniverseIndex::ROOT),
|
|
|
|
})
|
|
|
|
})
|
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> {
|
2017-03-09 21:47:09 -05:00
|
|
|
pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
|
2016-03-17 00:15:31 +02:00
|
|
|
if a_is_expected {
|
2018-08-29 13:25:47 -04:00
|
|
|
ExpectedFound {
|
|
|
|
expected: a,
|
|
|
|
found: b,
|
|
|
|
}
|
2016-03-17 00:15:31 +02:00
|
|
|
} else {
|
2018-08-29 13:25:47 -04:00
|
|
|
ExpectedFound {
|
|
|
|
expected: b,
|
|
|
|
found: a,
|
|
|
|
}
|
2016-03-17 00:15:31 +02:00
|
|
|
}
|
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, ()> {
|
2018-08-29 13:25:47 -04:00
|
|
|
InferOk {
|
|
|
|
value: (),
|
|
|
|
obligations: self.obligations,
|
|
|
|
}
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
2018-06-27 16:04:32 -04:00
|
|
|
|
|
|
|
/// Extract `value`, registering any obligations into `fulfill_cx`
|
|
|
|
pub fn into_value_registering_obligations(
|
|
|
|
self,
|
|
|
|
infcx: &InferCtxt<'_, '_, 'tcx>,
|
|
|
|
fulfill_cx: &mut impl TraitEngine<'tcx>,
|
|
|
|
) -> T {
|
|
|
|
let InferOk { value, obligations } = self;
|
|
|
|
for obligation in obligations {
|
|
|
|
fulfill_cx.register_predicate_obligation(infcx, obligation);
|
|
|
|
}
|
|
|
|
value
|
|
|
|
}
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
|
2018-02-09 10:39:36 -05:00
|
|
|
impl<'tcx> InferOk<'tcx, ()> {
|
|
|
|
pub fn into_obligations(self) -> PredicateObligations<'tcx> {
|
|
|
|
self.obligations
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-01 10:11:59 -05:00
|
|
|
#[must_use = "once you start a snapshot, you should always consume it"]
|
2018-08-29 13:25:47 -04:00
|
|
|
pub struct CombinedSnapshot<'a, 'tcx: 'a> {
|
2016-05-21 08:18:52 -04:00
|
|
|
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
|
2017-07-16 08:32:21 -04:00
|
|
|
type_snapshot: type_variable::Snapshot<'tcx>,
|
2017-07-16 07:07:51 -04:00
|
|
|
int_snapshot: ut::Snapshot<ut::InPlace<ty::IntVid>>,
|
|
|
|
float_snapshot: ut::Snapshot<ut::InPlace<ty::FloatVid>>,
|
2017-11-05 06:55:40 -05:00
|
|
|
region_constraints_snapshot: RegionSnapshot,
|
2017-11-14 15:12:36 -05:00
|
|
|
region_obligations_snapshot: usize,
|
2018-02-08 14:12:32 -07:00
|
|
|
universe: ty::UniverseIndex,
|
2017-04-15 23:51:58 +03:00
|
|
|
was_in_snapshot: bool,
|
2017-05-17 00:54:04 +03:00
|
|
|
_in_progress_tables: Option<Ref<'a, ty::TypeckTables<'tcx>>>,
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2016-04-29 06:00:23 +03:00
|
|
|
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
2017-04-15 23:51:58 +03:00
|
|
|
pub fn is_in_snapshot(&self) -> bool {
|
|
|
|
self.in_snapshot.get()
|
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
|
2014-12-12 06:13:42 -05:00
|
|
|
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 {
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Infer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
|
2018-08-29 13:25:47 -04:00
|
|
|
_ => false,
|
2014-10-24 21:14:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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;
|
2018-08-29 13:25:47 -04:00
|
|
|
use ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt};
|
2014-12-15 09:45:28 -05:00
|
|
|
match ty.sty {
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Infer(ty::IntVar(vid)) => {
|
2018-08-29 13:25:47 -04:00
|
|
|
if self.int_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.probe_value(vid)
|
|
|
|
.is_some()
|
|
|
|
{
|
2015-02-16 05:07:22 -05:00
|
|
|
Neither
|
|
|
|
} else {
|
|
|
|
UnconstrainedInt
|
2014-12-15 09:45:28 -05:00
|
|
|
}
|
2018-08-29 13:25:47 -04:00
|
|
|
}
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Infer(ty::FloatVar(vid)) => {
|
2018-08-29 13:25:47 -04:00
|
|
|
if self.float_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.probe_value(vid)
|
|
|
|
.is_some()
|
|
|
|
{
|
2015-02-16 05:07:22 -05:00
|
|
|
Neither
|
|
|
|
} else {
|
|
|
|
UnconstrainedFloat
|
2014-12-15 09:45:28 -05:00
|
|
|
}
|
2018-08-29 13:25:47 -04:00
|
|
|
}
|
2014-12-15 09:45:28 -05:00
|
|
|
_ => Neither,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-14 21:44:23 -04:00
|
|
|
pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {
|
2018-07-16 19:35:45 +02:00
|
|
|
let mut type_variables = self.type_variables.borrow_mut();
|
|
|
|
let mut int_unification_table = self.int_unification_table.borrow_mut();
|
|
|
|
let mut float_unification_table = self.float_unification_table.borrow_mut();
|
|
|
|
|
|
|
|
type_variables
|
|
|
|
.unsolved_variables()
|
|
|
|
.into_iter()
|
|
|
|
.map(|t| self.tcx.mk_var(t))
|
|
|
|
.chain(
|
2017-07-16 07:07:51 -04:00
|
|
|
(0..int_unification_table.len())
|
|
|
|
.map(|i| ty::IntVid { index: i as u32 })
|
|
|
|
.filter(|&vid| int_unification_table.probe_value(vid).is_none())
|
2018-08-29 13:25:47 -04:00
|
|
|
.map(|v| self.tcx.mk_int_var(v)),
|
|
|
|
)
|
|
|
|
.chain(
|
2017-07-16 07:07:51 -04:00
|
|
|
(0..float_unification_table.len())
|
|
|
|
.map(|i| ty::FloatVid { index: i as u32 })
|
|
|
|
.filter(|&vid| float_unification_table.probe_value(vid).is_none())
|
2018-08-29 13:25:47 -04:00
|
|
|
.map(|v| self.tcx.mk_float_var(v)),
|
|
|
|
)
|
|
|
|
.collect()
|
2015-07-07 15:50:02 -07:00
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
fn combine_fields(
|
|
|
|
&'a self,
|
|
|
|
trace: TypeTrace<'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
) -> CombineFields<'a, 'gcx, 'tcx> {
|
2016-03-29 20:06:42 -07:00
|
|
|
CombineFields {
|
|
|
|
infcx: self,
|
2017-07-03 11:19:51 -07:00
|
|
|
trace,
|
2016-03-29 20:06:42 -07:00
|
|
|
cause: None,
|
2017-05-23 04:19:47 -04:00
|
|
|
param_env,
|
2016-03-29 20:06:42 -07:00
|
|
|
obligations: PredicateObligations::new(),
|
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2017-04-15 23:51:58 +03:00
|
|
|
// Clear the "currently in a snapshot" flag, invoke the closure,
|
2016-09-13 18:31:26 -04:00
|
|
|
// then restore the flag to its original value. This flag is a
|
|
|
|
// debugging measure designed to detect cases where we start a
|
2017-04-15 23:51:58 +03:00
|
|
|
// snapshot, create type variables, and register obligations
|
|
|
|
// which may involve those type variables in the fulfillment cx,
|
|
|
|
// potentially leaving "dangling type variables" behind.
|
|
|
|
// In such cases, an assertion will fail when attempting to
|
|
|
|
// register obligations, within a snapshot. Very useful, much
|
|
|
|
// better than grovelling through megabytes of RUST_LOG output.
|
2016-09-13 18:31:26 -04:00
|
|
|
//
|
2017-04-15 23:51:58 +03:00
|
|
|
// HOWEVER, in some cases the flag is unhelpful. In particular, we
|
2016-09-13 18:31:26 -04:00
|
|
|
// 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.
|
2017-04-15 23:51:58 +03:00
|
|
|
pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R
|
2018-08-29 13:25:47 -04:00
|
|
|
where
|
|
|
|
F: FnOnce(&Self) -> R,
|
2016-09-13 18:31:26 -04:00
|
|
|
{
|
2017-04-15 23:51:58 +03:00
|
|
|
let flag = self.in_snapshot.get();
|
|
|
|
self.in_snapshot.set(false);
|
2016-09-13 18:31:26 -04:00
|
|
|
let result = func(self);
|
2017-04-15 23:51:58 +03:00
|
|
|
self.in_snapshot.set(flag);
|
2016-09-13 18:31:26 -04:00
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2017-07-16 08:32:21 -04:00
|
|
|
fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> {
|
2016-05-21 05:41:40 -04:00
|
|
|
debug!("start_snapshot()");
|
|
|
|
|
2017-04-15 23:51:58 +03:00
|
|
|
let in_snapshot = self.in_snapshot.get();
|
|
|
|
self.in_snapshot.set(true);
|
2016-05-25 21:12:35 +03:00
|
|
|
|
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(),
|
2017-11-05 07:22:39 -05:00
|
|
|
region_constraints_snapshot: self.borrow_region_constraints().start_snapshot(),
|
2017-11-14 15:12:36 -05:00
|
|
|
region_obligations_snapshot: self.region_obligations.borrow().len(),
|
2018-02-08 14:12:32 -07:00
|
|
|
universe: self.universe(),
|
2017-04-15 23:51:58 +03:00
|
|
|
was_in_snapshot: in_snapshot,
|
2017-05-17 00:54:04 +03:00
|
|
|
// Borrow tables "in progress" (i.e. during typeck)
|
|
|
|
// to ban writes from within a snapshot to them.
|
2018-08-29 13:25:47 -04:00
|
|
|
_in_progress_tables: self.in_progress_tables.map(|tables| tables.borrow()),
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-16 08:32:21 -04:00
|
|
|
fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) {
|
2015-07-24 10:23:35 -04:00
|
|
|
debug!("rollback_to(cause={})", cause);
|
2018-08-29 13:25:47 -04:00
|
|
|
let CombinedSnapshot {
|
|
|
|
projection_cache_snapshot,
|
|
|
|
type_snapshot,
|
|
|
|
int_snapshot,
|
|
|
|
float_snapshot,
|
|
|
|
region_constraints_snapshot,
|
|
|
|
region_obligations_snapshot,
|
|
|
|
universe,
|
|
|
|
was_in_snapshot,
|
|
|
|
_in_progress_tables,
|
|
|
|
} = snapshot;
|
2016-05-25 21:12:35 +03:00
|
|
|
|
2017-04-15 23:51:58 +03:00
|
|
|
self.in_snapshot.set(was_in_snapshot);
|
2018-02-08 14:12:32 -07:00
|
|
|
self.universe.set(universe);
|
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);
|
2018-08-29 13:25:47 -04:00
|
|
|
self.type_variables.borrow_mut().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);
|
2017-11-14 15:12:36 -05:00
|
|
|
self.region_obligations
|
|
|
|
.borrow_mut()
|
|
|
|
.truncate(region_obligations_snapshot);
|
2017-11-05 07:22:39 -05:00
|
|
|
self.borrow_region_constraints()
|
2017-11-05 06:55:40 -05:00
|
|
|
.rollback_to(region_constraints_snapshot);
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2017-07-16 08:32:21 -04:00
|
|
|
fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
|
2016-05-21 05:41:40 -04:00
|
|
|
debug!("commit_from()");
|
2018-08-29 13:25:47 -04:00
|
|
|
let CombinedSnapshot {
|
|
|
|
projection_cache_snapshot,
|
|
|
|
type_snapshot,
|
|
|
|
int_snapshot,
|
|
|
|
float_snapshot,
|
|
|
|
region_constraints_snapshot,
|
|
|
|
region_obligations_snapshot: _,
|
|
|
|
universe: _,
|
|
|
|
was_in_snapshot,
|
|
|
|
_in_progress_tables,
|
|
|
|
} = snapshot;
|
2016-05-25 21:12:35 +03:00
|
|
|
|
2017-04-15 23:51:58 +03:00
|
|
|
self.in_snapshot.set(was_in_snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
|
2016-05-21 08:18:52 -04:00
|
|
|
self.projection_cache
|
|
|
|
.borrow_mut()
|
2018-08-09 16:57:55 +02:00
|
|
|
.commit(&projection_cache_snapshot);
|
2018-08-29 13:25:47 -04:00
|
|
|
self.type_variables.borrow_mut().commit(type_snapshot);
|
|
|
|
self.int_unification_table.borrow_mut().commit(int_snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
self.float_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.commit(float_snapshot);
|
2017-11-05 07:22:39 -05:00
|
|
|
self.borrow_region_constraints()
|
2017-11-05 06:55:40 -05:00
|
|
|
.commit(region_constraints_snapshot);
|
2014-06-20 06:35:06 -04:00
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2014-06-20 06:35:06 -04:00
|
|
|
/// Execute `f` and commit the bindings
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn commit_unconditionally<R, F>(&self, f: F) -> R
|
|
|
|
where
|
2014-12-08 20:26:43 -05:00
|
|
|
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(_)`
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
|
|
|
|
where
|
|
|
|
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> 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 {
|
2018-08-29 13:25:47 -04:00
|
|
|
Ok(_) => {
|
|
|
|
self.commit_from(snapshot);
|
|
|
|
}
|
|
|
|
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
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn in_snapshot<T, F>(&self, f: F) -> T
|
|
|
|
where
|
|
|
|
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T,
|
2016-05-01 17:19:11 +03:00
|
|
|
{
|
|
|
|
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
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn probe<R, F>(&self, f: F) -> R
|
|
|
|
where
|
2017-07-16 08:32:21 -04:00
|
|
|
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> 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
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
|
2017-11-05 07:22:39 -05:00
|
|
|
self.borrow_region_constraints().add_given(sub, sup);
|
2014-08-27 21:46:52 -04:00
|
|
|
}
|
2014-09-12 10:53:35 -04:00
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
|
|
|
|
where
|
|
|
|
T: at::ToTrace<'tcx>,
|
2016-03-17 00:15:31 +02:00
|
|
|
{
|
2017-05-24 09:43:20 -04:00
|
|
|
let origin = &ObligationCause::dummy();
|
2016-03-17 00:15:31 +02:00
|
|
|
self.probe(|_| {
|
2018-08-29 13:25:47 -04:00
|
|
|
self.at(origin, param_env)
|
|
|
|
.sub(a, b)
|
|
|
|
.map(|InferOk { obligations: _, .. }| {
|
|
|
|
// Ignore obligations, since we are unrolling
|
|
|
|
// everything anyway.
|
|
|
|
})
|
2016-03-17 00:15:31 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
|
|
|
|
where
|
|
|
|
T: at::ToTrace<'tcx>,
|
2014-09-12 10:53:35 -04:00
|
|
|
{
|
2017-05-24 09:43:20 -04:00
|
|
|
let origin = &ObligationCause::dummy();
|
|
|
|
self.probe(|_| {
|
2018-08-29 13:25:47 -04:00
|
|
|
self.at(origin, param_env)
|
|
|
|
.eq(a, b)
|
|
|
|
.map(|InferOk { obligations: _, .. }| {
|
|
|
|
// Ignore obligations, since we are unrolling
|
|
|
|
// everything anyway.
|
|
|
|
})
|
2014-10-09 17:19:50 -04:00
|
|
|
})
|
2014-09-12 10:53:35 -04:00
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn sub_regions(
|
|
|
|
&self,
|
|
|
|
origin: SubregionOrigin<'tcx>,
|
|
|
|
a: ty::Region<'tcx>,
|
|
|
|
b: ty::Region<'tcx>,
|
|
|
|
) {
|
2016-03-17 00:15:31 +02:00
|
|
|
debug!("sub_regions({:?} <: {:?})", a, b);
|
2018-08-29 13:25:47 -04:00
|
|
|
self.borrow_region_constraints()
|
|
|
|
.make_subregion(origin, a, b);
|
2014-12-14 07:17:23 -05:00
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn subtype_predicate(
|
|
|
|
&self,
|
|
|
|
cause: &ObligationCause<'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
predicate: &ty::PolySubtypePredicate<'tcx>,
|
|
|
|
) -> Option<InferResult<'tcx, ()>> {
|
2017-03-09 21:47:09 -05:00
|
|
|
// Subtle: it's ok to skip the binder here and resolve because
|
|
|
|
// `shallow_resolve` just ignores anything that is not a type
|
|
|
|
// variable, and because type variable's can't (at present, at
|
|
|
|
// least) capture any of the things bound by this binder.
|
|
|
|
//
|
|
|
|
// Really, there is no *particular* reason to do this
|
|
|
|
// `shallow_resolve` here except as a
|
|
|
|
// micro-optimization. Naturally I could not
|
|
|
|
// resist. -nmatsakis
|
|
|
|
let two_unbound_type_vars = {
|
|
|
|
let a = self.shallow_resolve(predicate.skip_binder().a);
|
|
|
|
let b = self.shallow_resolve(predicate.skip_binder().b);
|
|
|
|
a.is_ty_var() && b.is_ty_var()
|
|
|
|
};
|
|
|
|
|
|
|
|
if two_unbound_type_vars {
|
|
|
|
// Two unbound type variables? Can't make progress.
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(self.commit_if_ok(|snapshot| {
|
2018-08-29 13:25:47 -04:00
|
|
|
let (
|
|
|
|
ty::SubtypePredicate {
|
|
|
|
a_is_expected,
|
|
|
|
a,
|
|
|
|
b,
|
|
|
|
},
|
|
|
|
skol_map,
|
|
|
|
) = self.skolemize_late_bound_regions(predicate);
|
2017-03-09 21:47:09 -05:00
|
|
|
|
|
|
|
let cause_span = cause.span;
|
2017-05-24 09:43:20 -04:00
|
|
|
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
|
2017-03-09 21:47:09 -05:00
|
|
|
self.leak_check(false, cause_span, &skol_map, snapshot)?;
|
|
|
|
self.pop_skolemized(skol_map, snapshot);
|
|
|
|
Ok(ok.unit())
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn region_outlives_predicate(
|
|
|
|
&self,
|
|
|
|
cause: &traits::ObligationCause<'tcx>,
|
|
|
|
predicate: &ty::PolyRegionOutlivesPredicate<'tcx>,
|
|
|
|
) -> 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) =
|
2018-02-08 14:12:32 -07:00
|
|
|
self.skolemize_late_bound_regions(predicate);
|
2018-08-29 13:25:47 -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
|
|
|
}
|
|
|
|
|
2018-03-06 09:07:27 -07: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()
|
2018-02-08 13:14:24 -07:00
|
|
|
.new_var(self.universe(), diverging, origin)
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2018-03-06 09:07:27 -07: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
|
|
|
}
|
|
|
|
|
2018-03-06 09:07:27 -07: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 {
|
2018-08-29 13:25:47 -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 {
|
2018-08-29 13:25:47 -04:00
|
|
|
self.float_unification_table.borrow_mut().new_key(None)
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2017-11-06 05:21:48 -05:00
|
|
|
/// Create a fresh region variable with the next available index.
|
2018-08-29 14:33:38 -04:00
|
|
|
/// The variable will be created in the maximum universe created
|
|
|
|
/// thus far, allowing it to name any region created thus far.
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> {
|
2018-08-29 14:33:38 -04:00
|
|
|
self.next_region_var_in_universe(origin, self.universe())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a fresh region variable with the next available index
|
|
|
|
/// in the given universe; typically, you can use
|
|
|
|
/// `next_region_var` and just use the maximal universe.
|
|
|
|
pub fn next_region_var_in_universe(
|
|
|
|
&self,
|
|
|
|
origin: RegionVariableOrigin,
|
|
|
|
universe: ty::UniverseIndex,
|
|
|
|
) -> ty::Region<'tcx> {
|
2018-02-07 12:22:47 -07:00
|
|
|
let region_var = self.borrow_region_constraints()
|
2018-08-29 14:33:38 -04:00
|
|
|
.new_region_var(universe, origin);
|
2018-02-07 12:22:47 -07:00
|
|
|
self.tcx.mk_region(ty::ReVar(region_var))
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2017-11-22 17:38:51 -05:00
|
|
|
/// Number of region variables created so far.
|
|
|
|
pub fn num_region_vars(&self) -> usize {
|
2018-02-07 11:47:57 -07:00
|
|
|
self.borrow_region_constraints().num_region_vars()
|
2017-11-22 17:38:51 -05:00
|
|
|
}
|
|
|
|
|
2017-11-06 05:21:48 -05:00
|
|
|
/// Just a convenient wrapper of `next_region_var` for using during NLL.
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn next_nll_region_var(&self, origin: NLLRegionVariableOrigin) -> ty::Region<'tcx> {
|
2017-11-06 05:21:48 -05:00
|
|
|
self.next_region_var(RegionVariableOrigin::NLL(origin))
|
|
|
|
}
|
|
|
|
|
2018-08-29 14:33:38 -04:00
|
|
|
/// Just a convenient wrapper of `next_region_var` for using during NLL.
|
|
|
|
pub fn next_nll_region_var_in_universe(
|
|
|
|
&self,
|
|
|
|
origin: NLLRegionVariableOrigin,
|
|
|
|
universe: ty::UniverseIndex,
|
|
|
|
) -> ty::Region<'tcx> {
|
|
|
|
self.next_region_var_in_universe(RegionVariableOrigin::NLL(origin), universe)
|
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> Kind<'tcx> {
|
2018-05-14 19:57:59 +01:00
|
|
|
match param.kind {
|
|
|
|
GenericParamDefKind::Lifetime => {
|
|
|
|
// Create a region inference variable for the given
|
|
|
|
// region parameter definition.
|
2018-08-29 13:25:47 -04:00
|
|
|
self.next_region_var(EarlyBoundRegion(span, param.name))
|
|
|
|
.into()
|
2018-05-14 19:57:59 +01:00
|
|
|
}
|
2018-08-29 13:25:47 -04:00
|
|
|
GenericParamDefKind::Type { .. } => {
|
2018-05-14 19:57:59 +01: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)`.
|
2018-08-29 13:25:47 -04:00
|
|
|
let ty_var_id = self.type_variables.borrow_mut().new_var(
|
|
|
|
self.universe(),
|
|
|
|
false,
|
|
|
|
TypeVariableOrigin::TypeParameterDefinition(span, param.name),
|
|
|
|
);
|
2018-05-14 19:57:59 +01:00
|
|
|
|
2018-05-15 13:15:49 +01:00
|
|
|
self.tcx.mk_var(ty_var_id).into()
|
2018-05-14 19:57:59 +01:00
|
|
|
}
|
|
|
|
}
|
2016-08-17 03:56:18 +03:00
|
|
|
}
|
|
|
|
|
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.
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn fresh_substs_for_item(&self, span: Span, def_id: DefId) -> &'tcx Substs<'tcx> {
|
|
|
|
Substs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
|
2014-05-31 18:53:13 -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 {
|
2018-08-29 13:25:47 -04:00
|
|
|
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()
|
|
|
|
);
|
2016-03-15 04:49:10 -04:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-11-05 07:22:39 -05:00
|
|
|
/// Process the region constraints and report any errors that
|
|
|
|
/// result. After this, no more unification operations should be
|
|
|
|
/// done -- or the compiler will panic -- but it is legal to use
|
|
|
|
/// `resolve_type_vars_if_possible` as well as `fully_resolve`.
|
2017-12-20 04:54:35 -05:00
|
|
|
pub fn resolve_regions_and_report_errors(
|
|
|
|
&self,
|
|
|
|
region_context: DefId,
|
|
|
|
region_map: ®ion::ScopeTree,
|
|
|
|
outlives_env: &OutlivesEnvironment<'tcx>,
|
2018-09-12 15:43:26 -04:00
|
|
|
unless_nll: UnlessNll,
|
2017-12-20 04:54:35 -05:00
|
|
|
) {
|
2018-08-29 13:25:47 -04:00
|
|
|
assert!(
|
|
|
|
self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(),
|
|
|
|
"region_obligations not empty: {:#?}",
|
|
|
|
self.region_obligations.borrow()
|
|
|
|
);
|
|
|
|
|
|
|
|
let region_rels = &RegionRelations::new(
|
|
|
|
self.tcx,
|
|
|
|
region_context,
|
|
|
|
region_map,
|
|
|
|
outlives_env.free_region_map(),
|
|
|
|
);
|
|
|
|
let (var_infos, data) = self.region_constraints
|
|
|
|
.borrow_mut()
|
|
|
|
.take()
|
|
|
|
.expect("regions already resolved")
|
|
|
|
.into_infos_and_data();
|
2017-11-05 14:37:55 -05:00
|
|
|
let (lexical_region_resolutions, errors) =
|
2018-02-07 11:47:57 -07:00
|
|
|
lexical_region_resolve::resolve(region_rels, var_infos, data);
|
2017-11-05 05:48:16 -05:00
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
let old_value = self.lexical_region_resolutions
|
|
|
|
.replace(Some(lexical_region_resolutions));
|
2017-11-05 05:48:16 -05:00
|
|
|
assert!(old_value.is_none());
|
2017-06-12 11:45:19 -07:00
|
|
|
|
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.
|
2018-09-12 15:43:26 -04:00
|
|
|
self.report_region_errors(region_map, &errors, unless_nll);
|
2016-03-09 16:53:19 -05:00
|
|
|
}
|
2012-11-29 16:41:39 -08:00
|
|
|
}
|
|
|
|
|
2017-11-05 14:42:56 -05:00
|
|
|
/// Obtains (and clears) the current set of region
|
|
|
|
/// constraints. The inference context is still usable: further
|
|
|
|
/// unifications will simply add new constraints.
|
|
|
|
///
|
|
|
|
/// This method is not meant to be used with normal lexical region
|
|
|
|
/// resolution. Rather, it is used in the NLL mode as a kind of
|
|
|
|
/// interim hack: basically we run normal type-check and generate
|
|
|
|
/// region constraints as normal, but then we take them and
|
|
|
|
/// translate them into the form that the NLL solver
|
|
|
|
/// understands. See the NLL module for mode details.
|
|
|
|
pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
|
2018-08-29 13:25:47 -04:00
|
|
|
assert!(
|
|
|
|
self.region_obligations.borrow().is_empty(),
|
|
|
|
"region_obligations not empty: {:#?}",
|
|
|
|
self.region_obligations.borrow()
|
|
|
|
);
|
2017-11-28 00:39:38 -03:00
|
|
|
|
2017-11-05 14:42:56 -05:00
|
|
|
self.borrow_region_constraints().take_and_reset_data()
|
|
|
|
}
|
|
|
|
|
2018-02-25 10:58:54 -05:00
|
|
|
/// Gives temporary access to the region constraint data.
|
|
|
|
#[allow(non_camel_case_types)] // bug with impl trait
|
|
|
|
pub fn with_region_constraints<R>(
|
|
|
|
&self,
|
|
|
|
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
|
|
|
|
) -> R {
|
|
|
|
let region_constraints = self.borrow_region_constraints();
|
|
|
|
op(region_constraints.data())
|
|
|
|
}
|
|
|
|
|
2017-11-06 05:21:48 -05:00
|
|
|
/// Takes ownership of the list of variable regions. This implies
|
|
|
|
/// that all the region constriants have already been taken, and
|
|
|
|
/// hence that `resolve_regions_and_report_errors` can never be
|
|
|
|
/// called. This is used only during NLL processing to "hand off" ownership
|
|
|
|
/// of the set of region vairables into the NLL region context.
|
2018-02-07 11:47:57 -07:00
|
|
|
pub fn take_region_var_origins(&self) -> VarInfos {
|
2018-08-29 13:25:47 -04:00
|
|
|
let (var_infos, data) = self.region_constraints
|
|
|
|
.borrow_mut()
|
|
|
|
.take()
|
|
|
|
.expect("regions already resolved")
|
|
|
|
.into_infos_and_data();
|
2017-11-06 05:21:48 -05:00
|
|
|
assert!(data.is_empty());
|
2018-02-07 11:47:57 -07:00
|
|
|
var_infos
|
2017-11-06 04:29:50 -05: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
|
|
|
}
|
|
|
|
|
2018-08-17 16:05:24 +10:00
|
|
|
// We have this force-inlined variant of shallow_resolve() for the one
|
|
|
|
// callsite that is extremely hot. All other callsites use the normal
|
|
|
|
// variant.
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn inlined_shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
|
2014-10-31 10:51:16 +02:00
|
|
|
match typ.sty {
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Infer(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
|
2018-02-09 11:24:18 -05:00
|
|
|
// variables from unifyxing to other type variables
|
2014-12-01 12:27:27 -05:00
|
|
|
// directly (though they may be embedded
|
|
|
|
// structurally), and we prevent cycles in any case,
|
|
|
|
// so this recursion should always be of very limited
|
|
|
|
// depth.
|
2018-08-29 13:25:47 -04:00
|
|
|
self.type_variables
|
2015-02-15 15:16:45 -05:00
|
|
|
.borrow_mut()
|
2018-08-29 13:25:47 -04:00
|
|
|
.probe(v)
|
|
|
|
.known()
|
|
|
|
.map(|t| self.shallow_resolve(t))
|
2014-10-09 17:19:50 -04:00
|
|
|
.unwrap_or(typ)
|
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
ty::Infer(ty::IntVar(v)) => self.int_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.probe_value(v)
|
|
|
|
.map(|v| v.to_type(self.tcx))
|
|
|
|
.unwrap_or(typ),
|
2014-10-09 17:19:50 -04:00
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
ty::Infer(ty::FloatVar(v)) => self.float_unification_table
|
|
|
|
.borrow_mut()
|
|
|
|
.probe_value(v)
|
|
|
|
.map(|v| v.to_type(self.tcx))
|
|
|
|
.unwrap_or(typ),
|
|
|
|
|
|
|
|
_ => typ,
|
2014-10-09 17:19:50 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-17 16:05:24 +10:00
|
|
|
pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
|
|
|
|
self.inlined_shallow_resolve(typ)
|
|
|
|
}
|
|
|
|
|
2015-08-17 23:50:24 +03:00
|
|
|
pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
|
2018-08-29 13:25:47 -04: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
|
|
|
}
|
|
|
|
|
2017-09-02 08:35:07 -04:00
|
|
|
/// Returns true if `T` contains unresolved type variables. In the
|
|
|
|
/// process of visiting `T`, this will resolve (where possible)
|
|
|
|
/// type variables in `T`, but it never constructs the final,
|
|
|
|
/// resolved type, so it's more efficient than
|
|
|
|
/// `resolve_type_vars_if_possible()`.
|
|
|
|
pub fn any_unresolved_type_vars<T>(&self, value: &T) -> bool
|
2018-08-29 13:25:47 -04:00
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
2017-09-02 08:35:07 -04:00
|
|
|
{
|
|
|
|
let mut r = resolve::UnresolvedTypeFinder::new(self);
|
|
|
|
value.visit_with(&mut r)
|
|
|
|
}
|
|
|
|
|
2015-12-06 20:21:23 +02:00
|
|
|
pub fn resolve_type_and_region_vars_if_possible<T>(&self, value: &T) -> T
|
2018-08-29 13:25:47 -04:00
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
2015-12-06 20:21:23 +02:00
|
|
|
{
|
|
|
|
let mut r = resolve::OpportunisticTypeAndRegionResolver::new(self);
|
|
|
|
value.fold_with(&mut r)
|
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04: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]
|
2018-08-22 01:35:02 +01:00
|
|
|
// An invariant is that anytime the expected or actual type is Error (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.
|
2018-08-22 01:35:02 +01:00
|
|
|
// They check if either the actual or expected type is Error, 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
|
|
|
|
2018-08-29 13:25:47 -04: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>,
|
2016-07-21 16:07:08 +02:00
|
|
|
{
|
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
|
|
|
|
2018-08-22 01:35:02 +01:00
|
|
|
// Don't report an error if actual type is Error.
|
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
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn report_mismatched_types(
|
|
|
|
&self,
|
|
|
|
cause: &ObligationCause<'tcx>,
|
|
|
|
expected: Ty<'tcx>,
|
|
|
|
actual: Ty<'tcx>,
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-11-12 14:11:22 -05:00
|
|
|
pub fn replace_late_bound_regions_with_fresh_var<T>(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
lbrct: LateBoundRegionConversionTime,
|
2018-08-29 13:25:47 -04:00
|
|
|
value: &ty::Binder<T>,
|
|
|
|
) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
|
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
2014-11-05 22:06:04 -05:00
|
|
|
{
|
2018-08-29 13:25:47 -04:00
|
|
|
self.tcx.replace_late_bound_regions(value, |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.
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn match_poly_projection_predicate(
|
|
|
|
&self,
|
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
match_a: ty::PolyProjectionPredicate<'tcx>,
|
|
|
|
match_b: ty::TraitRef<'tcx>,
|
|
|
|
) -> InferResult<'tcx, HrMatchResult<Ty<'tcx>>> {
|
2017-07-11 10:33:09 -04:00
|
|
|
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty));
|
2016-05-21 08:16:07 -04:00
|
|
|
let trace = TypeTrace {
|
2017-07-03 11:19:51 -07:00
|
|
|
cause,
|
2018-08-29 13:25:47 -04:00
|
|
|
values: TraitRefs(ExpectedFound::new(
|
|
|
|
true,
|
|
|
|
match_pair.skip_binder().0,
|
|
|
|
match_b,
|
|
|
|
)),
|
2016-05-21 08:16:07 -04:00
|
|
|
};
|
|
|
|
|
2017-05-23 04:19:47 -04:00
|
|
|
let mut combine = self.combine_fields(trace, param_env);
|
2017-07-29 17:19:57 +03:00
|
|
|
let result = combine.higher_ranked_match(&match_pair, &match_b, true)?;
|
2018-08-29 13:25:47 -04:00
|
|
|
Ok(InferOk {
|
|
|
|
value: result,
|
|
|
|
obligations: combine.obligations,
|
|
|
|
})
|
2016-05-21 08:16:07 -04:00
|
|
|
}
|
|
|
|
|
2017-11-05 06:34:22 -05:00
|
|
|
/// See `verify_generic_bound` method in `region_constraints`
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn verify_generic_bound(
|
|
|
|
&self,
|
|
|
|
origin: SubregionOrigin<'tcx>,
|
|
|
|
kind: GenericKind<'tcx>,
|
|
|
|
a: ty::Region<'tcx>,
|
|
|
|
bound: VerifyBound<'tcx>,
|
|
|
|
) {
|
|
|
|
debug!("verify_generic_bound({:?}, {:?} <: {:?})", kind, a, bound);
|
|
|
|
|
|
|
|
self.borrow_region_constraints()
|
|
|
|
.verify_generic_bound(origin, kind, a, bound);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn type_moves_by_default(
|
|
|
|
&self,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
span: Span,
|
|
|
|
) -> bool {
|
2015-06-30 02:18:03 -07:00
|
|
|
let ty = self.resolve_type_vars_if_possible(&ty);
|
2017-06-09 10:55:16 +03:00
|
|
|
// Even if the type may have no inference variables, during
|
|
|
|
// type-checking closure types are in local tables only.
|
|
|
|
if !self.in_progress_tables.is_some() || !ty.has_closure_types() {
|
|
|
|
if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
|
2017-05-23 04:19:47 -04:00
|
|
|
return ty.moves_by_default(self.tcx.global_tcx(), param_env, span);
|
2016-04-29 06:00:23 +03:00
|
|
|
}
|
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.
|
2017-05-23 04:19:47 -04:00
|
|
|
!traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span)
|
2015-06-30 02:18:03 -07:00
|
|
|
}
|
|
|
|
|
2017-11-08 09:45:48 -05:00
|
|
|
/// Obtains the latest type of the given closure; this may be a
|
|
|
|
/// closure in the current function, in which case its
|
|
|
|
/// `ClosureKind` may not yet be known.
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn closure_kind(
|
|
|
|
&self,
|
|
|
|
closure_def_id: DefId,
|
|
|
|
closure_substs: ty::ClosureSubsts<'tcx>,
|
|
|
|
) -> Option<ty::ClosureKind> {
|
2017-11-08 09:45:48 -05:00
|
|
|
let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
|
|
|
|
let closure_kind_ty = self.shallow_resolve(&closure_kind_ty);
|
|
|
|
closure_kind_ty.to_opt_closure_kind()
|
2015-06-30 02:18:03 -07:00
|
|
|
}
|
|
|
|
|
2017-12-01 08:51:01 -05:00
|
|
|
/// Obtain the signature of a closure. For closures, unlike
|
|
|
|
/// `tcx.fn_sig(def_id)`, this method will work during the
|
|
|
|
/// type-checking of the enclosing function and return the closure
|
|
|
|
/// signature in its partially inferred state.
|
|
|
|
pub fn closure_sig(
|
|
|
|
&self,
|
|
|
|
def_id: DefId,
|
2018-08-29 13:25:47 -04:00
|
|
|
substs: ty::ClosureSubsts<'tcx>,
|
2017-12-01 08:51:01 -05:00
|
|
|
) -> ty::PolyFnSig<'tcx> {
|
|
|
|
let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx);
|
|
|
|
let closure_sig_ty = self.shallow_resolve(&closure_sig_ty);
|
|
|
|
closure_sig_ty.fn_sig(self.tcx)
|
2015-06-30 02:18:03 -07:00
|
|
|
}
|
2016-12-26 14:34:03 +01:00
|
|
|
|
2017-11-02 06:06:09 -04:00
|
|
|
/// Normalizes associated types in `value`, potentially returning
|
|
|
|
/// new obligations that must further be processed.
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn partially_normalize_associated_types_in<T>(
|
|
|
|
&self,
|
|
|
|
span: Span,
|
|
|
|
body_id: ast::NodeId,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
value: &T,
|
|
|
|
) -> InferOk<'tcx, T>
|
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
2017-11-02 06:06:09 -04:00
|
|
|
{
|
|
|
|
debug!("partially_normalize_associated_types_in(value={:?})", value);
|
|
|
|
let mut selcx = traits::SelectionContext::new(self);
|
|
|
|
let cause = ObligationCause::misc(span, body_id);
|
|
|
|
let traits::Normalized { value, obligations } =
|
|
|
|
traits::normalize(&mut selcx, param_env, cause, value);
|
2018-08-29 13:25:47 -04:00
|
|
|
debug!(
|
|
|
|
"partially_normalize_associated_types_in: result={:?} predicates={:?}",
|
|
|
|
value, obligations
|
|
|
|
);
|
2017-11-02 06:06:09 -04:00
|
|
|
InferOk { value, obligations }
|
|
|
|
}
|
2017-11-05 07:22:39 -05:00
|
|
|
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
|
|
|
pub fn borrow_region_constraints(&self) -> RefMut<'_, RegionConstraintCollector<'tcx>> {
|
2018-08-29 13:25:47 -04:00
|
|
|
RefMut::map(self.region_constraints.borrow_mut(), |c| {
|
|
|
|
c.as_mut().expect("region constraints already solved")
|
|
|
|
})
|
2017-11-05 07:22:39 -05:00
|
|
|
}
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
|
|
|
|
|
|
|
/// Clears the selection, evaluation, and projection cachesThis is useful when
|
2018-02-10 14:53:08 -05:00
|
|
|
/// repeatedly attemping to select an Obligation while changing only
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
|
|
|
/// its ParamEnv, since FulfillmentContext doesn't use 'probe'
|
|
|
|
pub fn clear_caches(&self) {
|
|
|
|
self.selection_cache.clear();
|
|
|
|
self.evaluation_cache.clear();
|
|
|
|
self.projection_cache.borrow_mut().clear();
|
|
|
|
}
|
2018-02-08 13:14:24 -07:00
|
|
|
|
|
|
|
fn universe(&self) -> ty::UniverseIndex {
|
|
|
|
self.universe.get()
|
|
|
|
}
|
2018-07-23 17:30:59 +03:00
|
|
|
|
|
|
|
/// Create and return a new subunivese of the current universe;
|
|
|
|
/// update `self.universe` to that new subuniverse. At present,
|
|
|
|
/// used only in the NLL subtyping code, which uses the new
|
|
|
|
/// universe-based scheme instead of the more limited leak-check
|
|
|
|
/// scheme.
|
|
|
|
pub fn create_subuniverse(&self) -> ty::UniverseIndex {
|
|
|
|
let u = self.universe.get().subuniverse();
|
|
|
|
self.universe.set(u);
|
|
|
|
u
|
|
|
|
}
|
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
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn types(
|
|
|
|
cause: &ObligationCause<'tcx>,
|
|
|
|
a_is_expected: bool,
|
|
|
|
a: Ty<'tcx>,
|
|
|
|
b: Ty<'tcx>,
|
|
|
|
) -> TypeTrace<'tcx> {
|
2015-01-16 05:48:15 +02:00
|
|
|
TypeTrace {
|
2016-11-07 13:25:06 -05:00
|
|
|
cause: cause.clone(),
|
2018-08-29 13:25:47 -04: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,
|
2018-08-29 13:25:47 -04:00
|
|
|
}),
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-29 13:25:47 -04:00
|
|
|
pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>, default: F) -> Self
|
|
|
|
where
|
|
|
|
F: FnOnce() -> Self,
|
2016-10-05 10:17:14 -04:00
|
|
|
{
|
|
|
|
match cause.code {
|
2018-08-29 13:25:47 -04:00
|
|
|
traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => {
|
|
|
|
SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span)
|
|
|
|
}
|
|
|
|
|
|
|
|
traits::ObligationCauseCode::CompareImplMethodObligation {
|
|
|
|
item_name,
|
|
|
|
impl_item_def_id,
|
|
|
|
trait_item_def_id,
|
|
|
|
} => SubregionOrigin::CompareImplMethodObligation {
|
|
|
|
span: cause.span,
|
|
|
|
item_name,
|
|
|
|
impl_item_def_id,
|
|
|
|
trait_item_def_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,
|
2017-11-06 05:21:48 -05:00
|
|
|
UpvarRegion(_, a) => a,
|
|
|
|
NLL(..) => bug!("NLL variable used with `span`"),
|
2013-05-23 21:37:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-16 19:38:17 +03:00
|
|
|
|
2018-02-09 10:43:15 -05:00
|
|
|
EnumTypeFoldableImpl! {
|
|
|
|
impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
|
|
|
|
(ValuePairs::Types)(a),
|
|
|
|
(ValuePairs::Regions)(a),
|
|
|
|
(ValuePairs::TraitRefs)(a),
|
|
|
|
(ValuePairs::PolyTraitRefs)(a),
|
2016-07-16 19:38:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-01 13:41:07 -04:00
|
|
|
impl<'tcx> fmt::Debug for RegionObligation<'tcx> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2018-08-29 13:25:47 -04:00
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"RegionObligation(sub_region={:?}, sup_type={:?})",
|
|
|
|
self.sub_region, self.sup_type
|
|
|
|
)
|
2017-11-01 13:41:07 -04:00
|
|
|
}
|
|
|
|
}
|