diff --git a/compiler/rustc_data_structures/src/stable_hash.rs b/compiler/rustc_data_structures/src/stable_hash.rs index 8e7ca5a75d861..a270a87e7ea7e 100644 --- a/compiler/rustc_data_structures/src/stable_hash.rs +++ b/compiler/rustc_data_structures/src/stable_hash.rs @@ -5,6 +5,7 @@ use std::num::NonZero; use rustc_index::bit_set::{self, DenseBitSet}; use rustc_index::{Idx, IndexSlice, IndexVec}; +use rustc_macros::StableHash; use smallvec::SmallVec; use thin_vec::ThinVec; @@ -37,6 +38,25 @@ pub trait StableHashCtxt { fn assert_default_stable_hash_controls(&self, msg: &str); } +/// Dummy impl of [`StableHashCtxt`], for code that can't provide a real context, +/// and only wants to compute stable hashes for types that don't rely on the context. +pub struct DummyStableHashCtxt; + +impl StableHashCtxt for DummyStableHashCtxt { + fn stable_hash_span(&mut self, _span: RawSpan, _hasher: &mut StableHasher) { + unimplemented!() + } + fn def_path_hash(&self, _def_id: RawDefId) -> Fingerprint { + unimplemented!() + } + fn stable_hash_controls(&self) -> StableHashControls { + unimplemented!() + } + fn assert_default_stable_hash_controls(&self, _msg: &str) { + unimplemented!() + } +} + // A type used to work around `Span` not being visible in this crate. It is the same size as // `Span` but has a different alignment. pub struct RawSpan(pub u64); @@ -575,8 +595,84 @@ impl StableHash for bit_set::BitMatrix { impl_stable_traits_for_trivial_type!(::std::ffi::OsStr); -impl_stable_traits_for_trivial_type!(::std::path::Path); -impl_stable_traits_for_trivial_type!(::std::path::PathBuf); +impl StableHash for std::path::Path { + fn stable_hash(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { + use std::path::{Component, Prefix}; + + #[derive(StableHash)] + enum Tag { + PrefixVerbatim, + PrefixVerbatimUNC, + PrefixVerbatimDisk, + PrefixDeviceNS, + PrefixUNC, + PrefixDisk, + RootDir, + CurDir, + ParentDir, + Normal, + } + + for component in self.components() { + match component { + Component::Prefix(prefix) => match prefix.kind() { + Prefix::Verbatim(os_str) => { + Tag::PrefixVerbatim.stable_hash(hcx, hasher); + os_str.stable_hash(hcx, hasher); + } + Prefix::VerbatimUNC(host, share) => { + Tag::PrefixVerbatimUNC.stable_hash(hcx, hasher); + host.stable_hash(hcx, hasher); + share.stable_hash(hcx, hasher); + } + Prefix::VerbatimDisk(letter) => { + Tag::PrefixVerbatimDisk.stable_hash(hcx, hasher); + letter.stable_hash(hcx, hasher); + } + Prefix::DeviceNS(os_str) => { + Tag::PrefixDeviceNS.stable_hash(hcx, hasher); + os_str.stable_hash(hcx, hasher); + } + Prefix::UNC(host, share) => { + Tag::PrefixUNC.stable_hash(hcx, hasher); + host.stable_hash(hcx, hasher); + share.stable_hash(hcx, hasher); + } + Prefix::Disk(letter) => { + Tag::PrefixDisk.stable_hash(hcx, hasher); + letter.stable_hash(hcx, hasher); + } + }, + Component::RootDir => Tag::RootDir.stable_hash(hcx, hasher), + Component::CurDir => Tag::CurDir.stable_hash(hcx, hasher), + Component::ParentDir => Tag::ParentDir.stable_hash(hcx, hasher), + Component::Normal(os_str) => { + Tag::Normal.stable_hash(hcx, hasher); + os_str.stable_hash(hcx, hasher); + } + } + } + } +} + +impl StableOrd for std::path::Path { + /// FIXME(Zalathar): Unstably sorting paths is pre-existing behavior, but potentially wrong. + const CAN_USE_UNSTABLE_SORT: bool = true; + /// Stdlib path sorting should (hopefully) not change. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); +} + +impl StableHash for std::path::PathBuf { + fn stable_hash(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { + self.as_path().stable_hash(hcx, hasher); + } +} + +impl StableOrd for std::path::PathBuf { + const CAN_USE_UNSTABLE_SORT: bool = ::CAN_USE_UNSTABLE_SORT; + /// Stdlib path sorting should (hopefully) not change. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); +} // It is not safe to implement StableHash for HashSet, HashMap or any other collection type // with unstable but observable iteration order. diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 7e274c66f6f75..2ccdbcf9bea18 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3370,7 +3370,7 @@ pub(crate) mod dep_tracking { use rustc_abi::Align; use rustc_ast::attr::version::RustcVersion; use rustc_data_structures::fx::FxIndexMap; - use rustc_data_structures::stable_hash::StableHasher; + use rustc_data_structures::stable_hash::{DummyStableHashCtxt, StableHash, StableHasher}; use rustc_errors::LanguageIdentifier; use rustc_feature::UnstableFeatures; use rustc_hashes::Hash64; @@ -3433,73 +3433,73 @@ pub(crate) mod dep_tracking { } impl_dep_tracking_hash_via_hash!( + // tidy-alphabetical-start (), + Align, AnnotateMoves, AutoDiff, - Offload, - bool, - usize, - NonZero, - u64, - Hash64, - String, - PathBuf, - lint::Level, - WasiExecModel, - u32, - FramePointer, - RelocModel, + BranchProtection, + CFGuard, + CFProtection, CodeModel, - TlsModel, - InstrumentCoverage, + CodegenRetagOptions, + CollapseMacroDebuginfo, CoverageOptions, + CrateType, + DebugInfo, + DebugInfoCompression, + Edition, + FmtDebug, + FramePointer, + FunctionReturn, + Hash64, + InliningThreshold, + InstrumentCoverage, InstrumentMcount, InstrumentMcountOpts, InstrumentXRay, - CrateType, + LanguageIdentifier, + LinkerPluginLto, + LocationDetail, + LtoCli, MergeFunctions, + MirStripDebugInfo, + NativeLib, + NextSolverConfig, + NonZero, + Offload, OnBrokenPipe, + OptLevel, + OutFileName, + OutputType, PanicStrategy, + PatchableFunctionEntry, + PointerAuthOption, + Polonius, + RelocModel, RelroLevel, - OptLevel, - LtoCli, - DebugInfo, - DebugInfoCompression, - MirStripDebugInfo, - CollapseMacroDebuginfo, - UnstableFeatures, - NativeLib, - SanitizerSet, - CFGuard, - CFProtection, - TargetTuple, - Edition, - LinkerPluginLto, + RemapPathScopeComponents, ResolveDocLinks, + RustcVersion, + SanitizerSet, + SourceFileHashAlgorithm, SplitDebuginfo, SplitDwarfKind, StackProtector, + String, SwitchWithOptPath, SymbolManglingVersion, SymbolVisibility, - RemapPathScopeComponents, - SourceFileHashAlgorithm, - OutFileName, - OutputType, - RealFileName, - LocationDetail, - FmtDebug, - BranchProtection, - LanguageIdentifier, - NextSolverConfig, - PatchableFunctionEntry, - Polonius, - InliningThreshold, - FunctionReturn, - Align, - CodegenRetagOptions, - RustcVersion, - PointerAuthOption, + TargetTuple, + TlsModel, + UnstableFeatures, + WasiExecModel, + bool, + lint::Level, + u32, + u64, + usize, + // tidy-alphabetical-end ); impl DepTrackingHash for (T1, T2) @@ -3588,6 +3588,28 @@ pub(crate) mod dep_tracking { } } + impl DepTrackingHash for PathBuf { + fn hash( + &self, + hasher: &mut StableHasher, + _error_format: ErrorOutputType, + _for_crate_hash: bool, + ) { + self.stable_hash(&mut DummyStableHashCtxt, hasher); + } + } + + impl DepTrackingHash for RealFileName { + fn hash( + &self, + hasher: &mut StableHasher, + _error_format: ErrorOutputType, + _for_crate_hash: bool, + ) { + self.stable_hash(&mut DummyStableHashCtxt, hasher); + } + } + // This is a stable hash because BTreeMap is a sorted container pub(crate) fn stable_hash( sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>, diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f69efebf5c950..64e6670e3e6ed 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -32,7 +32,7 @@ // this crate without this line making `rustc_span` available. extern crate self as rustc_span; -use rustc_data_structures::stable_hash::StableHashCtxt; +use rustc_data_structures::stable_hash::{DummyStableHashCtxt, StableHashCtxt}; use rustc_data_structures::{AtomicRef, outline}; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_serialize::opaque::mem_encoder::MemEncoder; @@ -315,7 +315,7 @@ pub struct RealFileName { /// The inner workings of `RealFileName`. /// /// It contains the `name`, `working_directory` and `embeddable_name` components. -#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable, Hash)] +#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, StableHash, Decodable, Encodable)] struct InnerRealFileName { /// The name. name: PathBuf, @@ -325,18 +325,18 @@ struct InnerRealFileName { embeddable_name: PathBuf, } -impl Hash for RealFileName { - #[inline] - fn hash(&self, state: &mut H) { +impl StableHash for RealFileName { + fn stable_hash(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { + let RealFileName { local, maybe_remapped, scopes } = self; // To prevent #70924 from happening again we should only hash the // remapped path if that exists. This is because remapped paths to // sysroot crates (/rust/$hash or /rust/$version) remain stable even // if the corresponding local path changes. if !self.was_fully_remapped() { - self.local.hash(state); + local.stable_hash(hcx, hasher); } - self.maybe_remapped.hash(state); - self.scopes.bits().hash(state); + maybe_remapped.stable_hash(hcx, hasher); + scopes.bits().stable_hash(hcx, hasher); } } @@ -505,7 +505,7 @@ impl RealFileName { } /// Differentiates between real files and common virtual files. -#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, Decodable, Encodable)] +#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, StableHash, Decodable, Encodable)] pub enum FileName { Real(RealFileName), /// Strings provided as `--cfg [cfgspec]`. @@ -2160,8 +2160,8 @@ impl StableSourceFileId { stable_crate_id: Option, ) -> Self { let mut hasher = StableHasher::new(); - filename.hash(&mut hasher); - stable_crate_id.hash(&mut hasher); + filename.stable_hash(&mut DummyStableHashCtxt, &mut hasher); + stable_crate_id.stable_hash(&mut DummyStableHashCtxt, &mut hasher); StableSourceFileId(hasher.finish()) } } diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index 5790c3cce2606..db0f046d72811 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{LocalDefId, LocalModId}; use rustc_hir::{Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; -use rustc_span::{FileName, Span}; +use rustc_span::{Span, StableSourceFileId}; use std::collections::hash_map::Entry; declare_clippy_lint! { @@ -63,7 +63,7 @@ impl MultipleInherentImpl { #[derive(Hash, Eq, PartialEq, Clone)] enum Criterion { Module(LocalModId), - File(FileName), + File(StableSourceFileId), Crate, } @@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { InherentImplLintScope::Module => Criterion::Module(cx.tcx.parent_module(hir_id)), InherentImplLintScope::File => { let span = cx.tcx.hir_span(hir_id); - Criterion::File(cx.tcx.sess.source_map().lookup_source_file(span.lo()).name.clone()) + Criterion::File(cx.tcx.sess.source_map().lookup_source_file(span.lo()).stable_id) }, InherentImplLintScope::Crate => Criterion::Crate, };