diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty')
| -rw-r--r-- | compiler/rustc_middle/src/ty/codec.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 51 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/fold.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 76 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/query/keys.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/query/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/query/on_disk_cache.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/util.rs | 10 |
9 files changed, 115 insertions, 89 deletions
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 1def4936860..b2fc3710cd6 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -162,7 +162,8 @@ encodable_via_deref! { ty::Region<'tcx>, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, - &'tcx mir::BorrowCheckResult<'tcx> + &'tcx mir::BorrowCheckResult<'tcx>, + &'tcx mir::coverage::CodeRegion } pub trait TyDecoder<'tcx>: Decoder { @@ -376,7 +377,8 @@ impl_decodable_via_ref! { &'tcx Allocation, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, - &'tcx mir::BorrowCheckResult<'tcx> + &'tcx mir::BorrowCheckResult<'tcx>, + &'tcx mir::coverage::CodeRegion } #[macro_export] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f078bbacfe9..a8d007c0be2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -51,7 +51,7 @@ use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; use rustc_session::lint::{Level, Lint}; use rustc_session::Session; use rustc_span::source_map::MultiSpan; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; @@ -624,6 +624,19 @@ impl<'tcx> TypeckResults<'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: DefId, + ) -> 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 upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { self.upvar_capture_map[&upvar_id] } @@ -2066,42 +2079,6 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig })) } - /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name` - /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`. - pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool { - self.super_traits_of(trait_def_id).any(|trait_did| { - self.associated_items(trait_did) - .find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did) - .is_some() - }) - } - - /// Computes the def-ids of the transitive super-traits of `trait_def_id`. This (intentionally) - /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used - /// to identify which traits may define a given associated type to help avoid cycle errors. - /// Returns a `DefId` iterator. - fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx { - let mut set = FxHashSet::default(); - let mut stack = vec![trait_def_id]; - - set.insert(trait_def_id); - - iter::from_fn(move || -> Option<DefId> { - let trait_did = stack.pop()?; - let generic_predicates = self.super_predicates_of(trait_did); - - for (predicate, _) in generic_predicates.predicates { - if let ty::PredicateAtom::Trait(data, _) = predicate.skip_binders() { - if set.insert(data.def_id()) { - stack.push(data.def_id()); - } - } - } - - Some(trait_did) - }) - } - /// Given a closure signature, returns an equivalent fn signature. Detuples /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then /// you would get a `fn(u32, i32)`. diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 1883c89a151..13c8d6b2bcc 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -581,7 +581,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut const_map = FxHashMap::default(); if !value.has_escaping_bound_vars() { - (value.clone(), region_map) + (value, region_map) } else { let mut real_fld_r = |br| *region_map.entry(br).or_insert_with(|| fld_r(br)); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 038de42a6f1..7428f34153c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -588,7 +588,18 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> { #[rustc_diagnostic_item = "Ty"] pub type Ty<'tcx> = &'tcx TyS<'tcx>; -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + TyEncodable, + TyDecodable, + TypeFoldable, + HashStable +)] pub struct UpvarPath { pub hir_id: hir::HirId, } @@ -596,7 +607,7 @@ pub struct UpvarPath { /// Upvars do not get their own `NodeId`. Instead, we use the pair of /// the original var ID (that is, the root variable that is referenced /// by the upvar) and the ID of the closure expression. -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct UpvarId { pub var_path: UpvarPath, pub closure_expr_id: LocalDefId, @@ -608,7 +619,7 @@ impl UpvarId { } } -#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)] +#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. ImmBorrow, @@ -662,7 +673,7 @@ pub enum BorrowKind { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub enum UpvarCapture<'tcx> { /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases @@ -679,7 +690,7 @@ pub enum UpvarCapture<'tcx> { ByRef(UpvarBorrow<'tcx>), } -#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct UpvarBorrow<'tcx> { /// The kind of borrow: by-ref upvars have access to shared /// immutable borrows, which are not part of the normal language @@ -706,7 +717,7 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>; /// A `Place` and the corresponding `CaptureInfo`. -#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct CapturedPlace<'tcx> { pub place: HirPlace<'tcx>, pub info: CaptureInfo<'tcx>, @@ -715,7 +726,7 @@ pub struct CapturedPlace<'tcx> { /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move) /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] pub struct CaptureInfo<'tcx> { /// Expr Id pointing to use that resulted in selecting the current capture kind /// @@ -1599,34 +1610,59 @@ pub struct BoundConst<'tcx> { pub type PlaceholderConst<'tcx> = Placeholder<BoundConst<'tcx>>; -/// A `DefId` which is potentially bundled with its corresponding generic parameter -/// in case `did` is a const argument. +/// A `DefId` which, in case it is a const argument, is potentially bundled with +/// the `DefId` of the generic parameter it instantiates. /// -/// This is used to prevent cycle errors during typeck -/// as `type_of(const_arg)` depends on `typeck(owning_body)` -/// which once again requires the type of its generic arguments. -/// -/// Luckily we only need to deal with const arguments once we -/// know their corresponding parameters. We (ab)use this by -/// calling `type_of(param_did)` for these arguments. +/// This is used to avoid calls to `type_of` for const arguments during typeck +/// which cause cycle errors. /// /// ```rust /// #![feature(const_generics)] /// /// struct A; /// impl A { -/// fn foo<const N: usize>(&self) -> usize { N } +/// fn foo<const N: usize>(&self) -> [u8; N] { [0; N] } +/// // ^ const parameter /// } /// struct B; /// impl B { -/// fn foo<const N: u8>(&self) -> usize { 42 } +/// fn foo<const M: u8>(&self) -> usize { 42 } +/// // ^ const parameter /// } /// /// fn main() { /// let a = A; -/// a.foo::<7>(); +/// let _b = a.foo::<{ 3 + 7 }>(); +/// // ^^^^^^^^^ const argument /// } /// ``` +/// +/// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know +/// which `foo` is used until we know the type of `a`. +/// +/// We only know the type of `a` once we are inside of `typeck(main)`. +/// We also end up normalizing the type of `_b` during `typeck(main)` which +/// requires us to evaluate the const argument. +/// +/// To evaluate that const argument we need to know its type, +/// which we would get using `type_of(const_arg)`. This requires us to +/// resolve `foo` as it can be either `usize` or `u8` in this example. +/// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`, +/// which results in a cycle. +/// +/// In short we must not call `type_of(const_arg)` during `typeck(main)`. +/// +/// When first creating the `ty::Const` of the const argument inside of `typeck` we have +/// already resolved `foo` so we know which const parameter this argument instantiates. +/// This means that we also know the expected result of `type_of(const_arg)` even if we +/// aren't allowed to call that query: it is equal to `type_of(const_param)` which is +/// trivial to compute. +/// +/// If we now want to use that constant in a place which potentionally needs its type +/// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`, +/// except that instead of a `Ty` we bundle the `DefId` of the const parameter. +/// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some` +/// to get the type of `did`. #[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)] #[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(Hash, HashStable)] @@ -1637,7 +1673,7 @@ pub struct WithOptConstParam<T> { /// /// Note that even if `did` is a const argument, this may still be `None`. /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)` - /// to potentially update `param_did` in case it `None`. + /// to potentially update `param_did` in the case it is `None`. pub const_param_did: Option<DefId>, } diff --git a/compiler/rustc_middle/src/ty/query/keys.rs b/compiler/rustc_middle/src/ty/query/keys.rs index 3949c303f72..a005990264c 100644 --- a/compiler/rustc_middle/src/ty/query/keys.rs +++ b/compiler/rustc_middle/src/ty/query/keys.rs @@ -7,7 +7,7 @@ use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_query_system::query::DefaultCacheSelector; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; /// The `Key` trait controls what types can legally be used as the key @@ -149,28 +149,6 @@ impl Key for (LocalDefId, DefId) { } } -impl Key for (DefId, Option<Ident>) { - type CacheSelector = DefaultCacheSelector; - - fn query_crate(&self) -> CrateNum { - self.0.krate - } - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - tcx.def_span(self.0) - } -} - -impl Key for (DefId, LocalDefId, Ident) { - type CacheSelector = DefaultCacheSelector; - - fn query_crate(&self) -> CrateNum { - self.0.krate - } - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - self.1.default_span(tcx) - } -} - impl Key for (CrateNum, DefId) { type CacheSelector = DefaultCacheSelector; diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 187f86a52f4..b269dd09b72 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -220,7 +220,7 @@ pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &De .map(|c| c.is_green()) .unwrap_or(false)); - let key = <query_keys::$name<'tcx> as DepNodeParams<TyCtxt<'_>>>::recover(tcx, dep_node).unwrap(); + let key = <query_keys::$name<'tcx> as DepNodeParams<TyCtxt<'_>>>::recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)); if queries::$name::cache_on_disk(tcx, &key, None) { let _ = tcx.$name(key); } diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 898cc24992b..3eed94b1ffb 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -454,6 +454,7 @@ impl<'sess> OnDiskCache<'sess> { fn try_remap_cnum(&self, tcx: TyCtxt<'_>, cnum: u32) -> Option<CrateNum> { let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..])); + debug!("try_remap_cnum({}): cnum_map={:?}", cnum, cnum_map); cnum_map[CrateNum::from_u32(cnum)] } @@ -466,9 +467,22 @@ impl<'sess> OnDiskCache<'sess> { .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() }); } - pub fn register_reused_dep_path_hash(&self, hash: DefPathHash) { - if let Some(old_id) = self.foreign_def_path_hashes.get(&hash) { - self.latest_foreign_def_path_hashes.lock().insert(hash, *old_id); + /// If the given `hash` still exists in the current compilation, + /// calls `store_foreign_def_id` with its current `DefId`. + /// + /// Normally, `store_foreign_def_id_hash` can be called directly by + /// the dependency graph when we construct a `DepNode`. However, + /// when we re-use a deserialized `DepNode` from the previous compilation + /// session, we only have the `DefPathHash` available. This method is used + /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written + /// out for usage in the next compilation session. + pub fn register_reused_dep_path_hash(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) { + // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to + // `latest_foreign_def_path_hashes`, since the `RawDefId` might have + // changed in the current compilation session (e.g. we've added/removed crates, + // or added/removed definitions before/after the target definition). + if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) { + self.store_foreign_def_id_hash(def_id, hash); } } @@ -592,6 +606,7 @@ impl<'sess> OnDiskCache<'sess> { match cache.entry(hash) { Entry::Occupied(e) => *e.get(), Entry::Vacant(e) => { + debug!("def_path_hash_to_def_id({:?})", hash); // Check if the `DefPathHash` corresponds to a definition in the current // crate if let Some(def_id) = self.local_def_path_hash_to_def_id.get(&hash).cloned() { @@ -605,9 +620,11 @@ impl<'sess> OnDiskCache<'sess> { // current compilation session, the crate is guaranteed to be the same // (otherwise, we would compute a different `DefPathHash`). let raw_def_id = self.get_raw_def_id(&hash)?; + debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id); // If the owning crate no longer exists, the corresponding definition definitely // no longer exists. let krate = self.try_remap_cnum(tcx, raw_def_id.krate)?; + debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate); // If our `DefPathHash` corresponded to a definition in the local crate, // we should have either found it in `local_def_path_hash_to_def_id`, or // never attempted to load it in the first place. Any query result or `DepNode` @@ -621,6 +638,7 @@ impl<'sess> OnDiskCache<'sess> { // Try to find a definition in the current session, using the previous `DefIndex` // as an initial guess. let opt_def_id = tcx.cstore.def_path_hash_to_def_id(krate, raw_def_id.index, hash); + debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id); e.insert(opt_def_id); opt_def_id } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 72c97dfcf5d..5b787f9841c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2068,6 +2068,15 @@ impl<'tcx> TyS<'tcx> { } } + /// Get the `i`-th element of a tuple. + /// Panics when called on anything but a tuple. + pub fn tuple_element_ty(&self, i: usize) -> Option<Ty<'tcx>> { + match self.kind() { + Tuple(substs) => substs.iter().nth(i).map(|field| field.expect_ty()), + _ => bug!("tuple_fields called on non-tuple"), + } + } + /// If the type contains variants, returns the valid range of variant indices. // // FIXME: This requires the optimized MIR in the case of generators. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index e23c3f51967..25787f005aa 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -18,7 +18,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Integer, Size, TargetDataLayout}; use smallvec::SmallVec; use std::{cmp, fmt}; @@ -221,7 +221,13 @@ impl<'tcx> TyCtxt<'tcx> { mut ty: Ty<'tcx>, normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>, ) -> Ty<'tcx> { - loop { + for iteration in 0.. { + if !self.sess.recursion_limit().value_within_limit(iteration) { + return self.ty_error_with_message( + DUMMY_SP, + &format!("reached the recursion limit finding the struct tail for {}", ty), + ); + } match *ty.kind() { ty::Adt(def, substs) => { if !def.is_struct() { |
