diff options
Diffstat (limited to 'compiler/rustc_middle/src')
33 files changed, 1115 insertions, 1028 deletions
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index efa9464529e..0b55757eb03 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -3,7 +3,6 @@ use rustc_macros::HashStable; use rustc_span::Symbol; -use std::cmp::Ord; use std::fmt::{self, Debug, Formatter}; rustc_index::newtype_index! { diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index d79cd8b7a8a..8fe349d9640 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -95,7 +95,6 @@ mod pointer; mod queries; mod value; -use std::convert::TryFrom; use std::fmt; use std::io; use std::io::{Read, Write}; diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 9c270ba1ec1..b0830991076 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -3,7 +3,6 @@ use super::{AllocId, InterpResult}; use rustc_macros::HashStable; use rustc_target::abi::{HasDataLayout, Size}; -use std::convert::{TryFrom, TryInto}; use std::fmt; //////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index e6636e50e6e..88fb14eb359 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -1,4 +1,3 @@ -use std::convert::{TryFrom, TryInto}; use std::fmt; use either::{Either, Left, Right}; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index a513444e1e0..bdaa586c698 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -36,7 +36,6 @@ use rustc_span::{Span, DUMMY_SP}; use either::Either; use std::borrow::Cow; -use std::convert::TryInto; use std::fmt::{self, Debug, Display, Formatter, Write}; use std::ops::{ControlFlow, Index, IndexMut}; use std::{iter, mem}; @@ -534,6 +533,11 @@ impl<'tcx> Body<'tcx> { }; injection_phase > self.phase } + + #[inline] + pub fn is_custom_mir(&self) -> bool { + self.injection_phase.is_some() + } } #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)] @@ -1848,7 +1852,7 @@ impl<'tcx> Operand<'tcx> { pub fn function_handle( tcx: TyCtxt<'tcx>, def_id: DefId, - substs: SubstsRef<'tcx>, + substs: impl IntoIterator<Item = GenericArg<'tcx>>, span: Span, ) -> Self { let ty = tcx.mk_fn_def(def_id, substs); diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 15a24aa4ace..1e8d5f7eae8 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -200,6 +200,15 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::GlobalAsm(..) => LOCAL_CRATE, } } + + /// Returns the item's `DefId` + pub fn def_id(&self) -> DefId { + match *self { + MonoItem::Fn(Instance { def, .. }) => def.def_id(), + MonoItem::Static(def_id) => def_id, + MonoItem::GlobalAsm(item_id) => item_id.owner_id.to_def_id(), + } + } } impl<'tcx> fmt::Display for MonoItem<'tcx> { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 143435cb2a1..d00b26a5a3d 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -250,7 +250,7 @@ pub enum ObligationCauseCode<'tcx> { TupleElem, /// This is the trait reference from the given projection. - ProjectionWf(ty::ProjectionTy<'tcx>), + ProjectionWf(ty::AliasTy<'tcx>), /// Must satisfy all of the where-clause predicates of the /// given item. diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index fb152b63f63..7380c62a669 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -12,7 +12,6 @@ use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_span::source_map::Span; -use std::iter::FromIterator; pub mod type_op { use crate::ty::fold::TypeFoldable; @@ -77,8 +76,7 @@ pub mod type_op { } } -pub type CanonicalProjectionGoal<'tcx> = - Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>; +pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>; pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>; @@ -219,6 +217,6 @@ pub struct NormalizationResult<'tcx> { pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), - RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>), + RegionSubProjection(ty::Region<'tcx>, ty::AliasTy<'tcx>), RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>), } diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 7036c4a7b27..8ce06404de0 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -131,7 +131,7 @@ impl<'tcx> OverloadedDeref<'tcx> { .find(|m| m.kind == ty::AssocKind::Fn) .unwrap() .def_id; - tcx.mk_fn_def(method_def_id, tcx.mk_substs_trait(source, [])) + tcx.mk_fn_def(method_def_id, [source]) } } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index f3186e1c30c..2a8a4d59888 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -2,7 +2,6 @@ use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_target::abi::Size; -use std::convert::{TryFrom, TryInto}; use std::fmt; use std::num::NonZeroU8; diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index becc2b805dd..d9721863a58 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,5 +1,3 @@ -use std::convert::TryInto; - use super::Const; use crate::mir; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 7d4971d1e9e..173c5ed4fee 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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,14 +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, ProjectionTy, Region, - RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, + 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}; @@ -36,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}; @@ -76,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; @@ -84,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 @@ -116,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>; type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>; type ListTy = &'tcx List<Ty<'tcx>>; - type ProjectionTy = ty::ProjectionTy<'tcx>; + type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; type PlaceholderType = ty::PlaceholderType; @@ -285,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>, @@ -2145,8 +1475,7 @@ impl<'tcx> TyCtxt<'tcx> { Bound, Param, Infer, - Projection, - Opaque, + Alias, Foreign )?; @@ -2323,7 +1652,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Given a `ty`, return whether it's an `impl Future<...>`. pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool { - let ty::Opaque(def_id, _) = ty.kind() else { return false }; + let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let future_trait = self.require_lang_item(LangItem::Future, None); self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| { @@ -2567,15 +1896,35 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - debug_assert_eq!( - self.generics_of(def_id).count(), - substs.len(), - "wrong number of generic parameters for {def_id:?}: {substs:?}", - ); + pub fn mk_fn_def( + self, + def_id: DefId, + substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>, + ) -> Ty<'tcx> { + let substs = self.check_substs(def_id, substs); self.mk_ty(FnDef(def_id, substs)) } + #[inline(always)] + fn check_substs( + self, + _def_id: DefId, + substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>, + ) -> SubstsRef<'tcx> { + let substs = substs.into_iter().map(Into::into); + #[cfg(debug_assertions)] + { + let n = self.generics_of(_def_id).count(); + assert_eq!( + (n, Some(n)), + substs.size_hint(), + "wrong number of generic parameters for {_def_id:?}: {:?}", + substs.collect::<Vec<_>>(), + ); + } + self.mk_substs(substs) + } + #[inline] pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { self.mk_ty(FnPtr(fty)) @@ -2592,13 +1941,12 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - debug_assert_eq!( - self.generics_of(item_def_id).count(), - substs.len(), - "wrong number of generic parameters for {item_def_id:?}: {substs:?}", - ); - self.mk_ty(Projection(ProjectionTy { item_def_id, substs })) + pub fn mk_projection( + self, + item_def_id: DefId, + substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>, + ) -> Ty<'tcx> { + self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs))) } #[inline] @@ -2668,7 +2016,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { - self.mk_ty(Opaque(def_id, substs)) + self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs))) } pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { @@ -2857,16 +2205,17 @@ impl<'tcx> TyCtxt<'tcx> { trait_def_id: DefId, substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>, ) -> ty::TraitRef<'tcx> { - let substs = substs.into_iter().map(Into::into); - let n = self.generics_of(trait_def_id).count(); - debug_assert_eq!( - (n, Some(n)), - substs.size_hint(), - "wrong number of generic parameters for {trait_def_id:?}: {:?} \nDid you accidentally include the self-type in the params list?", - substs.collect::<Vec<_>>(), - ); - let substs = self.mk_substs(substs); - ty::TraitRef::new(trait_def_id, substs) + let substs = self.check_substs(trait_def_id, substs); + ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () } + } + + pub fn mk_alias_ty( + self, + def_id: DefId, + substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>, + ) -> ty::AliasTy<'tcx> { + let substs = self.check_substs(def_id, substs); + ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () } } pub fn mk_bound_variable_kinds< diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 511d51cd670..8c22df7395f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -3,7 +3,7 @@ use std::ops::ControlFlow; use crate::ty::{ - visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy, + visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque, PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, }; @@ -457,11 +457,11 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> { return ControlFlow::Break(()); } - Opaque(did, _) => { - let parent = self.tcx.parent(*did); + Alias(Opaque, AliasTy { def_id, .. }) => { + let parent = self.tcx.parent(*def_id); if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) - && let Opaque(parent_did, _) = self.tcx.type_of(parent).kind() - && parent_did == did + && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = self.tcx.type_of(parent).kind() + && parent_opaque_def_id == def_id { // Okay } else { @@ -469,17 +469,6 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> { } } - Dynamic(dty, _, _) => { - for pred in *dty { - match pred.skip_binder() { - ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => { - // Okay - } - _ => return ControlFlow::Break(()), - } - } - } - Param(param) => { // FIXME: It would be nice to make this not use string manipulation, // but it's pretty hard to do this, since `ty::ParamTy` is missing diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index aa61c39b8d8..14d07608a78 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -1,6 +1,6 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::diagnostics::suggest_constraining_type_param; -use crate::ty::print::{FmtPrinter, Printer}; +use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer}; use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt}; use hir::def::DefKind; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; @@ -162,17 +162,29 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ), RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"), ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| { - report_maybe_different( - f, - &values.expected.sort_string(tcx), - &values.found.sort_string(tcx), - ) + let (mut expected, mut found) = with_forced_trimmed_paths!(( + values.expected.sort_string(tcx), + values.found.sort_string(tcx), + )); + if expected == found { + expected = values.expected.sort_string(tcx); + found = values.found.sort_string(tcx); + } + report_maybe_different(f, &expected, &found) }), Traits(values) => ty::tls::with(|tcx| { + let (mut expected, mut found) = with_forced_trimmed_paths!(( + tcx.def_path_str(values.expected), + tcx.def_path_str(values.found), + )); + if expected == found { + expected = tcx.def_path_str(values.expected); + found = tcx.def_path_str(values.found); + } report_maybe_different( f, - &format!("trait `{}`", tcx.def_path_str(values.expected)), - &format!("trait `{}`", tcx.def_path_str(values.found)), + &format!("trait `{expected}`"), + &format!("trait `{found}`"), ) }), IntMismatch(ref values) => { @@ -325,9 +337,9 @@ impl<'tcx> Ty<'tcx> { ty::Infer(ty::FreshTy(_)) => "fresh type".into(), ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(), ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), - ty::Projection(_) => "associated type".into(), + ty::Alias(ty::Projection, _) => "associated type".into(), ty::Param(p) => format!("type parameter `{}`", p).into(), - ty::Opaque(..) => "opaque type".into(), + ty::Alias(ty::Opaque, ..) => "opaque type".into(), ty::Error(_) => "type error".into(), } } @@ -363,9 +375,9 @@ impl<'tcx> Ty<'tcx> { ty::Tuple(..) => "tuple".into(), ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), - ty::Projection(_) => "associated type".into(), + ty::Alias(ty::Projection, _) => "associated type".into(), ty::Param(_) => "type parameter".into(), - ty::Opaque(..) => "opaque type".into(), + ty::Alias(ty::Opaque, ..) => "opaque type".into(), } } } @@ -388,7 +400,7 @@ impl<'tcx> TyCtxt<'tcx> { diag.note("no two closures, even if identical, have the same type"); diag.help("consider boxing your closure and/or using it as a trait object"); } - (ty::Opaque(..), ty::Opaque(..)) => { + (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => { // Issue #63167 diag.note("distinct uses of `impl Trait` result in different opaque types"); } @@ -427,11 +439,11 @@ impl<'tcx> TyCtxt<'tcx> { #traits-as-parameters", ); } - (ty::Projection(_), ty::Projection(_)) => { + (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => { diag.note("an associated type was expected, but a different one was found"); } - (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) - if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder => + (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p)) + if self.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder => { let generics = self.generics_of(body_owner_def_id); let p_span = self.def_span(generics.type_param(p, self).def_id); @@ -454,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> { let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self); let path = self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs); - let item_name = self.item_name(proj.item_def_id); + let item_name = self.item_name(proj.def_id); let item_args = self.format_generic_args(assoc_substs); let path = if path.ends_with('>') { @@ -481,8 +493,8 @@ impl<'tcx> TyCtxt<'tcx> { diag.note("you might be missing a type parameter or trait bound"); } } - (ty::Param(p), ty::Dynamic(..) | ty::Opaque(..)) - | (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => { + (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..)) + | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => { let generics = self.generics_of(body_owner_def_id); let p_span = self.def_span(generics.type_param(p, self).def_id); if !sp.contains(p_span) { @@ -541,7 +553,7 @@ impl<T> Trait<T> for X { diag.span_label(p_span, "this type parameter"); } } - (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { + (ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => { self.expected_projection( diag, proj_ty, @@ -550,7 +562,7 @@ impl<T> Trait<T> for X { cause.code(), ); } - (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => { + (_, ty::Alias(ty::Projection, proj_ty)) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => { let msg = format!( "consider constraining the associated type `{}` to `{}`", values.found, values.expected, @@ -612,10 +624,10 @@ impl<T> Trait<T> for X { diag: &mut Diagnostic, msg: &str, body_owner_def_id: DefId, - proj_ty: &ty::ProjectionTy<'tcx>, + proj_ty: &ty::AliasTy<'tcx>, ty: Ty<'tcx>, ) -> bool { - let assoc = self.associated_item(proj_ty.item_def_id); + let assoc = self.associated_item(proj_ty.def_id); let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self); if let Some(item) = self.hir().get_if_local(body_owner_def_id) { if let Some(hir_generics) = item.generics() { @@ -668,7 +680,7 @@ impl<T> Trait<T> for X { fn expected_projection( self, diag: &mut Diagnostic, - proj_ty: &ty::ProjectionTy<'tcx>, + proj_ty: &ty::AliasTy<'tcx>, values: ExpectedFound<Ty<'tcx>>, body_owner_def_id: DefId, cause_code: &ObligationCauseCode<'_>, @@ -691,7 +703,7 @@ impl<T> Trait<T> for X { ); let impl_comparison = matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. }); - let assoc = self.associated_item(proj_ty.item_def_id); + let assoc = self.associated_item(proj_ty.def_id); if !callable_scope || impl_comparison { // We do not want to suggest calling functions when the reason of the // type error is a comparison of an `impl` with its `trait` or when the @@ -704,7 +716,7 @@ impl<T> Trait<T> for X { diag, assoc.container_id(self), current_method_ident, - proj_ty.item_def_id, + proj_ty.def_id, values.expected, ); // Possibly suggest constraining the associated type to conform to the @@ -763,11 +775,11 @@ fn foo(&self) -> Self::T { String::new() } self, diag: &mut Diagnostic, msg: &str, - proj_ty: &ty::ProjectionTy<'tcx>, + proj_ty: &ty::AliasTy<'tcx>, ty: Ty<'tcx>, ) -> bool { - let assoc = self.associated_item(proj_ty.item_def_id); - if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { + let assoc = self.associated_item(proj_ty.def_id); + if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() { let opaque_local_def_id = def_id.as_local(); let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id { match &self.hir().expect_item(opaque_local_def_id).kind { @@ -816,7 +828,7 @@ fn foo(&self) -> Self::T { String::new() } .filter_map(|(_, item)| { let method = self.fn_sig(item.def_id); match *method.output().skip_binder().kind() { - ty::Projection(ty::ProjectionTy { item_def_id, .. }) + ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. }) if item_def_id == proj_ty_item_def_id => { Some(( @@ -998,15 +1010,17 @@ fn foo(&self) -> Self::T { String::new() } } let mut short; loop { - // Look for the longest properly trimmed path that still fits in lenght_limit. - short = FmtPrinter::new_with_limit( - self, - hir::def::Namespace::TypeNS, - rustc_session::Limit(type_limit), - ) - .pretty_print_type(ty) - .expect("could not write to `String`") - .into_buffer(); + // Look for the longest properly trimmed path that still fits in length_limit. + short = with_forced_trimmed_paths!( + FmtPrinter::new_with_limit( + self, + hir::def::Namespace::TypeNS, + rustc_session::Limit(type_limit), + ) + .pretty_print_type(ty) + .expect("could not write to `String`") + .into_buffer() + ); if short.len() <= length_limit || type_limit == 0 { break; } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index c9c09c93a3e..f785fb5c4b9 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -6,28 +6,18 @@ use std::fmt::Debug; use std::hash::Hash; use std::iter; -use self::SimplifiedTypeGen::*; +use self::SimplifiedType::*; -pub type SimplifiedType = SimplifiedTypeGen<DefId>; - -/// See `simplify_type` -/// -/// Note that we keep this type generic over the type of identifier it uses -/// because we sometimes need to use SimplifiedTypeGen values as stable sorting -/// keys (in which case we use a DefPathHash as id-type) but in the general case -/// the non-stable but fast to construct DefId-version is the better choice. +/// See `simplify_type`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -pub enum SimplifiedTypeGen<D> -where - D: Copy + Debug + Eq, -{ +pub enum SimplifiedType { BoolSimplifiedType, CharSimplifiedType, IntSimplifiedType(ty::IntTy), UintSimplifiedType(ty::UintTy), FloatSimplifiedType(ty::FloatTy), - AdtSimplifiedType(D), - ForeignSimplifiedType(D), + AdtSimplifiedType(DefId), + ForeignSimplifiedType(DefId), StrSimplifiedType, ArraySimplifiedType, SliceSimplifiedType, @@ -38,9 +28,9 @@ where /// A trait object, all of whose components are markers /// (e.g., `dyn Send + Sync`). MarkerTraitObjectSimplifiedType, - TraitSimplifiedType(D), - ClosureSimplifiedType(D), - GeneratorSimplifiedType(D), + TraitSimplifiedType(DefId), + ClosureSimplifiedType(DefId), + GeneratorSimplifiedType(DefId), GeneratorWitnessSimplifiedType(usize), FunctionSimplifiedType(usize), PlaceholderSimplifiedType, @@ -126,7 +116,7 @@ pub fn simplify_type<'tcx>( TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType), TreatParams::AsInfer => None, }, - ty::Opaque(..) | ty::Projection(_) => match treat_params { + ty::Alias(..) => match treat_params { // When treating `ty::Param` as a placeholder, projections also // don't unify with anything else as long as they are fully normalized. // @@ -142,8 +132,8 @@ pub fn simplify_type<'tcx>( } } -impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> { - pub fn def(self) -> Option<D> { +impl SimplifiedType { + pub fn def(self) -> Option<DefId> { match self { AdtSimplifiedType(d) | ForeignSimplifiedType(d) @@ -153,36 +143,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> { _ => None, } } - - pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U> - where - F: Fn(D) -> U, - U: Copy + Debug + Eq, - { - match self { - BoolSimplifiedType => BoolSimplifiedType, - CharSimplifiedType => CharSimplifiedType, - IntSimplifiedType(t) => IntSimplifiedType(t), - UintSimplifiedType(t) => UintSimplifiedType(t), - FloatSimplifiedType(t) => FloatSimplifiedType(t), - AdtSimplifiedType(d) => AdtSimplifiedType(map(d)), - ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)), - StrSimplifiedType => StrSimplifiedType, - ArraySimplifiedType => ArraySimplifiedType, - SliceSimplifiedType => SliceSimplifiedType, - RefSimplifiedType(m) => RefSimplifiedType(m), - PtrSimplifiedType(m) => PtrSimplifiedType(m), - NeverSimplifiedType => NeverSimplifiedType, - MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, - TupleSimplifiedType(n) => TupleSimplifiedType(n), - TraitSimplifiedType(d) => TraitSimplifiedType(map(d)), - ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)), - GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)), - GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n), - FunctionSimplifiedType(n) => FunctionSimplifiedType(n), - PlaceholderSimplifiedType => PlaceholderSimplifiedType, - } - } } /// Given generic arguments from an obligation and an impl, @@ -225,7 +185,7 @@ impl DeepRejectCtxt { match impl_ty.kind() { // Start by checking whether the type in the impl may unify with // pretty much everything. Just return `true` in that case. - ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true, + ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true, // These types only unify with inference variables or their own // variant. ty::Bool @@ -323,8 +283,6 @@ impl DeepRejectCtxt { _ => false, }, - ty::Opaque(..) => true, - // Impls cannot contain these types as these cannot be named directly. ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false, @@ -344,7 +302,7 @@ impl DeepRejectCtxt { // projections can unify with other stuff. // // Looking forward to lazy normalization this is the safer strategy anyways. - ty::Projection(_) => true, + ty::Alias(..) => true, ty::Error(_) => true, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 046a2660a1f..d283ccc3ad8 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -155,12 +155,12 @@ impl FlagComputation { self.add_substs(substs); } - &ty::Projection(data) => { + &ty::Alias(ty::Projection, data) => { self.add_flags(TypeFlags::HAS_TY_PROJECTION); self.add_projection_ty(data); } - &ty::Opaque(_, substs) => { + &ty::Alias(ty::Opaque, ty::AliasTy { substs, .. }) => { self.add_flags(TypeFlags::HAS_TY_OPAQUE); self.add_substs(substs); } @@ -345,7 +345,7 @@ impl FlagComputation { } } - fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) { + fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) { self.add_substs(projection_ty.substs); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index d431d008ddf..09fee0c3f7c 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -583,36 +583,6 @@ impl<'tcx> TyCtxt<'tcx> { self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0 } - /// Rewrite any late-bound regions so that they are anonymous. Region numbers are - /// assigned starting at 0 and increasing monotonically in the order traversed - /// by the fold operation. - /// - /// The chief purpose of this function is to canonicalize regions so that two - /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become - /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and - /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization. - pub fn anonymize_late_bound_regions<T>(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T> - where - T: TypeFoldable<'tcx>, - { - let mut counter = 0; - let inner = self - .replace_late_bound_regions(sig, |_| { - let br = ty::BoundRegion { - var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(counter, None), - }; - let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br)); - counter += 1; - r - }) - .0; - let bound_vars = self.mk_bound_variable_kinds( - (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))), - ); - Binder::bind_with_vars(inner, bound_vars) - } - /// Anonymize all bound variables in `value`, this is mostly used to improve caching. pub fn anonymize_bound_vars<T>(self, value: Binder<'tcx, T>) -> Binder<'tcx, T> where diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index ace81bc4f83..5d5089cec82 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -112,7 +112,7 @@ impl<'tcx> Ty<'tcx> { InhabitedPredicate::True } Never => InhabitedPredicate::False, - Param(_) | Projection(_) => InhabitedPredicate::GenericType(self), + Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self), Tuple(tys) if tys.is_empty() => InhabitedPredicate::True, // use a query for more complex cases Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 586460986dd..35d369ffc89 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -385,6 +385,21 @@ impl<'tcx> Instance<'tcx> { ) } + pub fn expect_resolve( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + ) -> Instance<'tcx> { + match ty::Instance::resolve(tcx, param_env, def_id, substs) { + Ok(Some(instance)) => instance, + _ => bug!( + "failed to resolve instance for {}", + tcx.def_path_str_with_substs(def_id, substs) + ), + } + } + // This should be kept up to date with `resolve`. pub fn resolve_opt_const_arg( tcx: TyCtxt<'tcx>, @@ -525,7 +540,7 @@ impl<'tcx> Instance<'tcx> { pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { let def_id = tcx.require_lang_item(LangItem::DropInPlace, None); let substs = tcx.intern_substs(&[ty.into()]); - Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap() + Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs) } #[instrument(level = "debug", skip(tcx), ret)] diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 488fd567846..7f66b993646 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -271,7 +271,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let non_zero = !ty.is_unsafe_ptr(); let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env); match tail.kind() { - ty::Param(_) | ty::Projection(_) => { + ty::Param(_) | ty::Alias(ty::Projection, _) => { debug_assert!(tail.has_non_region_param()); Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) }) } @@ -349,7 +349,7 @@ impl<'tcx> SizeSkeleton<'tcx> { } } - ty::Projection(_) | ty::Opaque(..) => { + ty::Alias(..) => { let normalized = tcx.normalize_erasing_regions(param_env, ty); if ty == normalized { Err(err) @@ -757,10 +757,9 @@ where } } - ty::Projection(_) + ty::Alias(..) | ty::Bound(..) | ty::Placeholder(..) - | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 659d99f025d..7290f0ae7c0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -64,6 +64,7 @@ use std::ops::ControlFlow; use std::{fmt, str}; pub use crate::ty::diagnostics::*; +pub use rustc_type_ir::AliasKind::*; pub use rustc_type_ir::DynKind::*; pub use rustc_type_ir::InferTy::*; pub use rustc_type_ir::RegionKind::*; @@ -82,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; @@ -93,16 +92,20 @@ pub use self::parameterized::ParameterizedOverTcx; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ - Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, + AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, - ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, - VarianceDiagInfo, + 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 @@ -235,7 +239,7 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec<Predicate<'tcx>>, } -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] pub enum ImplSubject<'tcx> { Trait(TraitRef<'tcx>), Inherent(Ty<'tcx>), @@ -781,8 +785,8 @@ impl<'tcx> TraitPredicate<'tcx> { } } - pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - Self { trait_ref: self.trait_ref.with_self_type(tcx, self_ty), ..self } + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } } pub fn def_id(self) -> DefId { @@ -1010,7 +1014,7 @@ impl<'tcx> TermKind<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct ProjectionPredicate<'tcx> { - pub projection_ty: ProjectionTy<'tcx>, + pub projection_ty: AliasTy<'tcx>, pub term: Term<'tcx>, } @@ -1046,7 +1050,19 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. pub fn projection_def_id(&self) -> DefId { // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().projection_ty.item_def_id + self.skip_binder().projection_ty.def_id + } +} + +impl<'tcx> ProjectionPredicate<'tcx> { + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + Self { + projection_ty: tcx.mk_alias_ty( + self.projection_ty.def_id, + [self_ty.into()].into_iter().chain(self.projection_ty.substs.iter().skip(1)), + ), + ..self + } } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index c7d6c6abd1c..a21e3961cb6 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -1,15 +1,10 @@ use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::{DefId, DefIndex}; +use rustc_hir::def_id::DefIndex; use rustc_index::vec::{Idx, IndexVec}; -use crate::middle::exported_symbols::ExportedSymbol; -use crate::mir::Body; -use crate::ty::{ - self, Clause, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty, -}; +use crate::ty; pub trait ParameterizedOverTcx: 'static { - #[allow(unused_lifetimes)] type Value<'tcx>; } @@ -67,7 +62,7 @@ trivially_parameterized_over_tcx! { ty::TraitDef, ty::Visibility<DefIndex>, ty::adjustment::CoerceUnsizedInfo, - ty::fast_reject::SimplifiedTypeGen<DefId>, + ty::fast_reject::SimplifiedType, rustc_ast::Attribute, rustc_ast::DelimArgs, rustc_attr::ConstStability, @@ -100,29 +95,28 @@ trivially_parameterized_over_tcx! { rustc_type_ir::Variance, } -// HACK(compiler-errors): This macro rule can only take an ident, -// not a path, due to parsing ambiguity reasons. That means we gotta -// import all of these types above. +// HACK(compiler-errors): This macro rule can only take a fake path, +// not a real, due to parsing ambiguity reasons. #[macro_export] macro_rules! parameterized_over_tcx { - ($($ident:ident),+ $(,)?) => { + ($($($fake_path:ident)::+),+ $(,)?) => { $( - impl $crate::ty::ParameterizedOverTcx for $ident<'static> { - type Value<'tcx> = $ident<'tcx>; + impl $crate::ty::ParameterizedOverTcx for $($fake_path)::+<'static> { + type Value<'tcx> = $($fake_path)::+<'tcx>; } )* } } parameterized_over_tcx! { - Ty, - FnSig, - GenericPredicates, - TraitRef, - Const, - Predicate, - Clause, - GeneratorDiagnosticData, - Body, - ExportedSymbol, + crate::middle::exported_symbols::ExportedSymbol, + crate::mir::Body, + ty::Ty, + ty::FnSig, + ty::GenericPredicates, + ty::TraitRef, + ty::Const, + ty::Predicate, + ty::Clause, + ty::GeneratorDiagnosticData, } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 667298b9b5b..29bad33e4bc 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -169,10 +169,8 @@ pub trait Printer<'tcx>: Sized { self.path_append( |cx: Self| { if trait_qualify_parent { - let trait_ref = ty::TraitRef::new( - parent_def_id, - cx.tcx().intern_substs(parent_substs), - ); + let trait_ref = + cx.tcx().mk_trait_ref(parent_def_id, parent_substs.iter().copied()); cx.path_qualified(trait_ref.self_ty(), Some(trait_ref)) } else { cx.print_def_path(parent_def_id, parent_substs) @@ -275,10 +273,9 @@ fn characteristic_def_id_of_type_cached<'a>( | ty::Uint(_) | ty::Str | ty::FnPtr(_) - | ty::Projection(_) + | ty::Alias(..) | ty::Placeholder(..) | ty::Param(_) - | ty::Opaque(..) | ty::Infer(_) | ty::Bound(..) | ty::Error(_) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5303341ba44..a1d53506707 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -10,12 +10,13 @@ use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; +use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::LangItem; use rustc_session::config::TrimmedDefPaths; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_session::Limit; use rustc_span::symbol::{kw, Ident, Symbol}; +use rustc_span::FileNameDisplayPreference; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; @@ -23,7 +24,6 @@ use smallvec::SmallVec; use std::cell::Cell; use std::char; use std::collections::BTreeMap; -use std::convert::TryFrom; use std::fmt::{self, Write as _}; use std::iter; use std::ops::{ControlFlow, Deref, DerefMut}; @@ -63,6 +63,7 @@ thread_local! { static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) }; static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) }; static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) }; + static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) }; static NO_QUERIES: Cell<bool> = const { Cell::new(false) }; static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) }; } @@ -116,6 +117,7 @@ define_helper!( /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`, /// if no other `Vec` is found. fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH); + fn with_forced_trimmed_paths(ForceTrimmedGuard, FORCE_TRIMMED_PATH); /// Prevent selection of visible paths. `Display` impl of DefId will prefer /// visible (public) reexports of types as paths. fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); @@ -295,11 +297,89 @@ pub trait PrettyPrinter<'tcx>: self.try_print_visible_def_path_recur(def_id, &mut callers) } + // Given a `DefId`, produce a short name. For types and traits, it prints *only* its name, + // For associated items on traits it prints out the trait's name and the associated item's name. + // For enum variants, if they have an unique name, then we only print the name, otherwise we + // print the enum name and the variant name. Otherwise, we do not print anything and let the + // caller use the `print_def_path` fallback. + fn force_print_trimmed_def_path( + mut self, + def_id: DefId, + ) -> Result<(Self::Path, bool), Self::Error> { + let key = self.tcx().def_key(def_id); + let visible_parent_map = self.tcx().visible_parent_map(()); + let kind = self.tcx().def_kind(def_id); + + let get_local_name = |this: &Self, name, def_id, key: DefKey| { + if let Some(visible_parent) = visible_parent_map.get(&def_id) + && let actual_parent = this.tcx().opt_parent(def_id) + && let DefPathData::TypeNs(_) = key.disambiguated_data.data + && Some(*visible_parent) != actual_parent + { + this + .tcx() + .module_children(visible_parent) + .iter() + .filter(|child| child.res.opt_def_id() == Some(def_id)) + .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore) + .map(|child| child.ident.name) + .unwrap_or(name) + } else { + name + } + }; + if let DefKind::Variant = kind + && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id) + { + // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`. + self.write_str(get_local_name(&self, *symbol, def_id, key).as_str())?; + return Ok((self, true)); + } + if let Some(symbol) = key.get_opt_name() { + if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = kind + && let Some(parent) = self.tcx().opt_parent(def_id) + && let parent_key = self.tcx().def_key(parent) + && let Some(symbol) = parent_key.get_opt_name() + { + // Trait + self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; + self.write_str("::")?; + } else if let DefKind::Variant = kind + && let Some(parent) = self.tcx().opt_parent(def_id) + && let parent_key = self.tcx().def_key(parent) + && let Some(symbol) = parent_key.get_opt_name() + { + // Enum + + // For associated items and variants, we want the "full" path, namely, include + // the parent type in the path. For example, `Iterator::Item`. + self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; + self.write_str("::")?; + } else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait + | DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind + { + } else { + // If not covered above, like for example items out of `impl` blocks, fallback. + return Ok((self, false)); + } + self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?; + return Ok((self, true)); + } + Ok((self, false)) + } + /// Try to see if this path can be trimmed to a unique symbol name. fn try_print_trimmed_def_path( mut self, def_id: DefId, ) -> Result<(Self::Path, bool), Self::Error> { + if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?; + if trimmed { + return Ok((s, true)); + } + self = s; + } if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never) || NO_TRIMMED_PATH.with(|flag| flag.get()) @@ -639,17 +719,17 @@ pub trait PrettyPrinter<'tcx>: ty::Foreign(def_id) => { p!(print_def_path(def_id, &[])); } - ty::Projection(ref data) => { + ty::Alias(ty::Projection, ref data) => { if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get())) - && self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder + && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder { - return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs); + return self.pretty_print_opaque_impl_type(data.def_id, data.substs); } else { p!(print(data)) } } ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), - ty::Opaque(def_id, substs) => { + ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { // FIXME(eddyb) print this with `print_def_path`. // We use verbose printing in 'NO_QUERIES' mode, to // avoid needing to call `predicates_of`. This should @@ -664,7 +744,9 @@ pub trait PrettyPrinter<'tcx>: let parent = self.tcx().parent(def_id); match self.tcx().def_kind(parent) { DefKind::TyAlias | DefKind::AssocTy => { - if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() { + if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) = + *self.tcx().type_of(parent).kind() + { if d == def_id { // If the type alias directly starts with the `impl` of the // opaque type we're printing, then skip the `::{opaque#1}`. @@ -737,11 +819,16 @@ pub trait PrettyPrinter<'tcx>: p!("@", print_def_path(did.to_def_id(), substs)); } else { let span = self.tcx().def_span(did); + let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + FileNameDisplayPreference::Short + } else { + FileNameDisplayPreference::Remapped + }; p!(write( "@{}", // This may end up in stderr diagnostics but it may also be emitted // into MIR. Hence we use the remapped path if available - self.tcx().sess.source_map().span_to_embeddable_string(span) + self.tcx().sess.source_map().span_to_string(span, preference) )); } } else { @@ -940,8 +1027,8 @@ pub trait PrettyPrinter<'tcx>: // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks, // unless we can find out what generator return type it comes from. let term = if let Some(ty) = term.skip_binder().ty() - && let ty::Projection(proj) = ty.kind() - && let Some(assoc) = tcx.opt_associated_item(proj.item_def_id) + && let ty::Alias(ty::Projection, proj) = ty.kind() + && let Some(assoc) = tcx.opt_associated_item(proj.def_id) && assoc.trait_container(tcx) == tcx.lang_items().gen_trait() && assoc.name == rustc_span::sym::Return { @@ -2574,7 +2661,7 @@ define_print_and_forward_display! { } ty::ExistentialProjection<'tcx> { - let name = cx.tcx().associated_item(self.item_def_id).name; + let name = cx.tcx().associated_item(self.def_id).name; p!(write("{} = ", name), print(self.term)) } @@ -2661,8 +2748,8 @@ define_print_and_forward_display! { } } - ty::ProjectionTy<'tcx> { - p!(print_def_path(self.item_def_id, self.substs)); + ty::AliasTy<'tcx> { + p!(print_def_path(self.def_id, self.substs)); } ty::ClosureKind { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index c759fb6d5e4..c4116558bd2 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -106,7 +106,7 @@ pub trait TypeRelation<'tcx>: Sized { T: Relate<'tcx>; } -pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy { +pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, a: Self, @@ -270,21 +270,17 @@ impl<'tcx> Relate<'tcx> for abi::Abi { } } -impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { +impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: ty::ProjectionTy<'tcx>, - b: ty::ProjectionTy<'tcx>, - ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> { - if a.item_def_id != b.item_def_id { - Err(TypeError::ProjectionMismatched(expected_found( - relation, - a.item_def_id, - b.item_def_id, - ))) + a: ty::AliasTy<'tcx>, + b: ty::AliasTy<'tcx>, + ) -> RelateResult<'tcx, ty::AliasTy<'tcx>> { + if a.def_id != b.def_id { + Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id))) } else { let substs = relation.relate(a.substs, b.substs)?; - Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs }) + Ok(relation.tcx().mk_alias_ty(a.def_id, substs)) } } } @@ -295,12 +291,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { a: ty::ExistentialProjection<'tcx>, b: ty::ExistentialProjection<'tcx>, ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> { - if a.item_def_id != b.item_def_id { - Err(TypeError::ProjectionMismatched(expected_found( - relation, - a.item_def_id, - b.item_def_id, - ))) + if a.def_id != b.def_id { + Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id))) } else { let term = relation.relate_with_variance( ty::Invariant, @@ -314,7 +306,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { a.substs, b.substs, )?; - Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term }) + Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term }) } } } @@ -330,7 +322,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) } else { let substs = relate_substs(relation, a.substs, b.substs)?; - Ok(ty::TraitRef { def_id: a.def_id, substs }) + Ok(relation.tcx().mk_trait_ref(a.def_id, substs)) } } } @@ -351,7 +343,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { } } -#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)] +#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)] struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>); impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { @@ -559,14 +551,15 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( } // these two are already handled downstream in case of lazy normalization - (&ty::Projection(a_data), &ty::Projection(b_data)) => { + (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => { let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) + Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs)) } - (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs)) - if a_def_id == b_def_id => - { + ( + &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }), + &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }), + ) if a_def_id == b_def_id => { if relation.intercrate() { // During coherence, opaque types should be treated as equal to each other, even if their generic params // differ, as they could resolve to the same hidden type, even for different generic params. diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 9f70b4f1ffd..3c6800cf293 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -651,8 +651,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> { } ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?), - ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?), - ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?), + ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), ty::Bool | ty::Char @@ -697,8 +696,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> { ty::Generator(_did, ref substs, _) => substs.visit_with(visitor), ty::GeneratorWitness(ref types) => types.visit_with(visitor), ty::Closure(_did, ref substs) => substs.visit_with(visitor), - ty::Projection(ref data) => data.visit_with(visitor), - ty::Opaque(_, ref substs) => substs.visit_with(visitor), + ty::Alias(_, ref data) => data.visit_with(visitor), ty::Bool | ty::Char diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9cbda95a4df..66aeebab88b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -217,7 +217,7 @@ static_assert_size!(TyKind<'_>, 32); /// * `GR`: The "return type", which is the type of value returned upon /// completion of the generator. /// * `GW`: The "generator witness". -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function, /// concatenated with a tuple containing the types of the upvars. @@ -348,7 +348,7 @@ impl<'tcx> ClosureSubsts<'tcx> { } /// Similar to `ClosureSubsts`; see the above documentation for more. -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] pub struct GeneratorSubsts<'tcx> { pub substs: SubstsRef<'tcx>, } @@ -693,7 +693,7 @@ impl<'tcx> ExistentialPredicate<'tcx> { match (*self, *other) { (Trait(_), Trait(_)) => Ordering::Equal, (Projection(ref a), Projection(ref b)) => { - tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id)) + tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id)) } (AutoTrait(ref a), AutoTrait(ref b)) => { tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) @@ -816,14 +816,13 @@ impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> { pub struct TraitRef<'tcx> { pub def_id: DefId, pub substs: SubstsRef<'tcx>, + /// This field exists to prevent the creation of `TraitRef` without + /// calling [TyCtxt::mk_trait_ref]. + pub(super) _use_mk_trait_ref_instead: (), } impl<'tcx> TraitRef<'tcx> { - pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> { - TraitRef { def_id, substs } - } - - pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { tcx.mk_trait_ref( self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)), @@ -833,10 +832,7 @@ impl<'tcx> TraitRef<'tcx> { /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi` /// are the parameters defined on trait. pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> { - ty::Binder::dummy(TraitRef { - def_id, - substs: InternalSubsts::identity_for_item(tcx, def_id), - }) + ty::Binder::dummy(tcx.mk_trait_ref(def_id, InternalSubsts::identity_for_item(tcx, def_id))) } #[inline] @@ -850,7 +846,7 @@ impl<'tcx> TraitRef<'tcx> { substs: SubstsRef<'tcx>, ) -> ty::TraitRef<'tcx> { let defs = tcx.generics_of(trait_id); - ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) } + tcx.mk_trait_ref(trait_id, tcx.intern_substs(&substs[..defs.params.len()])) } } @@ -980,8 +976,12 @@ where /// contain any bound vars that would be bound by the /// binder. This is commonly used to 'inject' a value T into a /// different binding level. + #[track_caller] pub fn dummy(value: T) -> Binder<'tcx, T> { - assert!(!value.has_escaping_bound_vars()); + assert!( + !value.has_escaping_bound_vars(), + "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder." + ); Binder(value, ty::List::empty()) } @@ -1128,28 +1128,52 @@ impl<'tcx, T> Binder<'tcx, Option<T>> { } } -/// Represents the projection of an associated type. In explicit UFCS -/// form this would be written `<T as Trait<..>>::N`. +impl<'tcx, T: IntoIterator> Binder<'tcx, T> { + pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> { + let bound_vars = self.1; + self.0.into_iter().map(|v| Binder(v, bound_vars)) + } +} + +/// Represents the projection of an associated type. +/// +/// For a projection, this would be `<Ty as Trait<...>>::N`. +/// +/// For an opaque type, there is no explicit syntax. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ProjectionTy<'tcx> { - /// The parameters of the associated item. +pub struct AliasTy<'tcx> { + /// The parameters of the associated or opaque item. + /// + /// For a projection, these are the substitutions for the trait and the + /// GAT substitutions, if there are any. + /// + /// For RPIT the substitutions are for the generics of the function, + /// while for TAIT it is used for the generic parameters of the alias. pub substs: SubstsRef<'tcx>, - /// The `DefId` of the `TraitItem` for the associated type `N`. + /// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection, + /// or the `OpaqueType` item if this is an opaque. /// - /// Note that this is not the `DefId` of the `TraitRef` containing this - /// associated type, which is in `tcx.associated_item(item_def_id).container`, - /// aka. `tcx.parent(item_def_id).unwrap()`. - pub item_def_id: DefId, + /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the + /// underlying type if the type is an opaque. + /// + /// Note that if this is an associated type, this is not the `DefId` of the + /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`, + /// aka. `tcx.parent(def_id)`. + pub def_id: DefId, + + /// This field exists to prevent the creation of `ProjectionTy` without using + /// [TyCtxt::mk_alias_ty]. + pub(super) _use_mk_alias_ty_instead: (), } -impl<'tcx> ProjectionTy<'tcx> { +impl<'tcx> AliasTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - match tcx.def_kind(self.item_def_id) { - DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id), + match tcx.def_kind(self.def_id) { + DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), DefKind::ImplTraitPlaceholder => { - tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id)) + tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id)) } kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"), } @@ -1162,11 +1186,11 @@ impl<'tcx> ProjectionTy<'tcx> { &self, tcx: TyCtxt<'tcx>, ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { - let def_id = tcx.parent(self.item_def_id); - assert_eq!(tcx.def_kind(def_id), DefKind::Trait); - let trait_generics = tcx.generics_of(def_id); + debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst)); + let trait_def_id = self.trait_def_id(tcx); + let trait_generics = tcx.generics_of(trait_def_id); ( - ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) }, + tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)), &self.substs[trait_generics.count()..], ) } @@ -1180,7 +1204,7 @@ impl<'tcx> ProjectionTy<'tcx> { /// as well. pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { let def_id = self.trait_def_id(tcx); - ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) } + tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id))) } pub fn self_ty(&self) -> Ty<'tcx> { @@ -1394,7 +1418,7 @@ impl From<BoundVar> for BoundTy { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct ExistentialProjection<'tcx> { - pub item_def_id: DefId, + pub def_id: DefId, pub substs: SubstsRef<'tcx>, pub term: Term<'tcx>, } @@ -1407,7 +1431,7 @@ impl<'tcx> ExistentialProjection<'tcx> { /// then this function would return an `exists T. T: Iterator` existential trait /// reference. pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { - let def_id = tcx.parent(self.item_def_id); + let def_id = tcx.parent(self.def_id); let subst_count = tcx.generics_of(def_id).count() - 1; let substs = tcx.intern_substs(&self.substs[..subst_count]); ty::ExistentialTraitRef { def_id, substs } @@ -1422,10 +1446,8 @@ impl<'tcx> ExistentialProjection<'tcx> { debug_assert!(!self_ty.has_escaping_bound_vars()); ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - item_def_id: self.item_def_id, - substs: tcx.mk_substs_trait(self_ty, self.substs), - }, + projection_ty: tcx + .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)), term: self.term, } } @@ -1438,7 +1460,7 @@ impl<'tcx> ExistentialProjection<'tcx> { projection_predicate.projection_ty.substs.type_at(0); Self { - item_def_id: projection_predicate.projection_ty.item_def_id, + def_id: projection_predicate.projection_ty.def_id, substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]), term: projection_predicate.term, } @@ -1455,7 +1477,7 @@ impl<'tcx> PolyExistentialProjection<'tcx> { } pub fn item_def_id(&self) -> DefId { - self.skip_binder().item_def_id + self.skip_binder().def_id } } @@ -1962,7 +1984,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_impl_trait(self) -> bool { - matches!(self.kind(), Opaque(..)) + matches!(self.kind(), Alias(ty::Opaque, ..)) } #[inline] @@ -2029,7 +2051,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx), ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), - ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => { + ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => { let assoc_items = tcx.associated_item_def_ids( tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), ); @@ -2109,7 +2131,7 @@ impl<'tcx> Ty<'tcx> { // type parameters only have unit metadata if they're sized, so return true // to make sure we double check this during confirmation - ty::Param(_) | ty::Projection(_) | ty::Opaque(..) => (tcx.types.unit, true), + ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true), ty::Infer(ty::TyVar(_)) | ty::Bound(..) @@ -2185,7 +2207,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(), - ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false, + ty::Alias(..) | ty::Param(_) => false, ty::Infer(ty::TyVar(_)) => false, @@ -2241,9 +2263,12 @@ impl<'tcx> Ty<'tcx> { ty::Generator(..) | ty::GeneratorWitness(..) => false, // Might be, but not "trivial" so just giving the safe answer. - ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false, + ty::Adt(..) | ty::Closure(..) => false, + + // Needs normalization or revealing to determine, so no is the safe answer. + ty::Alias(..) => false, - ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false, + ty::Param(..) | ty::Infer(..) | ty::Error(..) => false, ty::Bound(..) | ty::Placeholder(..) => { bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self); diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index a1b084a5e89..f8385c47016 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -252,7 +252,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArg<'tcx> { } } -/// A substitution mapping generic parameters to new values. +/// List of generic arguments that are gonna be used to substitute generic parameters. pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>; pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>; diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs new file mode 100644 index 00000000000..4fe85d4366f --- /dev/null +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -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>), +} diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 9ea8dc6e69f..857f52c8a24 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -259,7 +259,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(_) => break, - ty::Projection(_) | ty::Opaque(..) => { + ty::Alias(..) => { let normalized = normalize(ty); if ty == normalized { return ty; @@ -332,8 +332,7 @@ impl<'tcx> TyCtxt<'tcx> { break; } } - (ty::Projection(_) | ty::Opaque(..), _) - | (_, ty::Projection(_) | ty::Opaque(..)) => { + (ty::Alias(..), _) | (_, ty::Alias(..)) => { // If either side is a projection, attempt to // progress via normalization. (Should be safe to // apply to both sides as normalization is @@ -826,7 +825,7 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Opaque(def_id, substs) = *t.kind() { + if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() { self.expand_opaque_ty(def_id, substs).unwrap_or(t) } else if t.has_opaque_types() { t.super_fold_with(self) @@ -938,10 +937,9 @@ impl<'tcx> Ty<'tcx> { | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Infer(_) - | ty::Opaque(..) + | ty::Alias(..) | ty::Param(_) - | ty::Placeholder(_) - | ty::Projection(_) => false, + | ty::Placeholder(_) => false, } } @@ -978,10 +976,9 @@ impl<'tcx> Ty<'tcx> { | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Infer(_) - | ty::Opaque(..) + | ty::Alias(..) | ty::Param(_) - | ty::Placeholder(_) - | ty::Projection(_) => false, + | ty::Placeholder(_) => false, } } @@ -1101,12 +1098,9 @@ impl<'tcx> Ty<'tcx> { // // FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be // called for known, fully-monomorphized types. - ty::Projection(_) - | ty::Opaque(..) - | ty::Param(_) - | ty::Bound(..) - | ty::Placeholder(_) - | ty::Infer(_) => false, + ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => { + false + } ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false, } @@ -1237,11 +1231,10 @@ pub fn needs_drop_components<'tcx>( // These require checking for `Copy` bounds or `Adt` destructors. ty::Adt(..) - | ty::Projection(..) + | ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(..) - | ty::Opaque(..) | ty::Infer(_) | ty::Closure(..) | ty::Generator(..) => Ok(smallvec![ty]), @@ -1265,13 +1258,12 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { | ty::Never | ty::Foreign(_) => true, - ty::Opaque(..) + ty::Alias(..) | ty::Dynamic(..) | ty::Error(_) | ty::Bound(..) | ty::Param(_) | ty::Placeholder(_) - | ty::Projection(_) | ty::Infer(_) => false, // Not trivial because they have components, and instead of looking inside, diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 4cdfd9e5940..b302572f3ca 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -654,7 +654,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // ignore the inputs to a projection, as they may not appear // in the normalized form if self.just_constrained { - if let ty::Projection(..) | ty::Opaque(..) = t.kind() { + if let ty::Alias(..) = t.kind() { return ControlFlow::CONTINUE; } } diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 6eae94511e4..802925dfb04 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -1,4 +1,3 @@ -use std::convert::TryFrom; use std::fmt; use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar}; diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 4fab5abe909..34dbb6e9f68 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -165,7 +165,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) stack.push(ty.into()); stack.push(lt.into()); } - ty::Projection(data) => { + ty::Alias(_, data) => { stack.extend(data.substs.iter().rev()); } ty::Dynamic(obj, lt, _) => { @@ -188,7 +188,6 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) })); } ty::Adt(_, substs) - | ty::Opaque(_, substs) | ty::Closure(_, substs) | ty::Generator(_, substs, _) | ty::FnDef(_, substs) => { |
