diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty')
33 files changed, 1753 insertions, 1348 deletions
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index cd147d7e5..b9c5a4e0d 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -89,7 +89,9 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { Err(TypeError::Sorts(relate::expected_found(self, a, b))) } - (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(self.tcx().ty_error()), + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => { + Ok(self.tcx().ty_error_with_guaranteed(guar)) + } _ => relate::super_relate_tys(self, a, b), } diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 7036c4a7b..8ce06404d 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/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 55ee5bd2f..bb7fba3ee 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -37,6 +37,11 @@ impl AssocItem { Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) } + /// Gets the defaultness of the associated item. + /// To get the default associated type, use the [`type_of`] query on the + /// [`DefId`] of the type. + /// + /// [`type_of`]: crate::ty::TyCtxt::type_of pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness { tcx.impl_defaultness(self.def_id) } @@ -72,7 +77,7 @@ impl AssocItem { ty::AssocKind::Fn => { // We skip the binder here because the binder would deanonymize all // late-bound regions, and we don't want method signatures to show up - // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound + // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound // regions just fine, showing `fn(&MyType)`. tcx.fn_sig(self.def_id).skip_binder().to_string() } diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index d00553cba..6ade8935f 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -238,10 +238,7 @@ impl<'tcx> CapturedPlace<'tcx> { } } -fn symbols_for_closure_captures<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: (LocalDefId, LocalDefId), -) -> Vec<Symbol> { +fn symbols_for_closure_captures(tcx: TyCtxt<'_>, def_id: (LocalDefId, LocalDefId)) -> Vec<Symbol> { let typeck_results = tcx.typeck(def_id.0); let captures = typeck_results.closure_min_captures_flattened(def_id.1); captures.into_iter().map(|captured_place| captured_place.to_symbol(tcx)).collect() diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 75f2d45ea..8cc8286c1 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -310,7 +310,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> { fn decode(decoder: &mut D) -> Self { - let consts: ty::ConstS<'tcx> = Decodable::decode(decoder); + let consts: ty::ConstData<'tcx> = Decodable::decode(decoder); decoder.interner().mk_const(consts.kind, consts.ty) } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index c2be08e49..65cbac3e8 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -14,10 +14,10 @@ pub use int::*; pub use kind::*; pub use valtree::*; -/// Use this rather than `ConstS`, whenever possible. +/// Use this rather than `ConstData, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Const<'tcx>(pub Interned<'tcx, ConstS<'tcx>>); +pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>); impl<'tcx> fmt::Debug for Const<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -30,13 +30,13 @@ impl<'tcx> fmt::Debug for Const<'tcx> { /// Typed constant value. #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)] -pub struct ConstS<'tcx> { +pub struct ConstData<'tcx> { pub ty: Ty<'tcx>, pub kind: ConstKind<'tcx>, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ConstS<'_>, 40); +static_assert_size!(ConstData<'_>, 40); impl<'tcx> Const<'tcx> { #[inline] @@ -239,7 +239,7 @@ impl<'tcx> Const<'tcx> { } } -pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> { +pub fn const_param_default(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Const<'_>> { let default_def_id = match tcx.hir().get_by_def_id(def_id.expect_local()) { hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { default: Some(ac), .. }, @@ -250,5 +250,5 @@ pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx "`const_param_default` expected a generic parameter with a constant" ), }; - Const::from_anon_const(tcx, default_def_id) + ty::EarlyBinder(Const::from_anon_const(tcx, default_def_id)) } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index f3186e1c3..48958e0d9 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; @@ -233,7 +232,7 @@ impl ScalarInt { } #[inline] - pub fn try_to_machine_usize<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Result<u64, Size> { + pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> { Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64) } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index becc2b805..d9721863a 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 b44bc14ec..ce04d8d21 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, ConstData, DefIdTree, FloatTy, FloatVar, + FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, + ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, + ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy, Visibility, }; -use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; +use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -35,31 +33,26 @@ use rustc_data_structures::profiling::SelfProfilerRef; 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, RwLock, WorkerLocal}; -use rustc_data_structures::unord::UnordSet; -use rustc_data_structures::vec_map::VecMap; +use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal}; 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}; -use rustc_session::config::{CrateType, OutputFilenames}; -use rustc_session::cstore::CrateStoreDyn; +use rustc_session::config::CrateType; +use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; use rustc_session::Limit; use rustc_session::Session; @@ -76,15 +69,11 @@ 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; 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`. @@ -116,7 +105,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; @@ -150,7 +139,7 @@ pub struct CtxtInterners<'tcx> { predicates: InternedSet<'tcx, List<Predicate<'tcx>>>, projs: InternedSet<'tcx, List<ProjectionKind>>, place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>, - const_: InternedSet<'tcx, ConstS<'tcx>>, + const_: InternedSet<'tcx, ConstData<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>, layout: InternedSet<'tcx, LayoutS<VariantIdx>>, @@ -182,20 +171,12 @@ impl<'tcx> CtxtInterners<'tcx> { /// Interns a type. #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] - fn intern_ty( - &self, - kind: TyKind<'tcx>, - sess: &Session, - definitions: &rustc_hir::definitions::Definitions, - cstore: &CrateStoreDyn, - source_span: &IndexVec<LocalDefId, Span>, - ) -> Ty<'tcx> { + fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> { Ty(Interned::new_unchecked( self.type_ .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_kind(&kind); - let stable_hash = - self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); + let stable_hash = self.stable_hash(&flags, sess, untracked, &kind); InternedInSet(self.arena.alloc(WithCachedTypeInfo { internee: kind, @@ -212,9 +193,7 @@ impl<'tcx> CtxtInterners<'tcx> { &self, flags: &ty::flags::FlagComputation, sess: &'a Session, - definitions: &'a rustc_hir::definitions::Definitions, - cstore: &'a CrateStoreDyn, - source_span: &'a IndexVec<LocalDefId, Span>, + untracked: &'a Untracked, val: &T, ) -> Fingerprint { // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them. @@ -223,7 +202,7 @@ impl<'tcx> CtxtInterners<'tcx> { Fingerprint::ZERO } else { let mut hasher = StableHasher::new(); - let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span); + let mut hcx = StableHashingContext::new(sess, untracked); val.hash_stable(&mut hcx, &mut hasher); hasher.finish() } @@ -234,17 +213,14 @@ impl<'tcx> CtxtInterners<'tcx> { &self, kind: Binder<'tcx, PredicateKind<'tcx>>, sess: &Session, - definitions: &rustc_hir::definitions::Definitions, - cstore: &CrateStoreDyn, - source_span: &IndexVec<LocalDefId, Span>, + untracked: &Untracked, ) -> Predicate<'tcx> { Predicate(Interned::new_unchecked( self.predicate .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_predicate(kind); - let stable_hash = - self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); + let stable_hash = self.stable_hash(&flags, sess, untracked, &kind); InternedInSet(self.arena.alloc(WithCachedTypeInfo { internee: kind, @@ -298,675 +274,13 @@ 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>, sess: &Session, - definitions: &rustc_hir::definitions::Definitions, - cstore: &CrateStoreDyn, - source_span: &IndexVec<LocalDefId, Span>, + untracked: &Untracked, ) -> CommonTypes<'tcx> { - let mk = |ty| interners.intern_ty(ty, sess, definitions, cstore, source_span); + let mk = |ty| interners.intern_ty(ty, sess, untracked); CommonTypes { unit: mk(Tuple(List::empty())), @@ -1016,7 +330,7 @@ impl<'tcx> CommonConsts<'tcx> { }; CommonConsts { - unit: mk_const(ty::ConstS { + unit: mk_const(ty::ConstData { kind: ty::ConstKind::Value(ty::ValTree::zst()), ty: types.unit, }), @@ -1048,6 +362,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { TyCtxtFeed { tcx: self, key: () } } + pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> { + TyCtxtFeed { tcx: self, key: LOCAL_CRATE } + } } impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { @@ -1112,13 +429,7 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, - definitions: RwLock<Definitions>, - - /// Output of the resolver. - pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt, - /// The entire crate as AST. This field serves as the input for the hir_crate query, - /// which lowers it from AST to HIR. It must not be read or used by anything else. - pub untracked_crate: Steal<Lrc<ast::Crate>>, + untracked: Untracked, /// This provides access to the incremental compilation on-disk cache for query results. /// Do not access this directly. It is only meant to be used by @@ -1143,17 +454,11 @@ pub struct GlobalCtxt<'tcx> { /// Merge this with `selection_cache`? pub evaluation_cache: traits::EvaluationCache<'tcx>, - /// The definite name of the current crate after taking into account - /// attributes, commandline parameters, etc. - crate_name: Symbol, - /// Data layout specification for the current target. pub data_layout: TargetDataLayout, /// Stores memory for globals (statics/consts). pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>, - - output_filenames: Arc<OutputFilenames>, } impl<'tcx> TyCtxt<'tcx> { @@ -1278,28 +583,17 @@ impl<'tcx> TyCtxt<'tcx> { lint_store: Lrc<dyn Any + sync::Send + sync::Sync>, arena: &'tcx WorkerLocal<Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>, - definitions: Definitions, - untracked_resolutions: ty::ResolverGlobalCtxt, - krate: Lrc<ast::Crate>, + untracked: Untracked, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, query_kinds: &'tcx [DepKindStruct<'tcx>], - crate_name: Symbol, - output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { s.emit_fatal(err); }); let interners = CtxtInterners::new(arena); - let common_types = CommonTypes::new( - &interners, - s, - &definitions, - &*untracked_resolutions.cstore, - // This is only used to create a stable hashing context. - &untracked_resolutions.source_span, - ); + let common_types = CommonTypes::new(&interners, s, &untracked); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); @@ -1310,13 +604,11 @@ impl<'tcx> TyCtxt<'tcx> { hir_arena, interners, dep_graph, - definitions: RwLock::new(definitions), prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, consts: common_consts, - untracked_resolutions, - untracked_crate: Steal::new(krate), + untracked, on_disk_cache, queries, query_caches: query::QueryCaches::default(), @@ -1325,10 +617,8 @@ impl<'tcx> TyCtxt<'tcx> { pred_rcache: Default::default(), selection_cache: Default::default(), evaluation_cache: Default::default(), - crate_name, data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), - output_filenames: Arc::new(output_filenames), } } @@ -1428,7 +718,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id.as_local() { self.definitions_untracked().def_key(id) } else { - self.untracked_resolutions.cstore.def_key(id) + self.untracked.cstore.def_key(id) } } @@ -1442,7 +732,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id.as_local() { self.definitions_untracked().def_path(id) } else { - self.untracked_resolutions.cstore.def_path(id) + self.untracked.cstore.def_path(id) } } @@ -1452,7 +742,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(def_id) = def_id.as_local() { self.definitions_untracked().def_path_hash(def_id) } else { - self.untracked_resolutions.cstore.def_path_hash(def_id) + self.untracked.cstore.def_path_hash(def_id) } } @@ -1461,7 +751,7 @@ impl<'tcx> TyCtxt<'tcx> { if crate_num == LOCAL_CRATE { self.sess.local_stable_crate_id() } else { - self.untracked_resolutions.cstore.stable_crate_id(crate_num) + self.untracked.cstore.stable_crate_id(crate_num) } } @@ -1472,7 +762,7 @@ impl<'tcx> TyCtxt<'tcx> { if stable_crate_id == self.sess.local_stable_crate_id() { LOCAL_CRATE } else { - self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id) + self.untracked.cstore.stable_crate_id_to_crate_num(stable_crate_id) } } @@ -1487,11 +777,11 @@ impl<'tcx> TyCtxt<'tcx> { // If this is a DefPathHash from the local crate, we can look up the // DefId in the tcx's `Definitions`. if stable_crate_id == self.sess.local_stable_crate_id() { - self.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id() + self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id() } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map // it to a DefId. - let cstore = &*self.untracked_resolutions.cstore; + let cstore = &*self.untracked.cstore; let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id); cstore.def_path_hash_to_def_id(cnum, hash) } @@ -1503,9 +793,9 @@ impl<'tcx> TyCtxt<'tcx> { // statements within the query system and we'd run into endless // recursion otherwise. let (crate_name, stable_crate_id) = if def_id.is_local() { - (self.crate_name, self.sess.local_stable_crate_id()) + (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id()) } else { - let cstore = &*self.untracked_resolutions.cstore; + let cstore = &*self.untracked.cstore; (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) }; @@ -1547,7 +837,7 @@ impl<'tcx> TyCtxtAt<'tcx> { // This is fine because: // - those queries are `eval_always` so we won't miss their result changing; // - this write will have happened before these queries are called. - let key = self.definitions.write().create_def(parent, data); + let key = self.untracked.definitions.write().create_def(parent, data); let feed = TyCtxtFeed { tcx: self.tcx, key }; feed.def_span(self.span); @@ -1561,7 +851,7 @@ impl<'tcx> TyCtxt<'tcx> { // definitions change. self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); - let definitions = &self.definitions; + let definitions = &self.untracked.definitions; std::iter::from_generator(|| { let mut i = 0; @@ -1584,8 +874,8 @@ impl<'tcx> TyCtxt<'tcx> { self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); // Leak a read lock once we start iterating on definitions, to prevent adding new ones - // while iterating. If some query needs to add definitions, it should be `ensure`d above. - let definitions = self.definitions.leak(); + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.untracked.definitions.leak(); definitions.def_path_table() } @@ -1596,29 +886,29 @@ impl<'tcx> TyCtxt<'tcx> { // definitions change. self.ensure().hir_crate(()); // Leak a read lock once we start iterating on definitions, to prevent adding new ones - // while iterating. If some query needs to add definitions, it should be `ensure`d above. - let definitions = self.definitions.leak(); + // while iterating. If some query needs to add definitions, it should be `ensure`d above. + let definitions = self.untracked.definitions.leak(); definitions.def_path_hash_to_def_index_map() } /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn { - &*self.untracked_resolutions.cstore + &*self.untracked.cstore } /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries #[inline] pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> { - self.definitions.read() + self.untracked.definitions.read() } /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries #[inline] pub fn source_span_untracked(self, def_id: LocalDefId) -> Span { - self.untracked_resolutions.source_span.get(def_id).copied().unwrap_or(DUMMY_SP) + self.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP) } #[inline(always)] @@ -1626,14 +916,7 @@ impl<'tcx> TyCtxt<'tcx> { self, f: impl FnOnce(StableHashingContext<'_>) -> R, ) -> R { - let definitions = self.definitions_untracked(); - let hcx = StableHashingContext::new( - self.sess, - &*definitions, - &*self.untracked_resolutions.cstore, - &self.untracked_resolutions.source_span, - ); - f(hcx) + f(StableHashingContext::new(self.sess, &self.untracked)) } pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult { @@ -2175,8 +1458,7 @@ impl<'tcx> TyCtxt<'tcx> { Bound, Param, Infer, - Projection, - Opaque, + Alias, Foreign )?; @@ -2219,7 +1501,7 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { #[allow(rustc::usage_of_ty_tykind)] impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> { - fn borrow<'a>(&'a self) -> &'a T { + fn borrow(&self) -> &T { &self.0.internee } } @@ -2242,7 +1524,7 @@ impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> { } impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> { - fn borrow<'a>(&'a self) -> &'a [T] { + fn borrow(&self) -> &[T] { &self.0[..] } } @@ -2302,7 +1584,7 @@ macro_rules! direct_interners { direct_interners! { region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>, - const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>, + const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>, const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>, adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>, @@ -2353,7 +1635,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, _)| { @@ -2427,10 +1709,8 @@ impl<'tcx> TyCtxt<'tcx> { self.interners.intern_ty( st, self.sess, - &self.definitions.read(), - &*self.untracked_resolutions.cstore, // This is only used to create a stable hashing context. - &self.untracked_resolutions.source_span, + &self.untracked, ) } @@ -2439,10 +1719,8 @@ impl<'tcx> TyCtxt<'tcx> { self.interners.intern_predicate( binder, self.sess, - &self.definitions.read(), - &*self.untracked_resolutions.cstore, // This is only used to create a stable hashing context. - &self.untracked_resolutions.source_span, + &self.untracked, ) } @@ -2601,15 +1879,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)) @@ -2626,13 +1924,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] @@ -2655,6 +1952,15 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(GeneratorWitness(types)) } + /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. + pub fn mk_task_context(self) -> Ty<'tcx> { + let context_did = self.require_lang_item(LangItem::Context, None); + let context_adt_ref = self.adt_def(context_did); + let context_substs = self.intern_substs(&[self.lifetimes.re_erased.into()]); + let context_ty = self.mk_adt(context_adt_ref, context_substs); + self.mk_mut_ref(self.lifetimes.re_erased, context_ty) + } + #[inline] pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> { self.mk_ty_infer(TyVar(v)) @@ -2662,7 +1968,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> { - self.mk_const_internal(ty::ConstS { kind: kind.into(), ty }) + self.mk_const_internal(ty::ConstData { kind: kind.into(), ty }) } #[inline] @@ -2702,7 +2008,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> { @@ -2891,16 +2197,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< @@ -3092,13 +2399,8 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool { } pub fn provide(providers: &mut ty::query::Providers) { - providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; providers.module_reexports = |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); - providers.crate_name = |tcx, id| { - assert_eq!(id, LOCAL_CRATE); - tcx.crate_name - }; providers.maybe_unused_trait_imports = |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports; providers.maybe_unused_extern_crates = @@ -3109,8 +2411,6 @@ pub fn provide(providers: &mut ty::query::Providers) { providers.extern_mod_stmt_cnum = |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); - providers.output_filenames = |tcx, ()| &tcx.output_filenames; - providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime) @@ -3124,4 +2424,6 @@ pub fn provide(providers: &mut ty::query::Providers) { // We want to check if the panic handler was defined in this crate tcx.lang_items().panic_impl().map_or(false, |did| did.is_local()) }; + providers.source_span = + |tcx, def_id| tcx.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP); } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 511d51cd6..4b4518f61 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -3,13 +3,14 @@ use std::ops::ControlFlow; use crate::ty::{ - visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy, - PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, + visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque, + PolyTraitPredicate, Projection, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, }; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::WherePredicate; use rustc_span::Span; @@ -17,7 +18,7 @@ use rustc_type_ir::sty::TyKind::*; impl<'tcx> IntoDiagnosticArg for Ty<'tcx> { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - format!("{}", self).into_diagnostic_arg() + self.to_string().into_diagnostic_arg() } } @@ -443,7 +444,7 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> { type BreakTy = (); fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - match t.kind() { + match *t.kind() { Infer(InferTy::TyVar(_)) if self.infer_suggestable => {} FnDef(..) @@ -457,11 +458,11 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> { return ControlFlow::Break(()); } - Opaque(did, _) => { - let parent = self.tcx.parent(*did); - 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 + Alias(Opaque, AliasTy { def_id, .. }) => { + let parent = self.tcx.parent(def_id); + if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent) + && 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,14 +470,9 @@ 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(()), - } + Alias(Projection, AliasTy { def_id, .. }) => { + if self.tcx.def_kind(def_id) != DefKind::AssocTy { + return ControlFlow::Break(()); } } diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index ffdac93bc..9e4f90caa 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -21,7 +21,7 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable<'tcx>, { // If there's nothing to erase avoid performing the query at all - if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { + if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { return value; } debug!("erase_regions({:?})", value); diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index aa61c39b8..5d394f71f 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -1,11 +1,11 @@ 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}; use rustc_errors::{pluralize, Diagnostic, MultiSpan}; use rustc_hir as hir; +use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::def_id::DefId; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, Span}; @@ -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) => { @@ -307,7 +319,11 @@ impl<'tcx> Ty<'tcx> { .into() } } - ty::FnDef(..) => "fn item".into(), + ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) { + DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(), + DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(), + _ => "fn item".into(), + }, ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => { format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into() @@ -325,9 +341,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(), } } @@ -354,7 +370,11 @@ impl<'tcx> Ty<'tcx> { _ => "reference", } .into(), - ty::FnDef(..) => "fn item".into(), + ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) { + DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(), + DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(), + _ => "fn item".into(), + }, ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(..) => "trait object".into(), ty::Closure(..) => "closure".into(), @@ -363,9 +383,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 +408,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 +447,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); @@ -445,7 +465,7 @@ impl<'tcx> TyCtxt<'tcx> { .def_id .as_local() .map(|id| hir.local_def_id_to_hir_id(id)) - .and_then(|id| self.hir().find(self.hir().get_parent_node(id))) + .and_then(|id| self.hir().find_parent(id)) .as_ref() .and_then(|node| node.generics()) { @@ -454,7 +474,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 +501,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 +561,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 +570,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 +632,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 +688,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 +711,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 +724,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 +783,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 +836,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 +1018,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 c9c09c93a..f785fb5c4 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 046a2660a..b7eafc4b4 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -22,7 +22,7 @@ impl FlagComputation { result } - pub fn for_predicate<'tcx>(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { + pub fn for_predicate(binder: ty::Binder<'_, ty::PredicateKind<'_>>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_predicate(binder); result @@ -59,8 +59,18 @@ impl FlagComputation { { let mut computation = FlagComputation::new(); - if !value.bound_vars().is_empty() { - computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND; + for bv in value.bound_vars() { + match bv { + ty::BoundVariableKind::Ty(_) => { + computation.flags |= TypeFlags::HAS_TY_LATE_BOUND; + } + ty::BoundVariableKind::Region(_) => { + computation.flags |= TypeFlags::HAS_RE_LATE_BOUND; + } + ty::BoundVariableKind::Const => { + computation.flags |= TypeFlags::HAS_CT_LATE_BOUND; + } + } } f(&mut computation, value.skip_binder()); @@ -95,7 +105,7 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } - &ty::Generator(_, ref substs, _) => { + ty::Generator(_, substs, _) => { let substs = substs.as_generator(); let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); @@ -131,6 +141,7 @@ impl FlagComputation { &ty::Bound(debruijn, _) => { self.add_bound_var(debruijn); + self.add_flags(TypeFlags::HAS_TY_LATE_BOUND); } &ty::Placeholder(..) => { @@ -155,12 +166,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); } @@ -186,7 +197,7 @@ impl FlagComputation { &ty::Slice(tt) => self.add_ty(tt), - &ty::RawPtr(ref m) => { + ty::RawPtr(m) => { self.add_ty(m.ty); } @@ -303,6 +314,7 @@ impl FlagComputation { } ty::ConstKind::Bound(debruijn, _) => { self.add_bound_var(debruijn); + self.add_flags(TypeFlags::HAS_CT_LATE_BOUND); } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); @@ -345,7 +357,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 d431d008d..6b9a37d84 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -290,7 +290,7 @@ pub struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, /// Stores the index of a binder *just outside* the stuff we have - /// visited. So this begins as INNERMOST; when we pass through a + /// visited. So this begins as INNERMOST; when we pass through a /// binder, it is incremented (via `shift_in`). current_index: ty::DebruijnIndex, @@ -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/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 48329da3e..801ca6004 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -70,14 +70,6 @@ impl GenericParamDef { } } - pub fn has_default(&self) -> bool { - match self.kind { - GenericParamDefKind::Type { has_default, .. } - | GenericParamDefKind::Const { has_default } => has_default, - GenericParamDefKind::Lifetime => false, - } - } - pub fn is_anonymous_lifetime(&self) -> bool { match self.kind { GenericParamDefKind::Lifetime => { @@ -96,7 +88,7 @@ impl GenericParamDef { Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into())) } GenericParamDefKind::Const { has_default } if has_default => { - Some(tcx.bound_const_param_default(self.def_id).map_bound(|c| c.into())) + Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into())) } _ => None, } @@ -234,6 +226,15 @@ impl<'tcx> Generics { } } + pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] { + if let Some(index) = param_index.checked_sub(self.parent_count) { + &self.params[..index] + } else { + tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) + .params_to(param_index, tcx) + } + } + /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`. pub fn region_param( &'tcx self, @@ -340,15 +341,9 @@ impl<'tcx> GenericPredicates<'tcx> { &self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, - ) -> InstantiatedPredicates<'tcx> { - InstantiatedPredicates { - predicates: self - .predicates - .iter() - .map(|(p, _)| EarlyBinder(*p).subst(tcx, substs)) - .collect(), - spans: self.predicates.iter().map(|(_, sp)| *sp).collect(), - } + ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator + { + EarlyBinder(self.predicates).subst_iter_copied(tcx, substs) } #[instrument(level = "debug", skip(self, tcx))] diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index ace81bc4f..5d5089cec 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 586460986..6ac00d16c 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -6,6 +6,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def::Namespace; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; +use rustc_index::bit_set::FiniteBitSet; use rustc_macros::HashStable; use rustc_middle::ty::normalize_erasing_regions::NormalizationError; use rustc_span::Symbol; @@ -385,6 +386,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 +541,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)] @@ -696,7 +712,7 @@ fn polymorphize<'tcx>( } InternalSubsts::for_item(tcx, def_id, |param, _| { - let is_unused = unused.contains(param.index).unwrap_or(false); + let is_unused = unused.is_unused(param.index); debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused); match param.kind { // Upvar case: If parameter is a type parameter.. @@ -718,7 +734,7 @@ fn polymorphize<'tcx>( // Simple case: If parameter is a const or type parameter.. ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if // ..and is within range and unused.. - unused.contains(param.index).unwrap_or(false) => + unused.is_unused(param.index) => // ..then use the identity for this parameter. tcx.mk_param_from_def(param), @@ -740,14 +756,14 @@ fn needs_fn_once_adapter_shim( Ok(false) } (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => { - // The closure fn `llfn` is a `fn(&self, ...)`. We want a + // The closure fn `llfn` is a `fn(&self, ...)`. We want a // `fn(&mut self, ...)`. In fact, at codegen time, these are // basically the same thing, so we can just return llfn. Ok(false) } (ty::ClosureKind::Fn | ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => { // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut - // self, ...)`. We want a `fn(self, ...)`. We can produce + // self, ...)`. We want a `fn(self, ...)`. We can produce // this by doing something like: // // fn call_once(self, ...) { call_mut(&self, ...) } @@ -759,3 +775,36 @@ fn needs_fn_once_adapter_shim( (ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce, _) => Err(()), } } + +// Set bits represent unused generic parameters. +// An empty set indicates that all parameters are used. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)] +pub struct UnusedGenericParams(FiniteBitSet<u32>); + +impl UnusedGenericParams { + pub fn new_all_unused(amount: u32) -> Self { + let mut bitset = FiniteBitSet::new_empty(); + bitset.set_range(0..amount); + Self(bitset) + } + + pub fn new_all_used() -> Self { + Self(FiniteBitSet::new_empty()) + } + + pub fn mark_used(&mut self, idx: u32) { + self.0.clear(idx); + } + + pub fn is_unused(&self, idx: u32) -> bool { + self.0.contains(idx).unwrap_or(false) + } + + pub fn is_used(&self, idx: u32) -> bool { + !self.is_unused(idx) + } + + pub fn all_used(&self) -> bool { + self.0.is_empty() + } +} diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 488fd5678..dfd016569 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) @@ -670,29 +670,50 @@ where }); } - match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { - ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize), - ty::Dynamic(_, _, ty::Dyn) => { - TyMaybeWithLayout::Ty(tcx.mk_imm_ref( - tcx.lifetimes.re_static, - tcx.mk_array(tcx.types.usize, 3), - )) - /* FIXME: use actual fn pointers - Warning: naively computing the number of entries in the - vtable by counting the methods on the trait + methods on - all parent traits does not work, because some methods can - be not object safe and thus excluded from the vtable. - Increase this counter if you tried to implement this but - failed to do it without duplicating a lot of code from - other places in the compiler: 2 - tcx.mk_tup(&[ - tcx.mk_array(tcx.types.usize, 3), - tcx.mk_array(Option<fn()>), - ]) - */ + let mk_dyn_vtable = || { + tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3)) + /* FIXME: use actual fn pointers + Warning: naively computing the number of entries in the + vtable by counting the methods on the trait + methods on + all parent traits does not work, because some methods can + be not object safe and thus excluded from the vtable. + Increase this counter if you tried to implement this but + failed to do it without duplicating a lot of code from + other places in the compiler: 2 + tcx.mk_tup(&[ + tcx.mk_array(tcx.types.usize, 3), + tcx.mk_array(Option<fn()>), + ]) + */ + }; + + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { + let metadata = tcx.normalize_erasing_regions( + cx.param_env(), + tcx.mk_projection(metadata_def_id, [pointee]), + ); + + // Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it + // offers better information than `std::ptr::metadata::VTable`, + // and we rely on this layout information to trigger a panic in + // `std::mem::uninitialized::<&dyn Trait>()`, for example. + if let ty::Adt(def, substs) = metadata.kind() + && Some(def.did()) == tcx.lang_items().dyn_metadata() + && substs.type_at(0).is_trait() + { + mk_dyn_vtable() + } else { + metadata } - _ => bug!("TyAndLayout::field({:?}): not applicable", this), - } + } else { + match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { + ty::Slice(_) | ty::Str => tcx.types.usize, + ty::Dynamic(_, _, ty::Dyn) => mk_dyn_vtable(), + _ => bug!("TyAndLayout::field({:?}): not applicable", this), + } + }; + + TyMaybeWithLayout::Ty(metadata) } // Arrays and slices. @@ -757,10 +778,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), @@ -859,7 +879,7 @@ where // // If the niche is a pointer, it's either valid (according // to its type), or null (which the niche field's scalar - // validity range encodes). This allows using + // validity range encodes). This allows using // `dereferenceable_or_null` for e.g., `Option<&T>`, and // this will continue to work as long as we don't start // using more niches than just null (e.g., the first page of @@ -994,7 +1014,7 @@ where /// might (from a foreign exception or similar). #[inline] #[tracing::instrument(level = "debug", skip(tcx))] -pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool { +pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool { if let Some(did) = fn_def_id { // Special attribute for functions which can't unwind. if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3f99efd25..7dfcd1bb5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -38,14 +38,13 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; -use rustc_hir::definitions::Definitions; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; use rustc_hir::Node; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{Decodable, Encodable}; -use rustc_session::cstore::CrateStoreDyn; +use rustc_session::cstore::Untracked; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; @@ -64,6 +63,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::*; @@ -79,30 +79,32 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstData, ConstInt, ConstKind, 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::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; 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,27 +145,25 @@ mod parameterized; mod rvalue_scopes; mod structural_impls; mod sty; +mod typeck_results; // Data types pub type RegisteredTools = FxHashSet<Ident>; pub struct ResolverOutputs { - pub definitions: Definitions, pub global_ctxt: ResolverGlobalCtxt, pub ast_lowering: ResolverAstLowering, + pub untracked: Untracked, } #[derive(Debug)] pub struct ResolverGlobalCtxt { - pub cstore: Box<CrateStoreDyn>, pub visibilities: FxHashMap<LocalDefId, Visibility>, /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. pub has_pub_restricted: bool, /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>, - /// Reference span for definitions. - pub source_span: IndexVec<LocalDefId, Span>, pub effective_visibilities: EffectiveVisibilities, pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>, pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>, @@ -238,7 +238,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>), @@ -436,7 +436,7 @@ pub struct CrateVariancesMap<'tcx> { /// For each item with generics, maps to a vector of the variance /// of its generics. If an item has no generics, it will have no /// entry. - pub variances: FxHashMap<DefId, &'tcx [ty::Variance]>, + pub variances: DefIdMap<&'tcx [ty::Variance]>, } // Contains information needed to resolve types and (in the future) look up @@ -534,6 +534,17 @@ impl<'tcx> Predicate<'tcx> { self } + #[instrument(level = "debug", skip(tcx), ret)] + pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { + match self.kind().skip_binder() { + ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { + tcx.trait_is_coinductive(data.def_id()) + } + ty::PredicateKind::WellFormed(_) => true, + _ => false, + } + } + /// Whether this projection can be soundly normalized. /// /// Wf predicates must not be normalized, as normalization @@ -677,7 +688,7 @@ impl<'tcx> Predicate<'tcx> { // // In terms of why this is sound, the idea is that whenever there // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` - // holds. So if there is an impl of `T:Foo<'a>` that applies to + // holds. So if there is an impl of `T:Foo<'a>` that applies to // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all // `'a`. // @@ -689,7 +700,7 @@ impl<'tcx> Predicate<'tcx> { // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The // reason is similar to the previous example: any impl of - // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So + // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So // basically we would want to collapse the bound lifetimes from // the input (`trait_ref`) and the supertraits. // @@ -784,8 +795,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 { @@ -944,7 +955,7 @@ impl<'tcx> Term<'tcx> { &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), + &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), ))), _ => core::intrinsics::unreachable(), } @@ -990,7 +1001,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize) + (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) } }; @@ -1013,10 +1024,28 @@ 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>, } +impl<'tcx> ProjectionPredicate<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.projection_ty.self_ty() + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { + Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + self.projection_ty.trait_def_id(tcx) + } + + pub fn def_id(self) -> DefId { + self.projection_ty.def_id + } +} + pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; impl<'tcx> PolyProjectionPredicate<'tcx> { @@ -1049,7 +1078,7 @@ 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 } } @@ -1222,6 +1251,35 @@ impl<'tcx> InstantiatedPredicates<'tcx> { pub fn is_empty(&self) -> bool { self.predicates.is_empty() } + + pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { + (&self).into_iter() + } +} + +impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { + type Item = (Predicate<'tcx>, Span); + + type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>; + + fn into_iter(self) -> Self::IntoIter { + debug_assert_eq!(self.predicates.len(), self.spans.len()); + std::iter::zip(self.predicates, self.spans) + } +} + +impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { + type Item = (Predicate<'tcx>, Span); + + type IntoIter = std::iter::Zip< + std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>, + std::iter::Copied<std::slice::Iter<'a, Span>>, + >; + + fn into_iter(self) -> Self::IntoIter { + debug_assert_eq!(self.predicates.len(), self.spans.len()); + std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied()) + } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)] @@ -1299,7 +1357,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> { debug!(?id_substs); // This zip may have several times the same lifetime in `substs` paired with a different - // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour: + // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour: // it will pick the last one, which is the one we introduced in the impl-trait desugaring. let map = substs.iter().zip(id_substs).collect(); debug!("map = {:#?}", map); @@ -2087,7 +2145,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Look up the name of a definition across crates. This does not look at HIR. /// - /// This method will ICE if the corresponding item does not have a name. In these cases, use + /// This method will ICE if the corresponding item does not have a name. In these cases, use /// [`opt_item_name`] instead. /// /// [`opt_item_name`]: Self::opt_item_name @@ -2133,8 +2191,10 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Option<ImplOverlapKind> { // If either trait impl references an error, they're allowed to overlap, // as one of them essentially doesn't exist. - if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error()) - || self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error()) + if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.subst_identity().references_error()) + || self + .impl_trait_ref(def_id2) + .map_or(false, |tr| tr.subst_identity().references_error()) { return Some(ImplOverlapKind::Permitted { marker: false }); } @@ -2164,7 +2224,7 @@ impl<'tcx> TyCtxt<'tcx> { let is_marker_overlap = { let is_marker_impl = |def_id: DefId| -> bool { let trait_ref = self.impl_trait_ref(def_id); - trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker) + trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker) }; is_marker_impl(def_id1) && is_marker_impl(def_id2) }; @@ -2297,6 +2357,11 @@ impl<'tcx> TyCtxt<'tcx> { self.trait_def(trait_def_id).has_auto_impl } + /// Returns `true` if this is a trait alias. + pub fn trait_is_alias(self, trait_def_id: DefId) -> bool { + self.def_kind(trait_def_id) == DefKind::TraitAlias + } + pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { self.trait_is_auto(trait_def_id) || self.lang_items().sized_trait() == Some(trait_def_id) } @@ -2310,7 +2375,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. /// If it implements no trait, returns `None`. pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> { - self.impl_trait_ref(def_id).map(|tr| tr.def_id) + self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) } /// If the given `DefId` describes an item belonging to a trait, @@ -2411,8 +2476,10 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn is_const_fn_raw(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..)) - && self.constness(def_id) == hir::Constness::Const + matches!( + self.def_kind(def_id), + DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure + ) && self.constness(def_id) == hir::Constness::Const } #[inline] diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 9e69544d2..24f3d1acf 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>; } @@ -37,6 +32,10 @@ impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::Binder<'static, T> { type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>; } +impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::EarlyBinder<T> { + type Value<'tcx> = ty::EarlyBinder<T::Value<'tcx>>; +} + #[macro_export] macro_rules! trivially_parameterized_over_tcx { ($($ty:ty),+ $(,)?) => { @@ -66,9 +65,10 @@ trivially_parameterized_over_tcx! { ty::ImplPolarity, ty::ReprOptions, ty::TraitDef, + ty::UnusedGenericParams, ty::Visibility<DefIndex>, ty::adjustment::CoerceUnsizedInfo, - ty::fast_reject::SimplifiedTypeGen<DefId>, + ty::fast_reject::SimplifiedType, rustc_ast::Attribute, rustc_ast::DelimArgs, rustc_attr::ConstStability, @@ -101,29 +101,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 667298b9b..c302c4611 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -116,7 +116,7 @@ pub trait Printer<'tcx>: Sized { DefPathData::Impl => { let generics = self.tcx().generics_of(def_id); let self_ty = self.tcx().bound_type_of(def_id); - let impl_trait_ref = self.tcx().bound_impl_trait_ref(def_id); + let impl_trait_ref = self.tcx().impl_trait_ref(def_id); let (self_ty, impl_trait_ref) = if substs.len() >= generics.count() { ( self_ty.subst(self.tcx(), substs), @@ -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 5303341ba..ae7c20fff 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); @@ -281,6 +283,8 @@ pub trait PrettyPrinter<'tcx>: /// This is typically the case for all non-`'_` regions. fn should_print_region(&self, region: ty::Region<'tcx>) -> bool; + fn reset_type_limit(&mut self) {} + // Defaults (should not be overridden): /// If possible, this returns a global path resolving to `def_id` that is visible @@ -295,11 +299,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()) @@ -311,7 +393,7 @@ pub trait PrettyPrinter<'tcx>: match self.tcx().trimmed_def_paths(()).get(&def_id) { None => Ok((self, false)), Some(symbol) => { - self.write_str(symbol.as_str())?; + write!(self, "{}", Ident::with_dummy_span(*symbol))?; Ok((self, true)) } } @@ -639,17 +721,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 +746,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 +821,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 { @@ -765,24 +854,7 @@ pub trait PrettyPrinter<'tcx>: } p!("]"); } - ty::Array(ty, sz) => { - p!("[", print(ty), "; "); - if self.should_print_verbose() { - p!(write("{:?}", sz)); - } else if let ty::ConstKind::Unevaluated(..) = sz.kind() { - // Do not try to evaluate unevaluated constants. If we are const evaluating an - // array length anon const, rustc will (with debug assertions) print the - // constant's path. Which will end up here again. - p!("_"); - } else if let Some(n) = sz.kind().try_to_bits(self.tcx().data_layout.pointer_size) { - p!(write("{}", n)); - } else if let ty::ConstKind::Param(param) = sz.kind() { - p!(print(param)); - } else { - p!("_"); - } - p!("]") - } + ty::Array(ty, sz) => p!("[", print(ty), "; ", print(sz), "]"), ty::Slice(ty) => p!("[", print(ty), "]"), } @@ -940,8 +1012,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 { @@ -1214,21 +1286,25 @@ pub trait PrettyPrinter<'tcx>: match ct.kind() { ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => { match self.tcx().def_kind(def.did) { - DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => { + DefKind::Const | DefKind::AssocConst => { p!(print_value_path(def.did, substs)) } - _ => { - if def.is_local() { - let span = self.tcx().def_span(def.did); - if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { - p!(write("{}", snip)) - } else { - print_underscore!() - } + DefKind::AnonConst => { + if def.is_local() + && let span = self.tcx().def_span(def.did) + && let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) + { + p!(write("{}", snip)) } else { - print_underscore!() + // Do not call `print_value_path` as if a parent of this anon const is an impl it will + // attempt to print out the impl trait ref i.e. `<T as Trait>::{constant#0}`. This would + // cause printing to enter an infinite recursion if the anon const is in the self type i.e. + // `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {` + // where we would try to print `<[T; /* print `constant#0` again */] as Default>::{constant#0}` + p!(write("{}::{}", self.tcx().crate_name(def.did.krate), self.tcx().def_path(def.did).to_string_no_crate_verbose())) } } + defkind => bug!("`{:?}` has unexpcted defkind {:?}", ct, defkind), } } ty::ConstKind::Infer(infer_ct) => { @@ -1250,7 +1326,7 @@ pub trait PrettyPrinter<'tcx>: ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), // FIXME(generic_const_exprs): // write out some legible representation of an abstract const? - ty::ConstKind::Expr(_) => p!("[Const Expr]"), + ty::ConstKind::Expr(_) => p!("[const expr]"), ty::ConstKind::Error(_) => p!("[const error]"), }; Ok(self) @@ -1894,6 +1970,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id)) } + fn reset_type_limit(&mut self) { + self.printed_type_count = 0; + } + fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option<Symbol> { self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id)) } @@ -2039,9 +2119,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions; - // These printouts are concise. They do not contain all the information + // These printouts are concise. They do not contain all the information // the user might want to diagnose an error, but there is basically no way - // to fit that into a short string. Hence the recommendation to use + // to fit that into a short string. Hence the recommendation to use // `explain_region()` or `note_and_explain_region()`. match *region { ty::ReEarlyBound(ref data) => { @@ -2388,7 +2468,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if not_previously_inserted { ty.super_visit_with(self) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } } @@ -2574,7 +2654,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)) } @@ -2635,11 +2715,15 @@ define_print_and_forward_display! { } ty::SubtypePredicate<'tcx> { - p!(print(self.a), " <: ", print(self.b)) + p!(print(self.a), " <: "); + cx.reset_type_limit(); + p!(print(self.b)) } ty::CoercePredicate<'tcx> { - p!(print(self.a), " -> ", print(self.b)) + p!(print(self.a), " -> "); + cx.reset_type_limit(); + p!(print(self.b)) } ty::TraitPredicate<'tcx> { @@ -2651,7 +2735,9 @@ define_print_and_forward_display! { } ty::ProjectionPredicate<'tcx> { - p!(print(self.projection_ty), " == ", print(self.term)) + p!(print(self.projection_ty), " == "); + cx.reset_type_limit(); + p!(print(self.term)) } ty::Term<'tcx> { @@ -2661,8 +2747,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 { @@ -2796,13 +2882,19 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere. /// /// The implementation uses similar import discovery logic to that of 'use' suggestions. +/// +/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths`]. fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> { let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default(); if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { + // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting. + // // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` // wrapper can be used to suppress this query, in exchange for full paths being formatted. - tcx.sess.delay_good_path_bug("trimmed_def_paths constructed"); + tcx.sess.delay_good_path_bug( + "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging", + ); } let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> = diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 642900d3a..9d4ee22a7 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -34,7 +34,7 @@ use crate::ty::layout::TyAndLayout; use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::GeneratorDiagnosticData; -use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; +use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams}; use rustc_ast as ast; use rustc_ast::expand::allocator::AllocatorKind; use rustc_attr as attr; @@ -50,7 +50,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::hir_id::OwnerId; use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; -use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; +use rustc_index::vec::IndexVec; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::cstore::{CrateDepKind, CrateSource}; use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib}; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index c759fb6d5..65fd8d975 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> { @@ -422,7 +414,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( bug!("bound types encountered in super_relate_tys") } - (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(tcx.ty_error()), + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error_with_guaranteed(guar)), (&ty::Never, _) | (&ty::Char, _) @@ -436,7 +428,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(a) } - (&ty::Param(ref a_p), &ty::Param(ref b_p)) if a_p.index == b_p.index => Ok(a), + (ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => Ok(a), (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a), @@ -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 9f70b4f1f..7d4d35b7f 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -7,7 +7,7 @@ use crate::mir::{Field, ProjectionKind}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; +use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; use rustc_hir::def::Namespace; use rustc_index::vec::{Idx, IndexVec}; @@ -99,12 +99,6 @@ impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> { } } -impl fmt::Debug for ty::RegionVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "'_#{}r", self.index()) - } -} - impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths!(fmt::Display::fmt(self, f)) @@ -186,6 +180,15 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { } } +impl<'tcx> fmt::Debug for AliasTy<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AliasTy") + .field("substs", &self.substs) + .field("def_id", &self.def_id) + .finish() + } +} + /////////////////////////////////////////////////////////////////////////// // Atomic structs // @@ -233,6 +236,7 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::BoundRegionKind, crate::ty::AssocItem, crate::ty::AssocKind, + crate::ty::AliasKind, crate::ty::Placeholder<crate::ty::BoundRegionKind>, crate::ty::ClosureKind, crate::ty::FreeRegion, @@ -363,7 +367,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::AdtDef<'tcx> { impl<'tcx> TypeVisitable<'tcx> for ty::AdtDef<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } @@ -461,7 +465,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> { let slot = Rc::get_mut_unchecked(&mut unique); // Semantically move the contained type out from `unique`, fold - // it, then move the folded value back into `unique`. Should + // it, then move the folded value back into `unique`. Should // folding fail, `ManuallyDrop` ensures that the "moved-out" // value is not re-dropped. let owned = ManuallyDrop::take(slot); @@ -507,7 +511,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> { let slot = Arc::get_mut_unchecked(&mut unique); // Semantically move the contained type out from `unique`, fold - // it, then move the folded value back into `unique`. Should + // it, then move the folded value back into `unique`. Should // folding fail, `ManuallyDrop` ensures that the "moved-out" // value is not re-dropped. let owned = ManuallyDrop::take(slot); @@ -651,8 +655,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 +700,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 @@ -712,7 +714,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> { | ty::Placeholder(..) | ty::Param(..) | ty::Never - | ty::Foreign(..) => ControlFlow::CONTINUE, + | ty::Foreign(..) => ControlFlow::Continue(()), } } } @@ -740,7 +742,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Region<'tcx> { impl<'tcx> TypeSuperVisitable<'tcx> for ty::Region<'tcx> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } @@ -842,7 +844,7 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9cbda95a4..91a7d5d38 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, - TypeVisitor, + self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; @@ -100,6 +100,13 @@ impl BoundRegionKind { None } + + pub fn get_id(&self) -> Option<DefId> { + match *self { + BoundRegionKind::BrNamed(id, _) => return Some(id), + _ => None, + } + } } pub trait Article { @@ -205,7 +212,7 @@ static_assert_size!(TyKind<'_>, 32); /// /// ## Generators /// -/// Generators are handled similarly in `GeneratorSubsts`. The set of +/// Generators are handled similarly in `GeneratorSubsts`. The set of /// type parameters is similar, but `CK` and `CS` are replaced by the /// following type parameters: /// @@ -217,7 +224,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 +355,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 +700,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 +823,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 +839,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 +853,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()])) } } @@ -928,6 +931,12 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { } } +impl rustc_errors::IntoDiagnosticArg for PolyExistentialTraitRef<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable)] pub enum BoundVariableKind { @@ -980,8 +989,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,30 +1141,144 @@ 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`. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +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)) + } +} + +struct SkipBindersAt<'tcx> { + tcx: TyCtxt<'tcx>, + index: ty::DebruijnIndex, +} + +impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> { + type Error = (); + + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error> + where + T: ty::TypeFoldable<'tcx>, + { + self.index.shift_in(1); + let value = t.try_map_bound(|t| t.try_fold_with(self)); + self.index.shift_out(1); + value + } + + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { + if !ty.has_escaping_bound_vars() { + Ok(ty) + } else if let ty::Bound(index, bv) = *ty.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_ty(ty::Bound(index.shifted_out(1), bv))) + } + } else { + ty.try_super_fold_with(self) + } + } + + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { + if !r.has_escaping_bound_vars() { + Ok(r) + } else if let ty::ReLateBound(index, bv) = r.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_region(ty::ReLateBound(index.shifted_out(1), bv))) + } + } else { + r.try_super_fold_with(self) + } + } + + fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> { + if !ct.has_escaping_bound_vars() { + Ok(ct) + } else if let ty::ConstKind::Bound(index, bv) = ct.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_const( + ty::ConstKind::Bound(index.shifted_out(1), bv), + ct.ty().try_fold_with(self)?, + )) + } + } else { + ct.try_super_fold_with(self) + } + } + + fn try_fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result<ty::Predicate<'tcx>, Self::Error> { + if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) } + } +} + +/// 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, 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 `AliasTy` without using + /// [TyCtxt::mk_alias_ty]. + pub(super) _use_mk_alias_ty_instead: (), } -impl<'tcx> ProjectionTy<'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), +impl<'tcx> AliasTy<'tcx> { + pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind { + match tcx.def_kind(self.def_id) { + DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection, + DefKind::OpaqueTy => ty::Opaque, + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } + + pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + tcx.mk_ty(ty::Alias(self.kind(tcx), self)) + } +} + +/// The following methods work only with associated type projections. +impl<'tcx> AliasTy<'tcx> { + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + 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:?}"), + kind => bug!("expected a projection AliasTy; found {kind:?}"), } } @@ -1159,14 +1286,14 @@ impl<'tcx> ProjectionTy<'tcx> { /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`, /// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs pub fn trait_ref_and_own_substs( - &self, + 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()..], ) } @@ -1178,14 +1305,18 @@ impl<'tcx> ProjectionTy<'tcx> { /// WARNING: This will drop the substs for generic associated types /// consider calling [Self::trait_ref_and_own_substs] to get those /// as well. - pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { + 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> { + pub fn self_ty(self) -> Ty<'tcx> { self.substs.type_at(0) } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1))) + } } #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)] @@ -1354,9 +1485,8 @@ pub struct ConstVid<'tcx> { rustc_index::newtype_index! { /// A **region** (lifetime) **v**ariable **ID**. #[derive(HashStable)] - pub struct RegionVid { - DEBUG_FORMAT = custom, - } + #[debug_format = "'_#{}r"] + pub struct RegionVid {} } impl Atom for RegionVid { @@ -1367,7 +1497,7 @@ impl Atom for RegionVid { rustc_index::newtype_index! { #[derive(HashStable)] - pub struct BoundVar { .. } + pub struct BoundVar {} } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] @@ -1394,7 +1524,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 +1537,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 +1552,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 +1566,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 +1583,7 @@ impl<'tcx> PolyExistentialProjection<'tcx> { } pub fn item_def_id(&self) -> DefId { - self.skip_binder().item_def_id + self.skip_binder().def_id } } @@ -1661,7 +1789,7 @@ impl<'tcx> Ty<'tcx> { } #[inline] - pub fn is_ty_infer(self) -> bool { + pub fn is_ty_or_numeric_infer(self) -> bool { matches!(self.kind(), Infer(_)) } @@ -1904,7 +2032,7 @@ impl<'tcx> Ty<'tcx> { type BreakTy = (); fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - if self.0 == t { ControlFlow::BREAK } else { t.super_visit_with(self) } + if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) } } } @@ -1962,7 +2090,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 +2157,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 +2237,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 +2313,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 +2369,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 a1b084a5e..a07582fc8 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -7,6 +7,7 @@ use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; use rustc_data_structures::intern::Interned; +use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; @@ -36,6 +37,12 @@ pub struct GenericArg<'tcx> { marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>, } +impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + const TAG_MASK: usize = 0b11; const TYPE_TAG: usize = 0b00; const REGION_TAG: usize = 0b01; @@ -90,7 +97,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize) + (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) } }; @@ -166,7 +173,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), + &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), ))), _ => intrinsics::unreachable(), } @@ -202,7 +209,7 @@ impl<'tcx> GenericArg<'tcx> { pub fn is_non_region_infer(self) -> bool { match self.unpack() { GenericArgKind::Lifetime(_) => false, - GenericArgKind::Type(ty) => ty.is_ty_infer(), + GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(), GenericArgKind::Const(ct) => ct.is_ct_infer(), } } @@ -252,7 +259,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>; @@ -348,7 +355,7 @@ impl<'tcx> InternalSubsts<'tcx> { substs.reserve(defs.params.len()); for param in &defs.params { let kind = mk_kind(param, substs); - assert_eq!(param.index as usize, substs.len()); + assert_eq!(param.index as usize, substs.len(), "{substs:#?}, {defs:#?}"); substs.push(kind); } } @@ -400,6 +407,7 @@ impl<'tcx> InternalSubsts<'tcx> { } #[inline] + #[track_caller] pub fn type_at(&self, i: usize) -> Ty<'tcx> { if let GenericArgKind::Type(ty) = self[i].unpack() { ty @@ -409,6 +417,7 @@ impl<'tcx> InternalSubsts<'tcx> { } #[inline] + #[track_caller] pub fn region_at(&self, i: usize) -> ty::Region<'tcx> { if let GenericArgKind::Lifetime(lt) = self[i].unpack() { lt @@ -418,6 +427,7 @@ impl<'tcx> InternalSubsts<'tcx> { } #[inline] + #[track_caller] pub fn const_at(&self, i: usize) -> ty::Const<'tcx> { if let GenericArgKind::Const(ct) = self[i].unpack() { ct @@ -427,6 +437,7 @@ impl<'tcx> InternalSubsts<'tcx> { } #[inline] + #[track_caller] pub fn type_for_def(&self, def: &ty::GenericParamDef) -> GenericArg<'tcx> { self.type_at(def.index as usize).into() } @@ -534,6 +545,9 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> { /// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)` /// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call /// `subst`. +/// +/// If you don't have anything to `subst`, you may be looking for +/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable)] pub struct EarlyBinder<T>(pub T); @@ -573,6 +587,18 @@ impl<T> EarlyBinder<T> { pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> { EarlyBinder(value) } + + /// Skips the binder and returns the "bound" value. + /// This can be used to extract data that does not depend on generic parameters + /// (e.g., getting the `DefId` of the inner value or getting the number of + /// arguments of an `FnSig`). Otherwise, consider using + /// [`subst_identity`](EarlyBinder::subst_identity). + /// + /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is + /// the analogous operation on [`super::Binder`]. + pub fn skip_binder(self) -> T { + self.0 + } } impl<T> EarlyBinder<Option<T>> { @@ -631,6 +657,13 @@ where } } +impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I> +where + I::IntoIter: ExactSizeIterator, + I::Item: TypeFoldable<'tcx>, +{ +} + impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> where I::Item: Deref, @@ -678,6 +711,14 @@ where } } +impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I> +where + I::IntoIter: ExactSizeIterator, + I::Item: Deref, + <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>, +{ +} + pub struct EarlyBinderIter<T> { t: T, } @@ -705,6 +746,18 @@ impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> { let mut folder = SubstFolder { tcx, substs, binders_passed: 0 }; self.0.fold_with(&mut folder) } + + /// Makes the identity substitution `T0 => T0, ..., TN => TN`. + /// Conceptually, this converts universally bound variables into placeholders + /// when inside of a given item. + /// + /// For example, consider `for<T> fn foo<T>(){ .. }`: + /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`). + /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling + /// `subst_identity` to discharge the `EarlyBinder`. + pub fn subst_identity(self) -> T { + self.0 + } } /////////////////////////////////////////////////////////////////////////// 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 000000000..2902c6dc5 --- /dev/null +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -0,0 +1,707 @@ +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::{UnordItems, 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::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 items( + &'a self, + ) -> UnordItems<(hir::ItemLocalId, &'a V), impl Iterator<Item = (hir::ItemLocalId, &'a V)>> + { + self.data.items().map(|(id, value)| (*id, value)) + } + + pub fn items_in_stable_order(&self) -> Vec<(ItemLocalId, &'a V)> { + self.data.to_sorted_stable_ord() + } +} + +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) + } + + pub fn extend( + &mut self, + items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>, + ) { + self.data.extend(items.map(|(id, value)| { + validate_hir_id_for_typeck_results(self.hir_owner, id); + (id.local_id, value) + })) + } +} + +rustc_index::newtype_index! { + #[derive(HashStable)] + #[debug_format = "UserType({})"] + pub struct UserTypeAnnotationIndex { + 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>, +} + +/// Canonical 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(Eq, Hash, 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 47c1ce807..d0d1dcc58 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1,7 +1,9 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use crate::mir; use crate::ty::layout::IntegerExt; +use crate::ty::query::TyCtxtAt; use crate::ty::{ self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, @@ -15,6 +17,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_index::bit_set::GrowableBitSet; +use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_span::{sym, DUMMY_SP}; use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout}; @@ -257,7 +260,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(_) => break, - ty::Projection(_) | ty::Opaque(..) => { + ty::Alias(..) => { let normalized = normalize(ty); if ty == normalized { return ty; @@ -330,8 +333,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 @@ -639,24 +641,17 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.type_of(def_id)) } - pub fn bound_trait_impl_trait_tys( + pub fn bound_return_position_impl_trait_in_trait_tys( self, def_id: DefId, ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> { - ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id)) + ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id)) } pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> { ty::EarlyBinder(self.fn_sig(def_id)) } - pub fn bound_impl_trait_ref( - self, - def_id: DefId, - ) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> { - self.impl_trait_ref(def_id).map(|i| ty::EarlyBinder(i)) - } - pub fn bound_explicit_item_bounds( self, def_id: DefId, @@ -664,33 +659,88 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.explicit_item_bounds(def_id)) } - pub fn bound_item_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> { - ty::EarlyBinder(self.item_bounds(def_id)) - } - - pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> { - ty::EarlyBinder(self.const_param_default(def_id)) + pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> { + ty::EarlyBinder(self.impl_subject(def_id)) } - pub fn bound_predicates_of( + /// Returns names of captured upvars for closures and generators. + /// + /// Here are some examples: + /// - `name__field1__field2` when the upvar is captured by value. + /// - `_ref__name__field` when the upvar is captured by reference. + /// + /// For generators this only contains upvars that are shared by all states. + pub fn closure_saved_names_of_captured_variables( self, def_id: DefId, - ) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> { - ty::EarlyBinder(self.predicates_of(def_id)) + ) -> SmallVec<[String; 16]> { + let body = self.optimized_mir(def_id); + + body.var_debug_info + .iter() + .filter_map(|var| { + let is_ref = match var.value { + mir::VarDebugInfoContents::Place(place) + if place.local == mir::Local::new(1) => + { + // The projection is either `[.., Field, Deref]` or `[.., Field]`. It + // implies whether the variable is captured by value or by reference. + matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref) + } + _ => return None, + }; + let prefix = if is_ref { "_ref__" } else { "" }; + Some(prefix.to_owned() + var.name.as_str()) + }) + .collect() } - pub fn bound_explicit_predicates_of( + // FIXME(eddyb) maybe precompute this? Right now it's computed once + // per generator monomorphization, but it doesn't depend on substs. + pub fn generator_layout_and_saved_local_names( self, def_id: DefId, - ) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> { - ty::EarlyBinder(self.explicit_predicates_of(def_id)) + ) -> ( + &'tcx ty::GeneratorLayout<'tcx>, + IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>, + ) { + let tcx = self; + let body = tcx.optimized_mir(def_id); + let generator_layout = body.generator_layout().unwrap(); + let mut generator_saved_local_names = + IndexVec::from_elem(None, &generator_layout.field_tys); + + let state_arg = mir::Local::new(1); + for var in &body.var_debug_info { + let mir::VarDebugInfoContents::Place(place) = &var.value else { continue }; + if place.local != state_arg { + continue; + } + match place.projection[..] { + [ + // Deref of the `Pin<&mut Self>` state argument. + mir::ProjectionElem::Field(..), + mir::ProjectionElem::Deref, + // Field of a variant of the state. + mir::ProjectionElem::Downcast(_, variant), + mir::ProjectionElem::Field(field, _), + ] => { + let name = &mut generator_saved_local_names + [generator_layout.variant_fields[variant][field]]; + if name.is_none() { + name.replace(var.name); + } + } + _ => {} + } + } + (generator_layout, generator_saved_local_names) } +} - pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> { - ty::EarlyBinder(self.impl_subject(def_id)) +impl<'tcx> TyCtxtAt<'tcx> { + pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> { + ty::EarlyBinder(self.type_of(def_id)) } } @@ -750,7 +800,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) @@ -862,10 +912,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, } } @@ -902,10 +951,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, } } @@ -1025,12 +1073,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, } @@ -1161,18 +1206,17 @@ 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]), } } -pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { +pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { match *ty.kind() { ty::Bool | ty::Char @@ -1189,13 +1233,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 4cdfd9e59..bee3cc4d7 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -88,9 +88,11 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { self.has_vars_bound_at_or_above(ty::INNERMOST) } - #[instrument(level = "trace", ret)] fn has_type_flags(&self, flags: TypeFlags) -> bool { - self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags) + let res = + self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags); + trace!(?self, ?flags, ?res, "has_type_flags"); + res } fn has_projections(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PROJECTION) @@ -163,6 +165,14 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { fn has_late_bound_regions(&self) -> bool { self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) } + /// True if there are any late-bound non-region variables + fn has_non_region_late_bound(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) + } + /// True if there are any late-bound variables + fn has_late_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_BOUND) + } /// Indicates whether this value still has parameters/placeholders/inference variables /// which could be replaced later, in a way that would change the results of `impl` @@ -284,13 +294,13 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { match *r { ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } _ => { if (self.callback)(r) { - ControlFlow::BREAK + ControlFlow::Break(()) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } } @@ -301,7 +311,7 @@ impl<'tcx> TyCtxt<'tcx> { if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { ty.super_visit_with(self) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } } @@ -384,7 +394,7 @@ impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { - return ControlFlow::BREAK; + return ControlFlow::Break(()); } match *t.kind() { ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { @@ -502,7 +512,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { if t.outer_exclusive_binder() > self.outer_index { ControlFlow::Break(FoundEscapingVars) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } @@ -514,7 +524,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { if r.bound_at_or_above_binder(self.outer_index) { ControlFlow::Break(FoundEscapingVars) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } @@ -537,7 +547,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { if predicate.outer_exclusive_binder() > self.outer_index { ControlFlow::Break(FoundEscapingVars) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } } @@ -560,54 +570,42 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; #[inline] - #[instrument(skip(self), level = "trace", ret)] fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { let flags = t.flags(); - trace!(t.flags=?t.flags()); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } #[inline] - #[instrument(skip(self), level = "trace", ret)] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { let flags = r.type_flags(); - trace!(r.flags=?flags); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } #[inline] - #[instrument(level = "trace", ret)] fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { let flags = FlagComputation::for_const(c); trace!(r.flags=?flags); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } #[inline] - #[instrument(level = "trace", ret)] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { - debug!( - "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}", - predicate, - predicate.flags(), - self.flags - ); if predicate.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } } @@ -654,8 +652,8 @@ 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() { - return ControlFlow::CONTINUE; + if let ty::Alias(..) = t.kind() { + return ControlFlow::Continue(()); } } @@ -668,7 +666,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // in the normalized form if self.just_constrained { if let ty::ConstKind::Unevaluated(..) = c.kind() { - return ControlFlow::CONTINUE; + return ControlFlow::Continue(()); } } @@ -681,7 +679,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { self.regions.insert(br.kind); } } - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } @@ -728,6 +726,6 @@ impl<'tcx> TypeVisitor<'tcx> for MaxUniverse { ); } - ControlFlow::CONTINUE + ControlFlow::Continue(()) } } diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 6eae94511..f77bd9f0c 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}; @@ -89,8 +88,8 @@ pub(super) fn vtable_allocation_provider<'tcx>( let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) } - VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(), - VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(), + VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size), + VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size), VtblEntry::Vacant => continue, VtblEntry::Method(instance) => { // Prepare the fn ptr we write into the vtable. diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 4fab5abe9..708a5e4d0 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -4,7 +4,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::{self, Ty}; use rustc_data_structures::sso::SsoHashSet; -use smallvec::{self, SmallVec}; +use smallvec::SmallVec; // The TypeWalker's stack is hot enough that it's worth going to some effort to // avoid heap allocations. @@ -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) => { |