From 8961616e6004e204327f575081509b049268762b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 14 Nov 2020 03:02:03 +0100 Subject: Move rustc_middle::middle::cstore to rustc_session. --- compiler/rustc_session/Cargo.toml | 1 + compiler/rustc_session/src/cstore.rs | 195 +++++++++++++++++++++++++++++++++++ compiler/rustc_session/src/lib.rs | 3 +- 3 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_session/src/cstore.rs (limited to 'compiler/rustc_session') diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 4cff21bee3d..37cfc4a0dc3 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -9,6 +9,7 @@ rustc_macros = { path = "../rustc_macros" } tracing = "0.1" rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_hir = { path = "../rustc_hir" } rustc_target = { path = "../rustc_target" } rustc_serialize = { path = "../rustc_serialize" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs new file mode 100644 index 00000000000..4b93a3e8e83 --- /dev/null +++ b/compiler/rustc_session/src/cstore.rs @@ -0,0 +1,195 @@ +//! the rustc crate store interface. This also includes types that +//! are *mostly* used as a part of that interface, but these should +//! probably get a better home if someone can find one. + +use crate::search_paths::PathKind; +use crate::utils::NativeLibKind; +use rustc_ast as ast; +use rustc_data_structures::sync::{self, MetadataRef}; +use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE}; +use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; +use rustc_span::hygiene::{ExpnHash, ExpnId}; +use rustc_span::symbol::Symbol; +use rustc_span::Span; +use rustc_target::spec::Target; + +use std::any::Any; +use std::path::{Path, PathBuf}; + +// lonely orphan structs and enums looking for a better home + +/// Where a crate came from on the local filesystem. One of these three options +/// must be non-None. +#[derive(PartialEq, Clone, Debug, HashStable_Generic, Encodable, Decodable)] +pub struct CrateSource { + pub dylib: Option<(PathBuf, PathKind)>, + pub rlib: Option<(PathBuf, PathKind)>, + pub rmeta: Option<(PathBuf, PathKind)>, +} + +impl CrateSource { + pub fn paths(&self) -> impl Iterator { + self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0) + } +} + +#[derive(Encodable, Decodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] +#[derive(HashStable_Generic)] +pub enum CrateDepKind { + /// A dependency that is only used for its macros. + MacrosOnly, + /// A dependency that is always injected into the dependency list and so + /// doesn't need to be linked to an rlib, e.g., the injected allocator. + Implicit, + /// A dependency that is required by an rlib version of this crate. + /// Ordinary `extern crate`s result in `Explicit` dependencies. + Explicit, +} + +impl CrateDepKind { + pub fn macros_only(self) -> bool { + match self { + CrateDepKind::MacrosOnly => true, + CrateDepKind::Implicit | CrateDepKind::Explicit => false, + } + } +} + +#[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable_Generic)] +pub enum LinkagePreference { + RequireDynamic, + RequireStatic, +} + +#[derive(Debug, Encodable, Decodable, HashStable_Generic)] +pub struct NativeLib { + pub kind: NativeLibKind, + pub name: Option, + pub cfg: Option, + pub foreign_module: Option, + pub wasm_import_module: Option, + pub verbatim: Option, + pub dll_imports: Vec, +} + +#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)] +pub struct DllImport { + pub name: Symbol, + pub ordinal: Option, + /// Calling convention for the function. + /// + /// On x86_64, this is always `DllCallingConvention::C`; on i686, it can be any + /// of the values, and we use `DllCallingConvention::C` to represent `"cdecl"`. + pub calling_convention: DllCallingConvention, + /// Span of import's "extern" declaration; used for diagnostics. + pub span: Span, +} + +/// Calling convention for a function defined in an external library. +/// +/// The usize value, where present, indicates the size of the function's argument list +/// in bytes. +#[derive(Clone, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)] +pub enum DllCallingConvention { + C, + Stdcall(usize), + Fastcall(usize), + Vectorcall(usize), +} + +#[derive(Clone, Encodable, Decodable, HashStable_Generic, Debug)] +pub struct ForeignModule { + pub foreign_items: Vec, + pub def_id: DefId, +} + +#[derive(Copy, Clone, Debug, HashStable_Generic)] +pub struct ExternCrate { + pub src: ExternCrateSource, + + /// span of the extern crate that caused this to be loaded + pub span: Span, + + /// Number of links to reach the extern; + /// used to select the extern with the shortest path + pub path_len: usize, + + /// Crate that depends on this crate + pub dependency_of: CrateNum, +} + +impl ExternCrate { + /// If true, then this crate is the crate named by the extern + /// crate referenced above. If false, then this crate is a dep + /// of the crate. + pub fn is_direct(&self) -> bool { + self.dependency_of == LOCAL_CRATE + } + + pub fn rank(&self) -> impl PartialOrd { + // Prefer: + // - direct extern crate to indirect + // - shorter paths to longer + (self.is_direct(), !self.path_len) + } +} + +#[derive(Copy, Clone, Debug, HashStable_Generic)] +pub enum ExternCrateSource { + /// Crate is loaded by `extern crate`. + Extern( + /// def_id of the item in the current crate that caused + /// this crate to be loaded; note that there could be multiple + /// such ids + DefId, + ), + /// Crate is implicitly loaded by a path resolving through extern prelude. + Path, +} + +/// The backend's way to give the crate store access to the metadata in a library. +/// Note that it returns the raw metadata bytes stored in the library file, whether +/// it is compressed, uncompressed, some weird mix, etc. +/// rmeta files are backend independent and not handled here. +/// +/// At the time of this writing, there is only one backend and one way to store +/// metadata in library -- this trait just serves to decouple rustc_metadata from +/// the archive reader, which depends on LLVM. +pub trait MetadataLoader { + fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result; + fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result; +} + +pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; + +/// A store of Rust crates, through which their metadata can be accessed. +/// +/// Note that this trait should probably not be expanding today. All new +/// functionality should be driven through queries instead! +/// +/// If you find a method on this trait named `{name}_untracked` it signifies +/// that it's *not* tracked for dependency information throughout compilation +/// (it'd break incremental compilation) and should only be called pre-HIR (e.g. +/// during resolve) +pub trait CrateStore: std::fmt::Debug { + fn as_any(&self) -> &dyn Any; + + // Foreign definitions. + // This information is safe to access, since it's hashed as part of the DefPathHash, which incr. + // comp. uses to identify a DefId. + fn def_key(&self, def: DefId) -> DefKey; + fn def_path(&self, def: DefId) -> DefPath; + fn def_path_hash(&self, def: DefId) -> DefPathHash; + + // This information is safe to access, since it's hashed as part of the StableCrateId, which + // incr. comp. uses to identify a CrateNum. + fn crate_name(&self, cnum: CrateNum) -> Symbol; + fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId; + fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum; + + /// Fetch a DefId from a DefPathHash for a foreign crate. + fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId; + fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId; +} + +pub type CrateStoreDyn = dyn CrateStore + sync::Sync; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 9a82ae3fc10..d5f887f935b 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -14,6 +14,7 @@ pub mod parse; mod code_stats; #[macro_use] pub mod config; +pub mod cstore; pub mod filesearch; mod options; pub mod search_paths; @@ -28,4 +29,4 @@ pub use getopts; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext {} +pub trait HashStableContext: rustc_ast::HashStableContext + rustc_hir::HashStableContext {} -- cgit 1.4.1-3-g733a5 From c355b2e5cd74a6c9b80e6d31e39c5ea40497498f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 14 Nov 2020 16:35:31 +0100 Subject: Move ICH to rustc_query_system. --- Cargo.lock | 4 + compiler/rustc_middle/src/ich.rs | 5 + compiler/rustc_middle/src/ich/hcx.rs | 209 --------------------- compiler/rustc_middle/src/ich/impls_hir.rs | 150 --------------- compiler/rustc_middle/src/ich/impls_syntax.rs | 146 -------------- compiler/rustc_middle/src/ich/impls_ty.rs | 36 +--- compiler/rustc_middle/src/ich/mod.rs | 21 --- compiler/rustc_middle/src/middle/privacy.rs | 11 ++ compiler/rustc_query_system/Cargo.toml | 6 +- compiler/rustc_query_system/src/ich/hcx.rs | 209 +++++++++++++++++++++ compiler/rustc_query_system/src/ich/impls_hir.rs | 150 +++++++++++++++ .../rustc_query_system/src/ich/impls_syntax.rs | 146 ++++++++++++++ compiler/rustc_query_system/src/ich/mod.rs | 19 ++ compiler/rustc_query_system/src/lib.rs | 2 + compiler/rustc_session/src/lib.rs | 1 + 15 files changed, 553 insertions(+), 562 deletions(-) create mode 100644 compiler/rustc_middle/src/ich.rs delete mode 100644 compiler/rustc_middle/src/ich/hcx.rs delete mode 100644 compiler/rustc_middle/src/ich/impls_hir.rs delete mode 100644 compiler/rustc_middle/src/ich/impls_syntax.rs delete mode 100644 compiler/rustc_middle/src/ich/mod.rs create mode 100644 compiler/rustc_query_system/src/ich/hcx.rs create mode 100644 compiler/rustc_query_system/src/ich/impls_hir.rs create mode 100644 compiler/rustc_query_system/src/ich/impls_syntax.rs create mode 100644 compiler/rustc_query_system/src/ich/mod.rs (limited to 'compiler/rustc_session') diff --git a/Cargo.lock b/Cargo.lock index bada67eda44..eadac99787f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4308,13 +4308,17 @@ dependencies = [ "parking_lot", "rustc-rayon-core", "rustc_arena", + "rustc_ast", "rustc_data_structures", "rustc_errors", + "rustc_feature", + "rustc_hir", "rustc_index", "rustc_macros", "rustc_serialize", "rustc_session", "rustc_span", + "rustc_target", "smallvec", "tracing", ] diff --git a/compiler/rustc_middle/src/ich.rs b/compiler/rustc_middle/src/ich.rs new file mode 100644 index 00000000000..f0b869558bc --- /dev/null +++ b/compiler/rustc_middle/src/ich.rs @@ -0,0 +1,5 @@ +//! ICH - Incremental Compilation Hash + +pub use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; + +mod impls_ty; diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs deleted file mode 100644 index 98dcd62f795..00000000000 --- a/compiler/rustc_middle/src/ich/hcx.rs +++ /dev/null @@ -1,209 +0,0 @@ -use crate::ich; -use rustc_ast as ast; -use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::Lrc; -use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::definitions::{DefPathHash, Definitions}; -use rustc_session::cstore::CrateStore; -use rustc_session::Session; -use rustc_span::source_map::SourceMap; -use rustc_span::symbol::Symbol; -use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData}; - -fn compute_ignored_attr_names() -> FxHashSet { - debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty()); - ich::IGNORED_ATTRIBUTES.iter().copied().collect() -} - -/// This is the context state available during incr. comp. hashing. It contains -/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., -/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various -/// things (e.g., each `DefId`/`DefPath` is only hashed once). -#[derive(Clone)] -pub struct StableHashingContext<'a> { - definitions: &'a Definitions, - cstore: &'a dyn CrateStore, - pub(super) body_resolver: BodyResolver<'a>, - hash_spans: bool, - hash_bodies: bool, - pub(super) node_id_hashing_mode: NodeIdHashingMode, - - // Very often, we are hashing something that does not need the - // `CachingSourceMapView`, so we initialize it lazily. - raw_source_map: &'a SourceMap, - caching_source_map: Option>, -} - -#[derive(PartialEq, Eq, Clone, Copy)] -pub enum NodeIdHashingMode { - Ignore, - HashDefPath, -} - -/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. -/// We could also just store a plain reference to the `hir::Crate` but we want -/// to avoid that the crate is used to get untracked access to all of the HIR. -#[derive(Clone, Copy)] -pub(super) struct BodyResolver<'tcx>(&'tcx hir::Crate<'tcx>); - -impl<'tcx> BodyResolver<'tcx> { - /// Returns a reference to the `hir::Body` with the given `BodyId`. - /// **Does not do any tracking**; use carefully. - pub(super) fn body(self, id: hir::BodyId) -> &'tcx hir::Body<'tcx> { - self.0.body(id) - } -} - -impl<'a> StableHashingContext<'a> { - /// The `krate` here is only used for mapping `BodyId`s to `Body`s. - /// Don't use it for anything else or you'll run the risk of - /// leaking data out of the tracking system. - #[inline] - fn new_with_or_without_spans( - sess: &'a Session, - krate: &'a hir::Crate<'a>, - definitions: &'a Definitions, - cstore: &'a dyn CrateStore, - always_ignore_spans: bool, - ) -> Self { - let hash_spans_initial = - !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans; - - StableHashingContext { - body_resolver: BodyResolver(krate), - definitions, - cstore, - caching_source_map: None, - raw_source_map: sess.source_map(), - hash_spans: hash_spans_initial, - hash_bodies: true, - node_id_hashing_mode: NodeIdHashingMode::HashDefPath, - } - } - - #[inline] - pub fn new( - sess: &'a Session, - krate: &'a hir::Crate<'a>, - definitions: &'a Definitions, - cstore: &'a dyn CrateStore, - ) -> Self { - Self::new_with_or_without_spans( - sess, - krate, - definitions, - cstore, - /*always_ignore_spans=*/ false, - ) - } - - #[inline] - pub fn ignore_spans( - sess: &'a Session, - krate: &'a hir::Crate<'a>, - definitions: &'a Definitions, - cstore: &'a dyn CrateStore, - ) -> Self { - let always_ignore_spans = true; - Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans) - } - - #[inline] - pub fn while_hashing_hir_bodies(&mut self, hash_bodies: bool, f: F) { - let prev_hash_bodies = self.hash_bodies; - self.hash_bodies = hash_bodies; - f(self); - self.hash_bodies = prev_hash_bodies; - } - - #[inline] - pub fn while_hashing_spans(&mut self, hash_spans: bool, f: F) { - let prev_hash_spans = self.hash_spans; - self.hash_spans = hash_spans; - f(self); - self.hash_spans = prev_hash_spans; - } - - #[inline] - pub fn with_node_id_hashing_mode( - &mut self, - mode: NodeIdHashingMode, - f: F, - ) { - let prev = self.node_id_hashing_mode; - self.node_id_hashing_mode = mode; - f(self); - self.node_id_hashing_mode = prev; - } - - #[inline] - pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - if let Some(def_id) = def_id.as_local() { - self.local_def_path_hash(def_id) - } else { - self.cstore.def_path_hash(def_id) - } - } - - #[inline] - pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { - self.definitions.def_path_hash(def_id) - } - - #[inline] - pub fn hash_bodies(&self) -> bool { - self.hash_bodies - } - - #[inline] - pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { - match self.caching_source_map { - Some(ref mut sm) => sm, - ref mut none => { - *none = Some(CachingSourceMapView::new(self.raw_source_map)); - none.as_mut().unwrap() - } - } - } - - #[inline] - pub fn is_ignored_attr(&self, name: Symbol) -> bool { - thread_local! { - static IGNORED_ATTRIBUTES: FxHashSet = compute_ignored_attr_names(); - } - IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) - } -} - -impl<'a> HashStable> for ast::NodeId { - fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { - panic!("Node IDs should not appear in incremental state"); - } -} - -impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { - fn hash_spans(&self) -> bool { - self.hash_spans - } - - #[inline] - fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - self.def_path_hash(def_id) - } - - #[inline] - fn def_span(&self, def_id: LocalDefId) -> Span { - self.definitions.def_span(def_id) - } - - fn span_data_to_lines_and_cols( - &mut self, - span: &SpanData, - ) -> Option<(Lrc, usize, BytePos, usize, BytePos)> { - self.source_map().span_data_to_lines_and_cols(span) - } -} - -impl rustc_session::HashStableContext for StableHashingContext<'a> {} diff --git a/compiler/rustc_middle/src/ich/impls_hir.rs b/compiler/rustc_middle/src/ich/impls_hir.rs deleted file mode 100644 index 3c3e7e0d173..00000000000 --- a/compiler/rustc_middle/src/ich/impls_hir.rs +++ /dev/null @@ -1,150 +0,0 @@ -//! This module contains `HashStable` implementations for various HIR data -//! types in no particular order. - -use crate::ich::{NodeIdHashingMode, StableHashingContext}; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; -use rustc_hir as hir; -use rustc_hir::definitions::DefPathHash; -use smallvec::SmallVec; -use std::mem; - -impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { - #[inline] - fn hash_hir_id(&mut self, hir_id: hir::HirId, hasher: &mut StableHasher) { - let hcx = self; - match hcx.node_id_hashing_mode { - NodeIdHashingMode::Ignore => { - // Don't do anything. - } - NodeIdHashingMode::HashDefPath => { - let hir::HirId { owner, local_id } = hir_id; - - hcx.local_def_path_hash(owner).hash_stable(hcx, hasher); - local_id.hash_stable(hcx, hasher); - } - } - } - - fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) { - let hcx = self; - if hcx.hash_bodies() { - hcx.body_resolver.body(id).hash_stable(hcx, hasher); - } - } - - fn hash_reference_to_item(&mut self, id: hir::HirId, hasher: &mut StableHasher) { - let hcx = self; - - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - id.hash_stable(hcx, hasher); - }) - } - - fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) { - let hcx = self; - let hir::Mod { inner: ref inner_span, ref item_ids } = *module; - - inner_span.hash_stable(hcx, hasher); - - // Combining the `DefPathHash`s directly is faster than feeding them - // into the hasher. Because we use a commutative combine, we also don't - // have to sort the array. - let item_ids_hash = item_ids - .iter() - .map(|id| { - let def_path_hash = id.to_stable_hash_key(hcx); - def_path_hash.0 - }) - .fold(Fingerprint::ZERO, |a, b| a.combine_commutative(b)); - - item_ids.len().hash_stable(hcx, hasher); - item_ids_hash.hash_stable(hcx, hasher); - } - - fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) { - self.while_hashing_hir_bodies(true, |hcx| { - let hir::Expr { hir_id: _, ref span, ref kind } = *expr; - - span.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - }) - } - - fn hash_hir_ty(&mut self, ty: &hir::Ty<'_>, hasher: &mut StableHasher) { - self.while_hashing_hir_bodies(true, |hcx| { - let hir::Ty { hir_id: _, ref kind, ref span } = *ty; - - kind.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }) - } - - fn hash_hir_visibility_kind( - &mut self, - vis: &hir::VisibilityKind<'_>, - hasher: &mut StableHasher, - ) { - let hcx = self; - mem::discriminant(vis).hash_stable(hcx, hasher); - match *vis { - hir::VisibilityKind::Public | hir::VisibilityKind::Inherited => { - // No fields to hash. - } - hir::VisibilityKind::Crate(sugar) => { - sugar.hash_stable(hcx, hasher); - } - hir::VisibilityKind::Restricted { ref path, hir_id } => { - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - hir_id.hash_stable(hcx, hasher); - }); - path.hash_stable(hcx, hasher); - } - } - } - - fn hash_hir_item_like(&mut self, f: F) { - let prev_hash_node_ids = self.node_id_hashing_mode; - self.node_id_hashing_mode = NodeIdHashingMode::Ignore; - - f(self); - - self.node_id_hashing_mode = prev_hash_node_ids; - } -} - -impl<'a> HashStable> for hir::Body<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::Body { params, value, generator_kind } = self; - - hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| { - params.hash_stable(hcx, hasher); - value.hash_stable(hcx, hasher); - generator_kind.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> HashStable> for hir::TraitCandidate { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - let hir::TraitCandidate { def_id, import_ids } = self; - - def_id.hash_stable(hcx, hasher); - import_ids.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> ToStableHashKey> for hir::TraitCandidate { - type KeyType = (DefPathHash, SmallVec<[DefPathHash; 1]>); - - fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Self::KeyType { - let hir::TraitCandidate { def_id, import_ids } = self; - - ( - hcx.def_path_hash(*def_id), - import_ids.iter().map(|def_id| hcx.local_def_path_hash(*def_id)).collect(), - ) - } -} diff --git a/compiler/rustc_middle/src/ich/impls_syntax.rs b/compiler/rustc_middle/src/ich/impls_syntax.rs deleted file mode 100644 index acf2990b643..00000000000 --- a/compiler/rustc_middle/src/ich/impls_syntax.rs +++ /dev/null @@ -1,146 +0,0 @@ -//! This module contains `HashStable` implementations for various data types -//! from `rustc_ast` in no particular order. - -use crate::ich::StableHashingContext; - -use rustc_ast as ast; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_span::{BytePos, NormalizedPos, SourceFile}; -use std::assert_matches::assert_matches; - -use smallvec::SmallVec; - -impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {} - -impl<'a> HashStable> for [ast::Attribute] { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - if self.is_empty() { - self.len().hash_stable(hcx, hasher); - return; - } - - // Some attributes are always ignored during hashing. - let filtered: SmallVec<[&ast::Attribute; 8]> = self - .iter() - .filter(|attr| { - !attr.is_doc_comment() - && !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)) - }) - .collect(); - - filtered.len().hash_stable(hcx, hasher); - for attr in filtered { - attr.hash_stable(hcx, hasher); - } - } -} - -impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> { - fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) { - // Make sure that these have been filtered out. - debug_assert!(!attr.ident().map_or(false, |ident| self.is_ignored_attr(ident.name))); - debug_assert!(!attr.is_doc_comment()); - - let ast::Attribute { kind, id: _, style, span } = attr; - if let ast::AttrKind::Normal(item, tokens) = kind { - item.hash_stable(self, hasher); - style.hash_stable(self, hasher); - span.hash_stable(self, hasher); - assert_matches!( - tokens.as_ref(), - None, - "Tokens should have been removed during lowering!" - ); - } else { - unreachable!(); - } - } -} - -impl<'a> HashStable> for SourceFile { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let SourceFile { - name: _, // We hash the smaller name_hash instead of this - name_hash, - cnum, - // Do not hash the source as it is not encoded - src: _, - ref src_hash, - external_src: _, - start_pos, - end_pos: _, - ref lines, - ref multibyte_chars, - ref non_narrow_chars, - ref normalized_pos, - } = *self; - - (name_hash as u64).hash_stable(hcx, hasher); - - src_hash.hash_stable(hcx, hasher); - - // We only hash the relative position within this source_file - lines.len().hash_stable(hcx, hasher); - for &line in lines.iter() { - stable_byte_pos(line, start_pos).hash_stable(hcx, hasher); - } - - // We only hash the relative position within this source_file - multibyte_chars.len().hash_stable(hcx, hasher); - for &char_pos in multibyte_chars.iter() { - stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher); - } - - non_narrow_chars.len().hash_stable(hcx, hasher); - for &char_pos in non_narrow_chars.iter() { - stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher); - } - - normalized_pos.len().hash_stable(hcx, hasher); - for &char_pos in normalized_pos.iter() { - stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher); - } - - cnum.hash_stable(hcx, hasher); - } -} - -fn stable_byte_pos(pos: BytePos, source_file_start: BytePos) -> u32 { - pos.0 - source_file_start.0 -} - -fn stable_multibyte_char(mbc: rustc_span::MultiByteChar, source_file_start: BytePos) -> (u32, u32) { - let rustc_span::MultiByteChar { pos, bytes } = mbc; - - (pos.0 - source_file_start.0, bytes as u32) -} - -fn stable_non_narrow_char( - swc: rustc_span::NonNarrowChar, - source_file_start: BytePos, -) -> (u32, u32) { - let pos = swc.pos(); - let width = swc.width(); - - (pos.0 - source_file_start.0, width as u32) -} - -fn stable_normalized_pos(np: NormalizedPos, source_file_start: BytePos) -> (u32, u32) { - let NormalizedPos { pos, diff } = np; - - (pos.0 - source_file_start.0, diff) -} - -impl<'tcx> HashStable> for rustc_feature::Features { - fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { - // Unfortunately we cannot exhaustively list fields here, since the - // struct is macro generated. - self.declared_lang_features.hash_stable(hcx, hasher); - self.declared_lib_features.hash_stable(hcx, hasher); - - self.walk_feature_fields(|feature_name, value| { - feature_name.hash_stable(hcx, hasher); - value.hash_stable(hcx, hasher); - }); - } -} diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ich/impls_ty.rs index 3b0640eb98d..97106b58e0a 100644 --- a/compiler/rustc_middle/src/ich/impls_ty.rs +++ b/compiler/rustc_middle/src/ich/impls_ty.rs @@ -1,7 +1,7 @@ //! This module contains `HashStable` implementations for various data types //! from `rustc_middle::ty` in no particular order. -use crate::ich::{NodeIdHashingMode, StableHashingContext}; +use crate::ich::StableHashingContext; use crate::middle::region; use crate::mir; use crate::ty; @@ -163,37 +163,3 @@ impl<'a> ToStableHashKey> for region::Scope { *self } } - -impl<'a> HashStable> for ty::TyVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // `TyVid` values are confined to an inference context and hence - // should not be hashed. - bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self) - } -} - -impl<'a> HashStable> for ty::IntVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // `IntVid` values are confined to an inference context and hence - // should not be hashed. - bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self) - } -} - -impl<'a> HashStable> for ty::FloatVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // `FloatVid` values are confined to an inference context and hence - // should not be hashed. - bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self) - } -} - -impl<'a> HashStable> for crate::middle::privacy::AccessLevels { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - let crate::middle::privacy::AccessLevels { ref map } = *self; - - map.hash_stable(hcx, hasher); - }); - } -} diff --git a/compiler/rustc_middle/src/ich/mod.rs b/compiler/rustc_middle/src/ich/mod.rs deleted file mode 100644 index c91b6a8540b..00000000000 --- a/compiler/rustc_middle/src/ich/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! ICH - Incremental Compilation Hash - -pub use self::hcx::{NodeIdHashingMode, StableHashingContext}; -use rustc_span::symbol::{sym, Symbol}; - -mod hcx; - -mod impls_hir; -mod impls_syntax; -mod impls_ty; - -pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ - sym::cfg, - sym::rustc_if_this_changed, - sym::rustc_then_this_would_need, - sym::rustc_dirty, - sym::rustc_clean, - sym::rustc_partition_reused, - sym::rustc_partition_codegened, - sym::rustc_expected_cgu_reuse, -]; diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index a11ca74b25e..f33bd3438b9 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -3,7 +3,9 @@ //! which are available for use externally when compiled as a library. use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; +use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_span::def_id::LocalDefId; use std::hash::Hash; @@ -53,3 +55,12 @@ impl Default for AccessLevels { AccessLevels { map: Default::default() } } } + +impl<'a> HashStable> for AccessLevels { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + let AccessLevels { ref map } = *self; + map.hash_stable(hcx, hasher); + }); + } +} diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 11c18a497e5..898a8caa3ca 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -10,12 +10,16 @@ doctest = false rustc_arena = { path = "../rustc_arena" } tracing = "0.1" rustc-rayon-core = "0.3.1" +rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_macros = { path = "../rustc_macros" } +rustc_feature = { path = "../rustc_feature" } +rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } +rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } parking_lot = "0.11" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs new file mode 100644 index 00000000000..d3e5189ce76 --- /dev/null +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -0,0 +1,209 @@ +use crate::ich; +use rustc_ast as ast; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::sync::Lrc; +use rustc_hir as hir; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::definitions::{DefPathHash, Definitions}; +use rustc_session::cstore::CrateStore; +use rustc_session::Session; +use rustc_span::source_map::SourceMap; +use rustc_span::symbol::Symbol; +use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData}; + +fn compute_ignored_attr_names() -> FxHashSet { + debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty()); + ich::IGNORED_ATTRIBUTES.iter().copied().collect() +} + +/// This is the context state available during incr. comp. hashing. It contains +/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., +/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various +/// things (e.g., each `DefId`/`DefPath` is only hashed once). +#[derive(Clone)] +pub struct StableHashingContext<'a> { + definitions: &'a Definitions, + cstore: &'a dyn CrateStore, + pub(super) body_resolver: BodyResolver<'a>, + hash_spans: bool, + hash_bodies: bool, + pub(super) node_id_hashing_mode: NodeIdHashingMode, + + // Very often, we are hashing something that does not need the + // `CachingSourceMapView`, so we initialize it lazily. + raw_source_map: &'a SourceMap, + caching_source_map: Option>, +} + +#[derive(PartialEq, Eq, Clone, Copy)] +pub enum NodeIdHashingMode { + Ignore, + HashDefPath, +} + +/// The `BodyResolver` allows mapping a `BodyId` to the corresponding `hir::Body`. +/// We could also just store a plain reference to the `hir::Crate` but we want +/// to avoid that the crate is used to get untracked access to all of the HIR. +#[derive(Clone, Copy)] +pub(super) struct BodyResolver<'tcx>(&'tcx hir::Crate<'tcx>); + +impl<'tcx> BodyResolver<'tcx> { + /// Returns a reference to the `hir::Body` with the given `BodyId`. + /// **Does not do any tracking**; use carefully. + pub(super) fn body(self, id: hir::BodyId) -> &'tcx hir::Body<'tcx> { + self.0.body(id) + } +} + +impl<'a> StableHashingContext<'a> { + /// The `krate` here is only used for mapping `BodyId`s to `Body`s. + /// Don't use it for anything else or you'll run the risk of + /// leaking data out of the tracking system. + #[inline] + fn new_with_or_without_spans( + sess: &'a Session, + krate: &'a hir::Crate<'a>, + definitions: &'a Definitions, + cstore: &'a dyn CrateStore, + always_ignore_spans: bool, + ) -> Self { + let hash_spans_initial = + !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans; + + StableHashingContext { + body_resolver: BodyResolver(krate), + definitions, + cstore, + caching_source_map: None, + raw_source_map: sess.source_map(), + hash_spans: hash_spans_initial, + hash_bodies: true, + node_id_hashing_mode: NodeIdHashingMode::HashDefPath, + } + } + + #[inline] + pub fn new( + sess: &'a Session, + krate: &'a hir::Crate<'a>, + definitions: &'a Definitions, + cstore: &'a dyn CrateStore, + ) -> Self { + Self::new_with_or_without_spans( + sess, + krate, + definitions, + cstore, + /*always_ignore_spans=*/ false, + ) + } + + #[inline] + pub fn ignore_spans( + sess: &'a Session, + krate: &'a hir::Crate<'a>, + definitions: &'a Definitions, + cstore: &'a dyn CrateStore, + ) -> Self { + let always_ignore_spans = true; + Self::new_with_or_without_spans(sess, krate, definitions, cstore, always_ignore_spans) + } + + #[inline] + pub fn while_hashing_hir_bodies(&mut self, hash_bodies: bool, f: F) { + let prev_hash_bodies = self.hash_bodies; + self.hash_bodies = hash_bodies; + f(self); + self.hash_bodies = prev_hash_bodies; + } + + #[inline] + pub fn while_hashing_spans(&mut self, hash_spans: bool, f: F) { + let prev_hash_spans = self.hash_spans; + self.hash_spans = hash_spans; + f(self); + self.hash_spans = prev_hash_spans; + } + + #[inline] + pub fn with_node_id_hashing_mode( + &mut self, + mode: NodeIdHashingMode, + f: F, + ) { + let prev = self.node_id_hashing_mode; + self.node_id_hashing_mode = mode; + f(self); + self.node_id_hashing_mode = prev; + } + + #[inline] + pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + if let Some(def_id) = def_id.as_local() { + self.local_def_path_hash(def_id) + } else { + self.cstore.def_path_hash(def_id) + } + } + + #[inline] + pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { + self.definitions.def_path_hash(def_id) + } + + #[inline] + pub fn hash_bodies(&self) -> bool { + self.hash_bodies + } + + #[inline] + pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { + match self.caching_source_map { + Some(ref mut sm) => sm, + ref mut none => { + *none = Some(CachingSourceMapView::new(self.raw_source_map)); + none.as_mut().unwrap() + } + } + } + + #[inline] + pub fn is_ignored_attr(&self, name: Symbol) -> bool { + thread_local! { + static IGNORED_ATTRIBUTES: FxHashSet = compute_ignored_attr_names(); + } + IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) + } +} + +impl<'a> HashStable> for ast::NodeId { + fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { + panic!("Node IDs should not appear in incremental state"); + } +} + +impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { + fn hash_spans(&self) -> bool { + self.hash_spans + } + + #[inline] + fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + self.def_path_hash(def_id) + } + + #[inline] + fn def_span(&self, def_id: LocalDefId) -> Span { + self.definitions.def_span(def_id) + } + + fn span_data_to_lines_and_cols( + &mut self, + span: &SpanData, + ) -> Option<(Lrc, usize, BytePos, usize, BytePos)> { + self.source_map().span_data_to_lines_and_cols(span) + } +} + +impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {} diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs new file mode 100644 index 00000000000..3c3e7e0d173 --- /dev/null +++ b/compiler/rustc_query_system/src/ich/impls_hir.rs @@ -0,0 +1,150 @@ +//! This module contains `HashStable` implementations for various HIR data +//! types in no particular order. + +use crate::ich::{NodeIdHashingMode, StableHashingContext}; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_hir as hir; +use rustc_hir::definitions::DefPathHash; +use smallvec::SmallVec; +use std::mem; + +impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { + #[inline] + fn hash_hir_id(&mut self, hir_id: hir::HirId, hasher: &mut StableHasher) { + let hcx = self; + match hcx.node_id_hashing_mode { + NodeIdHashingMode::Ignore => { + // Don't do anything. + } + NodeIdHashingMode::HashDefPath => { + let hir::HirId { owner, local_id } = hir_id; + + hcx.local_def_path_hash(owner).hash_stable(hcx, hasher); + local_id.hash_stable(hcx, hasher); + } + } + } + + fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) { + let hcx = self; + if hcx.hash_bodies() { + hcx.body_resolver.body(id).hash_stable(hcx, hasher); + } + } + + fn hash_reference_to_item(&mut self, id: hir::HirId, hasher: &mut StableHasher) { + let hcx = self; + + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + id.hash_stable(hcx, hasher); + }) + } + + fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) { + let hcx = self; + let hir::Mod { inner: ref inner_span, ref item_ids } = *module; + + inner_span.hash_stable(hcx, hasher); + + // Combining the `DefPathHash`s directly is faster than feeding them + // into the hasher. Because we use a commutative combine, we also don't + // have to sort the array. + let item_ids_hash = item_ids + .iter() + .map(|id| { + let def_path_hash = id.to_stable_hash_key(hcx); + def_path_hash.0 + }) + .fold(Fingerprint::ZERO, |a, b| a.combine_commutative(b)); + + item_ids.len().hash_stable(hcx, hasher); + item_ids_hash.hash_stable(hcx, hasher); + } + + fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) { + self.while_hashing_hir_bodies(true, |hcx| { + let hir::Expr { hir_id: _, ref span, ref kind } = *expr; + + span.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + }) + } + + fn hash_hir_ty(&mut self, ty: &hir::Ty<'_>, hasher: &mut StableHasher) { + self.while_hashing_hir_bodies(true, |hcx| { + let hir::Ty { hir_id: _, ref kind, ref span } = *ty; + + kind.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }) + } + + fn hash_hir_visibility_kind( + &mut self, + vis: &hir::VisibilityKind<'_>, + hasher: &mut StableHasher, + ) { + let hcx = self; + mem::discriminant(vis).hash_stable(hcx, hasher); + match *vis { + hir::VisibilityKind::Public | hir::VisibilityKind::Inherited => { + // No fields to hash. + } + hir::VisibilityKind::Crate(sugar) => { + sugar.hash_stable(hcx, hasher); + } + hir::VisibilityKind::Restricted { ref path, hir_id } => { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + hir_id.hash_stable(hcx, hasher); + }); + path.hash_stable(hcx, hasher); + } + } + } + + fn hash_hir_item_like(&mut self, f: F) { + let prev_hash_node_ids = self.node_id_hashing_mode; + self.node_id_hashing_mode = NodeIdHashingMode::Ignore; + + f(self); + + self.node_id_hashing_mode = prev_hash_node_ids; + } +} + +impl<'a> HashStable> for hir::Body<'_> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + let hir::Body { params, value, generator_kind } = self; + + hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| { + params.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + generator_kind.hash_stable(hcx, hasher); + }); + } +} + +impl<'a> HashStable> for hir::TraitCandidate { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + let hir::TraitCandidate { def_id, import_ids } = self; + + def_id.hash_stable(hcx, hasher); + import_ids.hash_stable(hcx, hasher); + }); + } +} + +impl<'a> ToStableHashKey> for hir::TraitCandidate { + type KeyType = (DefPathHash, SmallVec<[DefPathHash; 1]>); + + fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Self::KeyType { + let hir::TraitCandidate { def_id, import_ids } = self; + + ( + hcx.def_path_hash(*def_id), + import_ids.iter().map(|def_id| hcx.local_def_path_hash(*def_id)).collect(), + ) + } +} diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs new file mode 100644 index 00000000000..acf2990b643 --- /dev/null +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -0,0 +1,146 @@ +//! This module contains `HashStable` implementations for various data types +//! from `rustc_ast` in no particular order. + +use crate::ich::StableHashingContext; + +use rustc_ast as ast; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_span::{BytePos, NormalizedPos, SourceFile}; +use std::assert_matches::assert_matches; + +use smallvec::SmallVec; + +impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {} + +impl<'a> HashStable> for [ast::Attribute] { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + if self.is_empty() { + self.len().hash_stable(hcx, hasher); + return; + } + + // Some attributes are always ignored during hashing. + let filtered: SmallVec<[&ast::Attribute; 8]> = self + .iter() + .filter(|attr| { + !attr.is_doc_comment() + && !attr.ident().map_or(false, |ident| hcx.is_ignored_attr(ident.name)) + }) + .collect(); + + filtered.len().hash_stable(hcx, hasher); + for attr in filtered { + attr.hash_stable(hcx, hasher); + } + } +} + +impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> { + fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) { + // Make sure that these have been filtered out. + debug_assert!(!attr.ident().map_or(false, |ident| self.is_ignored_attr(ident.name))); + debug_assert!(!attr.is_doc_comment()); + + let ast::Attribute { kind, id: _, style, span } = attr; + if let ast::AttrKind::Normal(item, tokens) = kind { + item.hash_stable(self, hasher); + style.hash_stable(self, hasher); + span.hash_stable(self, hasher); + assert_matches!( + tokens.as_ref(), + None, + "Tokens should have been removed during lowering!" + ); + } else { + unreachable!(); + } + } +} + +impl<'a> HashStable> for SourceFile { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + let SourceFile { + name: _, // We hash the smaller name_hash instead of this + name_hash, + cnum, + // Do not hash the source as it is not encoded + src: _, + ref src_hash, + external_src: _, + start_pos, + end_pos: _, + ref lines, + ref multibyte_chars, + ref non_narrow_chars, + ref normalized_pos, + } = *self; + + (name_hash as u64).hash_stable(hcx, hasher); + + src_hash.hash_stable(hcx, hasher); + + // We only hash the relative position within this source_file + lines.len().hash_stable(hcx, hasher); + for &line in lines.iter() { + stable_byte_pos(line, start_pos).hash_stable(hcx, hasher); + } + + // We only hash the relative position within this source_file + multibyte_chars.len().hash_stable(hcx, hasher); + for &char_pos in multibyte_chars.iter() { + stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher); + } + + non_narrow_chars.len().hash_stable(hcx, hasher); + for &char_pos in non_narrow_chars.iter() { + stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher); + } + + normalized_pos.len().hash_stable(hcx, hasher); + for &char_pos in normalized_pos.iter() { + stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher); + } + + cnum.hash_stable(hcx, hasher); + } +} + +fn stable_byte_pos(pos: BytePos, source_file_start: BytePos) -> u32 { + pos.0 - source_file_start.0 +} + +fn stable_multibyte_char(mbc: rustc_span::MultiByteChar, source_file_start: BytePos) -> (u32, u32) { + let rustc_span::MultiByteChar { pos, bytes } = mbc; + + (pos.0 - source_file_start.0, bytes as u32) +} + +fn stable_non_narrow_char( + swc: rustc_span::NonNarrowChar, + source_file_start: BytePos, +) -> (u32, u32) { + let pos = swc.pos(); + let width = swc.width(); + + (pos.0 - source_file_start.0, width as u32) +} + +fn stable_normalized_pos(np: NormalizedPos, source_file_start: BytePos) -> (u32, u32) { + let NormalizedPos { pos, diff } = np; + + (pos.0 - source_file_start.0, diff) +} + +impl<'tcx> HashStable> for rustc_feature::Features { + fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { + // Unfortunately we cannot exhaustively list fields here, since the + // struct is macro generated. + self.declared_lang_features.hash_stable(hcx, hasher); + self.declared_lib_features.hash_stable(hcx, hasher); + + self.walk_feature_fields(|feature_name, value| { + feature_name.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + }); + } +} diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs new file mode 100644 index 00000000000..54416902e5f --- /dev/null +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -0,0 +1,19 @@ +//! ICH - Incremental Compilation Hash + +pub use self::hcx::{NodeIdHashingMode, StableHashingContext}; +use rustc_span::symbol::{sym, Symbol}; + +mod hcx; +mod impls_hir; +mod impls_syntax; + +pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ + sym::cfg, + sym::rustc_if_this_changed, + sym::rustc_then_this_would_need, + sym::rustc_dirty, + sym::rustc_clean, + sym::rustc_partition_reused, + sym::rustc_partition_codegened, + sym::rustc_expected_cgu_reuse, +]; diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index c205f0fb531..bc23de069b0 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(assert_matches)] #![feature(bool_to_option)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] @@ -14,4 +15,5 @@ extern crate rustc_macros; pub mod cache; pub mod dep_graph; +pub mod ich; pub mod query; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index d5f887f935b..6c86f86ecd9 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,4 +1,5 @@ #![feature(crate_visibility_modifier)] +#![feature(min_specialization)] #![feature(once_cell)] #![recursion_limit = "256"] -- cgit 1.4.1-3-g733a5 From b2ed9c4007767f6cf692229cffd471d4ce5fde55 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 3 Oct 2021 16:07:26 +0200 Subject: Add some inlining. --- compiler/rustc_query_system/src/ich/hcx.rs | 3 +++ compiler/rustc_query_system/src/ich/impls_hir.rs | 5 +++++ compiler/rustc_session/src/cstore.rs | 4 ++++ 3 files changed, 12 insertions(+) (limited to 'compiler/rustc_session') diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index d3e5189ce76..f2e935c59fc 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -178,12 +178,14 @@ impl<'a> StableHashingContext<'a> { } impl<'a> HashStable> for ast::NodeId { + #[inline] fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { panic!("Node IDs should not appear in incremental state"); } } impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { + #[inline] fn hash_spans(&self) -> bool { self.hash_spans } @@ -198,6 +200,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { self.definitions.def_span(def_id) } + #[inline] fn span_data_to_lines_and_cols( &mut self, span: &SpanData, diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs index 3c3e7e0d173..04eb263a977 100644 --- a/compiler/rustc_query_system/src/ich/impls_hir.rs +++ b/compiler/rustc_query_system/src/ich/impls_hir.rs @@ -26,6 +26,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } + #[inline] fn hash_body_id(&mut self, id: hir::BodyId, hasher: &mut StableHasher) { let hcx = self; if hcx.hash_bodies() { @@ -33,6 +34,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } + #[inline] fn hash_reference_to_item(&mut self, id: hir::HirId, hasher: &mut StableHasher) { let hcx = self; @@ -41,6 +43,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { }) } + #[inline] fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) { let hcx = self; let hir::Mod { inner: ref inner_span, ref item_ids } = *module; @@ -103,6 +106,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } + #[inline] fn hash_hir_item_like(&mut self, f: F) { let prev_hash_node_ids = self.node_id_hashing_mode; self.node_id_hashing_mode = NodeIdHashingMode::Ignore; @@ -114,6 +118,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } impl<'a> HashStable> for hir::Body<'_> { + #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { params, value, generator_kind } = self; diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 4b93a3e8e83..9d6bd201039 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -28,6 +28,7 @@ pub struct CrateSource { } impl CrateSource { + #[inline] pub fn paths(&self) -> impl Iterator { self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0) } @@ -47,6 +48,7 @@ pub enum CrateDepKind { } impl CrateDepKind { + #[inline] pub fn macros_only(self) -> bool { match self { CrateDepKind::MacrosOnly => true, @@ -122,10 +124,12 @@ impl ExternCrate { /// If true, then this crate is the crate named by the extern /// crate referenced above. If false, then this crate is a dep /// of the crate. + #[inline] pub fn is_direct(&self) -> bool { self.dependency_of == LOCAL_CRATE } + #[inline] pub fn rank(&self) -> impl PartialOrd { // Prefer: // - direct extern crate to indirect -- cgit 1.4.1-3-g733a5