Move TypeckResults
to seperate module
This commit is contained in:
parent
153419b78f
commit
651e41c14c
3 changed files with 708 additions and 684 deletions
|
@ -4,8 +4,7 @@
|
|||
|
||||
use crate::arena::Arena;
|
||||
use crate::dep_graph::{DepGraph, DepKindStruct};
|
||||
use crate::hir::place::Place as HirPlace;
|
||||
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
|
||||
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
|
||||
use crate::lint::struct_lint_level;
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use crate::middle::resolve_lifetime;
|
||||
|
@ -18,13 +17,13 @@ use crate::thir::Thir;
|
|||
use crate::traits;
|
||||
use crate::ty::query::{self, TyCtxtAt};
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
|
||||
ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
|
||||
GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
|
||||
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
|
||||
TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstS, DefIdTree, FloatTy, FloatVar,
|
||||
FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
|
||||
ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
|
||||
ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
|
||||
Visibility,
|
||||
};
|
||||
use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
|
||||
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
|
@ -35,25 +34,20 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
|
|||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_errors::{
|
||||
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LOCAL_CRATE};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_hir::hir_id::OwnerId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet,
|
||||
Node, TraitCandidate, TraitItemKind,
|
||||
Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
|
||||
};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::mir::FakeReadCause;
|
||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||
|
@ -75,7 +69,6 @@ use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlag
|
|||
use std::any::Any;
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_map::{self, Entry};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter;
|
||||
|
@ -83,8 +76,6 @@ use std::mem;
|
|||
use std::ops::{Bound, Deref};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::{ImplPolarity, RvalueScopes};
|
||||
|
||||
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
|
||||
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
|
||||
fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
|
||||
|
@ -284,666 +275,6 @@ pub struct CommonConsts<'tcx> {
|
|||
pub unit: Const<'tcx>,
|
||||
}
|
||||
|
||||
pub struct LocalTableInContext<'a, V> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a ItemLocalMap<V>,
|
||||
}
|
||||
|
||||
/// Validate that the given HirId (respectively its `local_id` part) can be
|
||||
/// safely used as a key in the maps of a TypeckResults. For that to be
|
||||
/// the case, the HirId must have the same `owner` as all the other IDs in
|
||||
/// this table (signified by `hir_owner`). Otherwise the HirId
|
||||
/// would be in a different frame of reference and using its `local_id`
|
||||
/// would result in lookup errors, or worse, in silently wrong data being
|
||||
/// stored/returned.
|
||||
#[inline]
|
||||
fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
if hir_id.owner != hir_owner {
|
||||
invalid_hir_id_for_typeck_results(hir_owner, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
ty::tls::with(|tcx| {
|
||||
bug!(
|
||||
"node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
|
||||
tcx.hir().node_to_string(hir_id),
|
||||
hir_id.owner,
|
||||
hir_owner
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
impl<'a, V> LocalTableInContext<'a, V> {
|
||||
pub fn contains_key(&self, id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.contains_key(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn get(&self, id: hir::HirId) -> Option<&V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.get(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
|
||||
self.data.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, key: hir::HirId) -> &V {
|
||||
self.get(key).expect("LocalTableInContext: key not found")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LocalTableInContextMut<'a, V> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a mut ItemLocalMap<V>,
|
||||
}
|
||||
|
||||
impl<'a, V> LocalTableInContextMut<'a, V> {
|
||||
pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.get_mut(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.entry(id.local_id)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.insert(id.local_id, val)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.remove(&id.local_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
|
||||
/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
|
||||
/// captured types that can be useful for diagnostics. In particular, it stores the span that
|
||||
/// caused a given type to be recorded, along with the scope that enclosed the value (which can
|
||||
/// be used to find the await that the value is live across).
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```ignore (pseudo-Rust)
|
||||
/// async move {
|
||||
/// let x: T = expr;
|
||||
/// foo.await
|
||||
/// ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
|
||||
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
|
||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct GeneratorInteriorTypeCause<'tcx> {
|
||||
/// Type of the captured binding.
|
||||
pub ty: Ty<'tcx>,
|
||||
/// Span of the binding that was captured.
|
||||
pub span: Span,
|
||||
/// Span of the scope of the captured binding.
|
||||
pub scope_span: Option<Span>,
|
||||
/// Span of `.await` or `yield` expression.
|
||||
pub yield_span: Span,
|
||||
/// Expr which the type evaluated from.
|
||||
pub expr: Option<hir::HirId>,
|
||||
}
|
||||
|
||||
// This type holds diagnostic information on generators and async functions across crate boundaries
|
||||
// and is used to provide better error messages
|
||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
|
||||
pub struct GeneratorDiagnosticData<'tcx> {
|
||||
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
pub hir_owner: DefId,
|
||||
pub nodes_types: ItemLocalMap<Ty<'tcx>>,
|
||||
pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
}
|
||||
|
||||
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
|
||||
pub struct TypeckResults<'tcx> {
|
||||
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
|
||||
pub hir_owner: OwnerId,
|
||||
|
||||
/// Resolved definitions for `<T>::X` associated paths and
|
||||
/// method calls, including those of overloaded operators.
|
||||
type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
|
||||
|
||||
/// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
|
||||
/// or patterns (`S { field }`). The index is often useful by itself, but to learn more
|
||||
/// about the field you also need definition of the variant to which the field
|
||||
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
|
||||
field_indices: ItemLocalMap<usize>,
|
||||
|
||||
/// Stores the types for various nodes in the AST. Note that this table
|
||||
/// is not guaranteed to be populated outside inference. See
|
||||
/// typeck::check::fn_ctxt for details.
|
||||
node_types: ItemLocalMap<Ty<'tcx>>,
|
||||
|
||||
/// Stores the type parameters which were substituted to obtain the type
|
||||
/// of this node. This only applies to nodes that refer to entities
|
||||
/// parameterized by type parameters, such as generic fns, types, or
|
||||
/// other items.
|
||||
node_substs: ItemLocalMap<SubstsRef<'tcx>>,
|
||||
|
||||
/// This will either store the canonicalized types provided by the user
|
||||
/// or the substitutions that the user explicitly gave (if any) attached
|
||||
/// to `id`. These will not include any inferred values. The canonical form
|
||||
/// is used to capture things like `_` or other unspecified values.
|
||||
///
|
||||
/// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
|
||||
/// canonical substitutions would include only `for<X> { Vec<X> }`.
|
||||
///
|
||||
/// See also `AscribeUserType` statement in MIR.
|
||||
user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
|
||||
|
||||
adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
|
||||
/// Stores the actual binding mode for all instances of hir::BindingAnnotation.
|
||||
pat_binding_modes: ItemLocalMap<BindingMode>,
|
||||
|
||||
/// Stores the types which were implicitly dereferenced in pattern binding modes
|
||||
/// for later usage in THIR lowering. For example,
|
||||
///
|
||||
/// ```
|
||||
/// match &&Some(5i32) {
|
||||
/// Some(n) => {},
|
||||
/// _ => {},
|
||||
/// }
|
||||
/// ```
|
||||
/// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
|
||||
///
|
||||
/// See:
|
||||
/// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
|
||||
pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// Records the reasons that we picked the kind of each closure;
|
||||
/// not all closures are present in the map.
|
||||
closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
|
||||
|
||||
/// For each fn, records the "liberated" types of its arguments
|
||||
/// and return type. Liberated means that all bound regions
|
||||
/// (including late-bound regions) are replaced with free
|
||||
/// equivalents. This table is not used in codegen (since regions
|
||||
/// are erased there) and hence is not serialized to metadata.
|
||||
///
|
||||
/// This table also contains the "revealed" values for any `impl Trait`
|
||||
/// that appear in the signature and whose values are being inferred
|
||||
/// by this function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fmt::Debug;
|
||||
/// fn foo(x: &u32) -> impl Debug { *x }
|
||||
/// ```
|
||||
///
|
||||
/// The function signature here would be:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(&'a u32) -> Foo
|
||||
/// ```
|
||||
///
|
||||
/// where `Foo` is an opaque type created for this function.
|
||||
///
|
||||
///
|
||||
/// The *liberated* form of this would be
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn(&'a u32) -> u32
|
||||
/// ```
|
||||
///
|
||||
/// Note that `'a` is not bound (it would be an `ReFree`) and
|
||||
/// that the `Foo` opaque type is replaced by its hidden type.
|
||||
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
|
||||
|
||||
/// For each FRU expression, record the normalized types of the fields
|
||||
/// of the struct - this is needed because it is non-trivial to
|
||||
/// normalize while preserving regions. This table is used only in
|
||||
/// MIR construction and hence is not serialized to metadata.
|
||||
fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// For every coercion cast we add the HIR node ID of the cast
|
||||
/// expression to this set.
|
||||
coercion_casts: ItemLocalSet,
|
||||
|
||||
/// Set of trait imports actually used in the method resolution.
|
||||
/// This is used for warning unused imports. During type
|
||||
/// checking, this `Lrc` should not be cloned: it must have a ref-count
|
||||
/// of 1 so that we can insert things into the set mutably.
|
||||
pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
|
||||
|
||||
/// If any errors occurred while type-checking this body,
|
||||
/// this field will be set to `Some(ErrorGuaranteed)`.
|
||||
pub tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
|
||||
/// All the opaque types that have hidden types set
|
||||
/// by this function. We also store the
|
||||
/// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
|
||||
/// even if they are only set in dead code (which doesn't show up in MIR).
|
||||
pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
|
||||
|
||||
/// Tracks the minimum captures required for a closure;
|
||||
/// see `MinCaptureInformationMap` for more details.
|
||||
pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
|
||||
|
||||
/// Tracks the fake reads required for a closure and the reason for the fake read.
|
||||
/// When performing pattern matching for closures, there are times we don't end up
|
||||
/// reading places that are mentioned in a closure (because of _ patterns). However,
|
||||
/// to ensure the places are initialized, we introduce fake reads.
|
||||
/// Consider these two examples:
|
||||
/// ``` (discriminant matching with only wildcard arm)
|
||||
/// let x: u8;
|
||||
/// let c = || match x { _ => () };
|
||||
/// ```
|
||||
/// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
|
||||
/// want to capture it. However, we do still want an error here, because `x` should have
|
||||
/// to be initialized at the point where c is created. Therefore, we add a "fake read"
|
||||
/// instead.
|
||||
/// ``` (destructured assignments)
|
||||
/// let c = || {
|
||||
/// let (t1, t2) = t;
|
||||
/// }
|
||||
/// ```
|
||||
/// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
|
||||
/// we never capture `t`. This becomes an issue when we build MIR as we require
|
||||
/// information on `t` in order to create place `t.0` and `t.1`. We can solve this
|
||||
/// issue by fake reading `t`.
|
||||
pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
|
||||
|
||||
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
|
||||
/// by applying extended parameter rules.
|
||||
/// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
|
||||
pub rvalue_scopes: RvalueScopes,
|
||||
|
||||
/// Stores the type, expression, span and optional scope span of all types
|
||||
/// that are live across the yield of this generator (if a generator).
|
||||
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
|
||||
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
|
||||
/// as `&[u8]`, depending on the pattern in which they are used.
|
||||
/// This hashset records all instances where we behave
|
||||
/// like this to allow `const_to_pat` to reliably handle this situation.
|
||||
pub treat_byte_string_as_slice: ItemLocalSet,
|
||||
|
||||
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
|
||||
/// on closure size.
|
||||
pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeckResults<'tcx> {
|
||||
pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
|
||||
TypeckResults {
|
||||
hir_owner,
|
||||
type_dependent_defs: Default::default(),
|
||||
field_indices: Default::default(),
|
||||
user_provided_types: Default::default(),
|
||||
user_provided_sigs: Default::default(),
|
||||
node_types: Default::default(),
|
||||
node_substs: Default::default(),
|
||||
adjustments: Default::default(),
|
||||
pat_binding_modes: Default::default(),
|
||||
pat_adjustments: Default::default(),
|
||||
closure_kind_origins: Default::default(),
|
||||
liberated_fn_sigs: Default::default(),
|
||||
fru_field_types: Default::default(),
|
||||
coercion_casts: Default::default(),
|
||||
used_trait_imports: Lrc::new(Default::default()),
|
||||
tainted_by_errors: None,
|
||||
concrete_opaque_types: Default::default(),
|
||||
closure_min_captures: Default::default(),
|
||||
closure_fake_reads: Default::default(),
|
||||
rvalue_scopes: Default::default(),
|
||||
generator_interior_types: ty::Binder::dummy(Default::default()),
|
||||
treat_byte_string_as_slice: Default::default(),
|
||||
closure_size_eval: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
|
||||
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.res,
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
.type_dependent_def(id)
|
||||
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_dependent_defs(
|
||||
&self,
|
||||
) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
|
||||
}
|
||||
|
||||
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
|
||||
}
|
||||
|
||||
pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
|
||||
self.type_dependent_def(id).map(|(_, def_id)| def_id)
|
||||
}
|
||||
|
||||
pub fn type_dependent_defs_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
|
||||
}
|
||||
|
||||
pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_index(&self, id: hir::HirId) -> usize {
|
||||
self.field_indices().get(id).cloned().expect("no index for a field")
|
||||
}
|
||||
|
||||
pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
|
||||
self.field_indices().get(id).cloned()
|
||||
}
|
||||
|
||||
pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
|
||||
}
|
||||
|
||||
pub fn user_provided_types_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
|
||||
}
|
||||
|
||||
pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
|
||||
}
|
||||
|
||||
pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
|
||||
}
|
||||
|
||||
pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
|
||||
let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
|
||||
vec.iter()
|
||||
.map(|item| {
|
||||
GeneratorInteriorTypeCause {
|
||||
ty: item.ty,
|
||||
span: item.span,
|
||||
scope_span: item.scope_span,
|
||||
yield_span: item.yield_span,
|
||||
expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
GeneratorDiagnosticData {
|
||||
generator_interior_types: generator_interior_type,
|
||||
hir_owner: self.hir_owner.to_def_id(),
|
||||
nodes_types: self.node_types.clone(),
|
||||
adjustments: self.adjustments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
|
||||
self.node_type_opt(id).unwrap_or_else(|| {
|
||||
bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_types.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
|
||||
}
|
||||
|
||||
pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
|
||||
}
|
||||
|
||||
pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_substs.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
/// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
|
||||
/// doesn't provide type parameter substitutions.
|
||||
///
|
||||
/// [`expr_ty`]: TypeckResults::expr_ty
|
||||
pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
|
||||
self.node_type(pat.hir_id)
|
||||
}
|
||||
|
||||
/// Returns the type of an expression as a monotype.
|
||||
///
|
||||
/// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
|
||||
/// some cases, we insert `Adjustment` annotations such as auto-deref or
|
||||
/// auto-ref. The type returned by this function does not consider such
|
||||
/// adjustments. See `expr_ty_adjusted()` instead.
|
||||
///
|
||||
/// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
|
||||
/// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
|
||||
/// instead of `fn(ty) -> T with T = isize`.
|
||||
pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
self.node_type(expr.hir_id)
|
||||
}
|
||||
|
||||
pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
|
||||
self.node_type_opt(expr.hir_id)
|
||||
}
|
||||
|
||||
pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
|
||||
}
|
||||
|
||||
pub fn adjustments_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
|
||||
}
|
||||
|
||||
pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
|
||||
self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
|
||||
}
|
||||
|
||||
/// Returns the type of `expr`, considering any `Adjustment`
|
||||
/// entry recorded for that expression.
|
||||
pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
|
||||
}
|
||||
|
||||
pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
|
||||
self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
|
||||
}
|
||||
|
||||
pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
|
||||
// Only paths and method calls/overloaded operators have
|
||||
// entries in type_dependent_defs, ignore the former here.
|
||||
if let hir::ExprKind::Path(_) = expr.kind {
|
||||
return false;
|
||||
}
|
||||
|
||||
matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
|
||||
}
|
||||
|
||||
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
|
||||
self.pat_binding_modes().get(id).copied().or_else(|| {
|
||||
s.delay_span_bug(sp, "missing binding mode");
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
|
||||
}
|
||||
|
||||
pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
|
||||
}
|
||||
|
||||
/// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
|
||||
/// by the closure.
|
||||
pub fn closure_min_captures_flattened(
|
||||
&self,
|
||||
closure_def_id: LocalDefId,
|
||||
) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
|
||||
self.closure_min_captures
|
||||
.get(&closure_def_id)
|
||||
.map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
|
||||
}
|
||||
|
||||
pub fn closure_kind_origins_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
|
||||
}
|
||||
|
||||
pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
|
||||
}
|
||||
|
||||
pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
|
||||
}
|
||||
|
||||
pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
|
||||
}
|
||||
|
||||
pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
|
||||
}
|
||||
|
||||
pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
|
||||
self.coercion_casts.contains(&hir_id.local_id)
|
||||
}
|
||||
|
||||
pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
|
||||
self.coercion_casts.insert(id);
|
||||
}
|
||||
|
||||
pub fn coercion_casts(&self) -> &ItemLocalSet {
|
||||
&self.coercion_casts
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
pub struct UserTypeAnnotationIndex {
|
||||
derive [HashStable]
|
||||
DEBUG_FORMAT = "UserType({})",
|
||||
const START_INDEX = 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Mapping of type annotation indices to canonical user type annotations.
|
||||
pub type CanonicalUserTypeAnnotations<'tcx> =
|
||||
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
|
||||
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct CanonicalUserTypeAnnotation<'tcx> {
|
||||
pub user_ty: Box<CanonicalUserType<'tcx>>,
|
||||
pub span: Span,
|
||||
pub inferred_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
/// Canonicalized user type annotation.
|
||||
pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
|
||||
|
||||
impl<'tcx> CanonicalUserType<'tcx> {
|
||||
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
|
||||
/// i.e., each thing is mapped to a canonical variable with the same index.
|
||||
pub fn is_identity(&self) -> bool {
|
||||
match self.value {
|
||||
UserType::Ty(_) => false,
|
||||
UserType::TypeOf(_, user_substs) => {
|
||||
if user_substs.user_self_ty.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
|
||||
match kind.unpack() {
|
||||
GenericArgKind::Type(ty) => match ty.kind() {
|
||||
ty::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == b.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
GenericArgKind::Lifetime(r) => match *r {
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == br.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
GenericArgKind::Const(ct) => match ct.kind() {
|
||||
ty::ConstKind::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == b
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A user-given type annotation attached to a constant. These arise
|
||||
/// from constants that are named via paths, like `Foo::<A>::new` and
|
||||
/// so forth.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub enum UserType<'tcx> {
|
||||
Ty(Ty<'tcx>),
|
||||
|
||||
/// The canonical type is the result of `type_of(def_id)` with the
|
||||
/// given substitutions applied.
|
||||
TypeOf(DefId, UserSubsts<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> CommonTypes<'tcx> {
|
||||
fn new(
|
||||
interners: &CtxtInterners<'tcx>,
|
||||
|
|
|
@ -83,10 +83,8 @@ pub use self::consts::{
|
|||
Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
|
||||
};
|
||||
pub use self::context::{
|
||||
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
||||
CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData,
|
||||
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults,
|
||||
UserType, UserTypeAnnotationIndex,
|
||||
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
|
||||
TyCtxtFeed,
|
||||
};
|
||||
pub use self::instance::{Instance, InstanceDef, ShortInstance};
|
||||
pub use self::list::List;
|
||||
|
@ -103,6 +101,11 @@ pub use self::sty::{
|
|||
Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
|
||||
};
|
||||
pub use self::trait_def::TraitDef;
|
||||
pub use self::typeck_results::{
|
||||
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
||||
GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
|
||||
UserTypeAnnotationIndex,
|
||||
};
|
||||
|
||||
pub mod _match;
|
||||
pub mod abstract_const;
|
||||
|
@ -143,6 +146,7 @@ mod parameterized;
|
|||
mod rvalue_scopes;
|
||||
mod structural_impls;
|
||||
mod sty;
|
||||
mod typeck_results;
|
||||
|
||||
// Data types
|
||||
|
||||
|
|
689
compiler/rustc_middle/src/ty/typeck_results.rs
Normal file
689
compiler/rustc_middle/src/ty/typeck_results.rs
Normal file
|
@ -0,0 +1,689 @@
|
|||
use crate::{
|
||||
hir::place::Place as HirPlace,
|
||||
infer::canonical::Canonical,
|
||||
ty::{
|
||||
self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
|
||||
GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
|
||||
},
|
||||
};
|
||||
use rustc_data_structures::{fx::FxHashMap, sync::Lrc, unord::UnordSet, vec_map::VecMap};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{
|
||||
def::{DefKind, Res},
|
||||
def_id::{DefId, LocalDefId, LocalDefIdMap},
|
||||
hir_id::OwnerId,
|
||||
HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
|
||||
};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::mir::FakeReadCause;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
use std::{
|
||||
collections::hash_map::{self, Entry},
|
||||
hash::Hash,
|
||||
iter,
|
||||
};
|
||||
|
||||
use super::RvalueScopes;
|
||||
|
||||
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
|
||||
pub struct TypeckResults<'tcx> {
|
||||
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
|
||||
pub hir_owner: OwnerId,
|
||||
|
||||
/// Resolved definitions for `<T>::X` associated paths and
|
||||
/// method calls, including those of overloaded operators.
|
||||
type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
|
||||
|
||||
/// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
|
||||
/// or patterns (`S { field }`). The index is often useful by itself, but to learn more
|
||||
/// about the field you also need definition of the variant to which the field
|
||||
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
|
||||
field_indices: ItemLocalMap<usize>,
|
||||
|
||||
/// Stores the types for various nodes in the AST. Note that this table
|
||||
/// is not guaranteed to be populated outside inference. See
|
||||
/// typeck::check::fn_ctxt for details.
|
||||
node_types: ItemLocalMap<Ty<'tcx>>,
|
||||
|
||||
/// Stores the type parameters which were substituted to obtain the type
|
||||
/// of this node. This only applies to nodes that refer to entities
|
||||
/// parameterized by type parameters, such as generic fns, types, or
|
||||
/// other items.
|
||||
node_substs: ItemLocalMap<SubstsRef<'tcx>>,
|
||||
|
||||
/// This will either store the canonicalized types provided by the user
|
||||
/// or the substitutions that the user explicitly gave (if any) attached
|
||||
/// to `id`. These will not include any inferred values. The canonical form
|
||||
/// is used to capture things like `_` or other unspecified values.
|
||||
///
|
||||
/// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
|
||||
/// canonical substitutions would include only `for<X> { Vec<X> }`.
|
||||
///
|
||||
/// See also `AscribeUserType` statement in MIR.
|
||||
user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
|
||||
|
||||
adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
|
||||
/// Stores the actual binding mode for all instances of hir::BindingAnnotation.
|
||||
pat_binding_modes: ItemLocalMap<BindingMode>,
|
||||
|
||||
/// Stores the types which were implicitly dereferenced in pattern binding modes
|
||||
/// for later usage in THIR lowering. For example,
|
||||
///
|
||||
/// ```
|
||||
/// match &&Some(5i32) {
|
||||
/// Some(n) => {},
|
||||
/// _ => {},
|
||||
/// }
|
||||
/// ```
|
||||
/// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
|
||||
///
|
||||
/// See:
|
||||
/// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
|
||||
pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// Records the reasons that we picked the kind of each closure;
|
||||
/// not all closures are present in the map.
|
||||
closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
|
||||
|
||||
/// For each fn, records the "liberated" types of its arguments
|
||||
/// and return type. Liberated means that all bound regions
|
||||
/// (including late-bound regions) are replaced with free
|
||||
/// equivalents. This table is not used in codegen (since regions
|
||||
/// are erased there) and hence is not serialized to metadata.
|
||||
///
|
||||
/// This table also contains the "revealed" values for any `impl Trait`
|
||||
/// that appear in the signature and whose values are being inferred
|
||||
/// by this function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fmt::Debug;
|
||||
/// fn foo(x: &u32) -> impl Debug { *x }
|
||||
/// ```
|
||||
///
|
||||
/// The function signature here would be:
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// for<'a> fn(&'a u32) -> Foo
|
||||
/// ```
|
||||
///
|
||||
/// where `Foo` is an opaque type created for this function.
|
||||
///
|
||||
///
|
||||
/// The *liberated* form of this would be
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// fn(&'a u32) -> u32
|
||||
/// ```
|
||||
///
|
||||
/// Note that `'a` is not bound (it would be an `ReFree`) and
|
||||
/// that the `Foo` opaque type is replaced by its hidden type.
|
||||
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
|
||||
|
||||
/// For each FRU expression, record the normalized types of the fields
|
||||
/// of the struct - this is needed because it is non-trivial to
|
||||
/// normalize while preserving regions. This table is used only in
|
||||
/// MIR construction and hence is not serialized to metadata.
|
||||
fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
|
||||
|
||||
/// For every coercion cast we add the HIR node ID of the cast
|
||||
/// expression to this set.
|
||||
coercion_casts: ItemLocalSet,
|
||||
|
||||
/// Set of trait imports actually used in the method resolution.
|
||||
/// This is used for warning unused imports. During type
|
||||
/// checking, this `Lrc` should not be cloned: it must have a ref-count
|
||||
/// of 1 so that we can insert things into the set mutably.
|
||||
pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
|
||||
|
||||
/// If any errors occurred while type-checking this body,
|
||||
/// this field will be set to `Some(ErrorGuaranteed)`.
|
||||
pub tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
|
||||
/// All the opaque types that have hidden types set
|
||||
/// by this function. We also store the
|
||||
/// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
|
||||
/// even if they are only set in dead code (which doesn't show up in MIR).
|
||||
pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
|
||||
|
||||
/// Tracks the minimum captures required for a closure;
|
||||
/// see `MinCaptureInformationMap` for more details.
|
||||
pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
|
||||
|
||||
/// Tracks the fake reads required for a closure and the reason for the fake read.
|
||||
/// When performing pattern matching for closures, there are times we don't end up
|
||||
/// reading places that are mentioned in a closure (because of _ patterns). However,
|
||||
/// to ensure the places are initialized, we introduce fake reads.
|
||||
/// Consider these two examples:
|
||||
/// ``` (discriminant matching with only wildcard arm)
|
||||
/// let x: u8;
|
||||
/// let c = || match x { _ => () };
|
||||
/// ```
|
||||
/// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
|
||||
/// want to capture it. However, we do still want an error here, because `x` should have
|
||||
/// to be initialized at the point where c is created. Therefore, we add a "fake read"
|
||||
/// instead.
|
||||
/// ``` (destructured assignments)
|
||||
/// let c = || {
|
||||
/// let (t1, t2) = t;
|
||||
/// }
|
||||
/// ```
|
||||
/// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
|
||||
/// we never capture `t`. This becomes an issue when we build MIR as we require
|
||||
/// information on `t` in order to create place `t.0` and `t.1`. We can solve this
|
||||
/// issue by fake reading `t`.
|
||||
pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
|
||||
|
||||
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
|
||||
/// by applying extended parameter rules.
|
||||
/// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
|
||||
pub rvalue_scopes: RvalueScopes,
|
||||
|
||||
/// Stores the type, expression, span and optional scope span of all types
|
||||
/// that are live across the yield of this generator (if a generator).
|
||||
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
|
||||
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
|
||||
/// as `&[u8]`, depending on the pattern in which they are used.
|
||||
/// This hashset records all instances where we behave
|
||||
/// like this to allow `const_to_pat` to reliably handle this situation.
|
||||
pub treat_byte_string_as_slice: ItemLocalSet,
|
||||
|
||||
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
|
||||
/// on closure size.
|
||||
pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
|
||||
}
|
||||
|
||||
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
|
||||
/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
|
||||
/// captured types that can be useful for diagnostics. In particular, it stores the span that
|
||||
/// caused a given type to be recorded, along with the scope that enclosed the value (which can
|
||||
/// be used to find the await that the value is live across).
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```ignore (pseudo-Rust)
|
||||
/// async move {
|
||||
/// let x: T = expr;
|
||||
/// foo.await
|
||||
/// ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
|
||||
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
|
||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct GeneratorInteriorTypeCause<'tcx> {
|
||||
/// Type of the captured binding.
|
||||
pub ty: Ty<'tcx>,
|
||||
/// Span of the binding that was captured.
|
||||
pub span: Span,
|
||||
/// Span of the scope of the captured binding.
|
||||
pub scope_span: Option<Span>,
|
||||
/// Span of `.await` or `yield` expression.
|
||||
pub yield_span: Span,
|
||||
/// Expr which the type evaluated from.
|
||||
pub expr: Option<hir::HirId>,
|
||||
}
|
||||
|
||||
// This type holds diagnostic information on generators and async functions across crate boundaries
|
||||
// and is used to provide better error messages
|
||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
|
||||
pub struct GeneratorDiagnosticData<'tcx> {
|
||||
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
pub hir_owner: DefId,
|
||||
pub nodes_types: ItemLocalMap<Ty<'tcx>>,
|
||||
pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeckResults<'tcx> {
|
||||
pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
|
||||
TypeckResults {
|
||||
hir_owner,
|
||||
type_dependent_defs: Default::default(),
|
||||
field_indices: Default::default(),
|
||||
user_provided_types: Default::default(),
|
||||
user_provided_sigs: Default::default(),
|
||||
node_types: Default::default(),
|
||||
node_substs: Default::default(),
|
||||
adjustments: Default::default(),
|
||||
pat_binding_modes: Default::default(),
|
||||
pat_adjustments: Default::default(),
|
||||
closure_kind_origins: Default::default(),
|
||||
liberated_fn_sigs: Default::default(),
|
||||
fru_field_types: Default::default(),
|
||||
coercion_casts: Default::default(),
|
||||
used_trait_imports: Lrc::new(Default::default()),
|
||||
tainted_by_errors: None,
|
||||
concrete_opaque_types: Default::default(),
|
||||
closure_min_captures: Default::default(),
|
||||
closure_fake_reads: Default::default(),
|
||||
rvalue_scopes: Default::default(),
|
||||
generator_interior_types: ty::Binder::dummy(Default::default()),
|
||||
treat_byte_string_as_slice: Default::default(),
|
||||
closure_size_eval: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
|
||||
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(_, ref path) => path.res,
|
||||
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
|
||||
.type_dependent_def(id)
|
||||
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_dependent_defs(
|
||||
&self,
|
||||
) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
|
||||
}
|
||||
|
||||
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
|
||||
}
|
||||
|
||||
pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
|
||||
self.type_dependent_def(id).map(|(_, def_id)| def_id)
|
||||
}
|
||||
|
||||
pub fn type_dependent_defs_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
|
||||
}
|
||||
|
||||
pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
|
||||
}
|
||||
|
||||
pub fn field_index(&self, id: hir::HirId) -> usize {
|
||||
self.field_indices().get(id).cloned().expect("no index for a field")
|
||||
}
|
||||
|
||||
pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
|
||||
self.field_indices().get(id).cloned()
|
||||
}
|
||||
|
||||
pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
|
||||
}
|
||||
|
||||
pub fn user_provided_types_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
|
||||
}
|
||||
|
||||
pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
|
||||
}
|
||||
|
||||
pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
|
||||
}
|
||||
|
||||
pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
|
||||
let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
|
||||
vec.iter()
|
||||
.map(|item| {
|
||||
GeneratorInteriorTypeCause {
|
||||
ty: item.ty,
|
||||
span: item.span,
|
||||
scope_span: item.scope_span,
|
||||
yield_span: item.yield_span,
|
||||
expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
GeneratorDiagnosticData {
|
||||
generator_interior_types: generator_interior_type,
|
||||
hir_owner: self.hir_owner.to_def_id(),
|
||||
nodes_types: self.node_types.clone(),
|
||||
adjustments: self.adjustments.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
|
||||
self.node_type_opt(id).unwrap_or_else(|| {
|
||||
bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_types.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
|
||||
}
|
||||
|
||||
pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
|
||||
}
|
||||
|
||||
pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.node_substs.get(&id.local_id).cloned()
|
||||
}
|
||||
|
||||
/// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
|
||||
/// doesn't provide type parameter substitutions.
|
||||
///
|
||||
/// [`expr_ty`]: TypeckResults::expr_ty
|
||||
pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
|
||||
self.node_type(pat.hir_id)
|
||||
}
|
||||
|
||||
/// Returns the type of an expression as a monotype.
|
||||
///
|
||||
/// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
|
||||
/// some cases, we insert `Adjustment` annotations such as auto-deref or
|
||||
/// auto-ref. The type returned by this function does not consider such
|
||||
/// adjustments. See `expr_ty_adjusted()` instead.
|
||||
///
|
||||
/// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
|
||||
/// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
|
||||
/// instead of `fn(ty) -> T with T = isize`.
|
||||
pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
self.node_type(expr.hir_id)
|
||||
}
|
||||
|
||||
pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
|
||||
self.node_type_opt(expr.hir_id)
|
||||
}
|
||||
|
||||
pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
|
||||
}
|
||||
|
||||
pub fn adjustments_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
|
||||
}
|
||||
|
||||
pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
|
||||
self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
|
||||
}
|
||||
|
||||
/// Returns the type of `expr`, considering any `Adjustment`
|
||||
/// entry recorded for that expression.
|
||||
pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
|
||||
self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
|
||||
}
|
||||
|
||||
pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
|
||||
self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
|
||||
}
|
||||
|
||||
pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
|
||||
// Only paths and method calls/overloaded operators have
|
||||
// entries in type_dependent_defs, ignore the former here.
|
||||
if let hir::ExprKind::Path(_) = expr.kind {
|
||||
return false;
|
||||
}
|
||||
|
||||
matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
|
||||
}
|
||||
|
||||
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
|
||||
self.pat_binding_modes().get(id).copied().or_else(|| {
|
||||
s.delay_span_bug(sp, "missing binding mode");
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
|
||||
}
|
||||
|
||||
pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
|
||||
}
|
||||
|
||||
pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
|
||||
}
|
||||
|
||||
/// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
|
||||
/// by the closure.
|
||||
pub fn closure_min_captures_flattened(
|
||||
&self,
|
||||
closure_def_id: LocalDefId,
|
||||
) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
|
||||
self.closure_min_captures
|
||||
.get(&closure_def_id)
|
||||
.map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
|
||||
}
|
||||
|
||||
pub fn closure_kind_origins_mut(
|
||||
&mut self,
|
||||
) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
|
||||
}
|
||||
|
||||
pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
|
||||
}
|
||||
|
||||
pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
|
||||
}
|
||||
|
||||
pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
|
||||
}
|
||||
|
||||
pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
|
||||
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
|
||||
}
|
||||
|
||||
pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
|
||||
self.coercion_casts.contains(&hir_id.local_id)
|
||||
}
|
||||
|
||||
pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
|
||||
self.coercion_casts.insert(id);
|
||||
}
|
||||
|
||||
pub fn coercion_casts(&self) -> &ItemLocalSet {
|
||||
&self.coercion_casts
|
||||
}
|
||||
}
|
||||
|
||||
/// Validate that the given HirId (respectively its `local_id` part) can be
|
||||
/// safely used as a key in the maps of a TypeckResults. For that to be
|
||||
/// the case, the HirId must have the same `owner` as all the other IDs in
|
||||
/// this table (signified by `hir_owner`). Otherwise the HirId
|
||||
/// would be in a different frame of reference and using its `local_id`
|
||||
/// would result in lookup errors, or worse, in silently wrong data being
|
||||
/// stored/returned.
|
||||
#[inline]
|
||||
fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
if hir_id.owner != hir_owner {
|
||||
invalid_hir_id_for_typeck_results(hir_owner, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
|
||||
ty::tls::with(|tcx| {
|
||||
bug!(
|
||||
"node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
|
||||
tcx.hir().node_to_string(hir_id),
|
||||
hir_id.owner,
|
||||
hir_owner
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
pub struct LocalTableInContext<'a, V> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a ItemLocalMap<V>,
|
||||
}
|
||||
|
||||
impl<'a, V> LocalTableInContext<'a, V> {
|
||||
pub fn contains_key(&self, id: hir::HirId) -> bool {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.contains_key(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn get(&self, id: hir::HirId) -> Option<&V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.get(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
|
||||
self.data.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
|
||||
type Output = V;
|
||||
|
||||
fn index(&self, key: hir::HirId) -> &V {
|
||||
self.get(key).expect("LocalTableInContext: key not found")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LocalTableInContextMut<'a, V> {
|
||||
hir_owner: OwnerId,
|
||||
data: &'a mut ItemLocalMap<V>,
|
||||
}
|
||||
|
||||
impl<'a, V> LocalTableInContextMut<'a, V> {
|
||||
pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.get_mut(&id.local_id)
|
||||
}
|
||||
|
||||
pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.entry(id.local_id)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.insert(id.local_id, val)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
|
||||
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||
self.data.remove(&id.local_id)
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
pub struct UserTypeAnnotationIndex {
|
||||
derive [HashStable]
|
||||
DEBUG_FORMAT = "UserType({})",
|
||||
const START_INDEX = 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Mapping of type annotation indices to canonical user type annotations.
|
||||
pub type CanonicalUserTypeAnnotations<'tcx> =
|
||||
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
|
||||
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct CanonicalUserTypeAnnotation<'tcx> {
|
||||
pub user_ty: Box<CanonicalUserType<'tcx>>,
|
||||
pub span: Span,
|
||||
pub inferred_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
/// Canonicalized user type annotation.
|
||||
pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
|
||||
|
||||
impl<'tcx> CanonicalUserType<'tcx> {
|
||||
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
|
||||
/// i.e., each thing is mapped to a canonical variable with the same index.
|
||||
pub fn is_identity(&self) -> bool {
|
||||
match self.value {
|
||||
UserType::Ty(_) => false,
|
||||
UserType::TypeOf(_, user_substs) => {
|
||||
if user_substs.user_self_ty.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
|
||||
match kind.unpack() {
|
||||
GenericArgKind::Type(ty) => match ty.kind() {
|
||||
ty::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(*debruijn, ty::INNERMOST);
|
||||
cvar == b.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
GenericArgKind::Lifetime(r) => match *r {
|
||||
ty::ReLateBound(debruijn, br) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == br.var
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
|
||||
GenericArgKind::Const(ct) => match ct.kind() {
|
||||
ty::ConstKind::Bound(debruijn, b) => {
|
||||
// We only allow a `ty::INNERMOST` index in substitutions.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
cvar == b
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A user-given type annotation attached to a constant. These arise
|
||||
/// from constants that are named via paths, like `Foo::<A>::new` and
|
||||
/// so forth.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub enum UserType<'tcx> {
|
||||
Ty(Ty<'tcx>),
|
||||
|
||||
/// The canonical type is the result of `type_of(def_id)` with the
|
||||
/// given substitutions applied.
|
||||
TypeOf(DefId, UserSubsts<'tcx>),
|
||||
}
|
Loading…
Add table
Reference in a new issue