Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4387,6 +4387,7 @@ dependencies = [
"rustc_target",
"tempfile",
"tracing",
"twox-hash 2.1.2",
]

[[package]]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let nodes = hir::OwnerNodes { opt_hash: bodies_hash, nodes, bodies };
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };

let opt_hash = self.tcx.needs_hir_hash().then(|| {
let opt_hash = self.tcx.needs_owner_info_hash().then(|| {
self.tcx.with_stable_hashing_context(|mut hcx| {
let mut stable_hasher = StableHasher::new();
bodies_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_crate_store/src/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

use std::any::Any;
use std::path::PathBuf;
use std::sync::OnceLock;

use rustc_abi::ExternAbi;
use rustc_attr_ir::{CfgEntry, PeImportNameType};
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock};
use rustc_hir_id::definitions::{DefKey, DefPath, Definitions};
use rustc_macros::{BlobDecodable, Decodable, Encodable, StableHash};
Expand Down Expand Up @@ -220,6 +222,8 @@ pub struct Untracked {
pub definitions: FreezeLock<Definitions>,
/// The interned [StableCrateId]s.
pub stable_crate_ids: FreezeLock<StableCrateIdMap>,
/// The hash of the local crate as computed in metadata encoding.
pub local_crate_hash: OnceLock<Svh>,
}

impl Untracked {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_data_structures/src/svh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ impl Svh {
pub fn to_hex(self) -> String {
format!("{:032x}", self.hash.as_u128())
}

pub fn as_fingerprint(self) -> Fingerprint {
self.hash
}
}

impl fmt::Display for Svh {
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))

tcx.ensure_ok().analysis(());

if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
dump_feature_usage_metrics(tcx, metrics_dir);
}

if callbacks.after_analysis(compiler, tcx) == Compilation::Stop {
return None;
}
Expand All @@ -331,6 +327,10 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))

let linker = Linker::codegen_and_build_linker(tcx, codegen_backend);

if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
dump_feature_usage_metrics(tcx, metrics_dir);
}

tcx.report_unused_features();

Some(linker)
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,16 @@ impl<'tcx> OwnerInfo<'tcx> {
pub fn node(&self) -> OwnerNode<'tcx> {
self.nodes.node()
}

// A fingerprint that identifies the contents of the OwnerInfo.
// It only depends on `nodes` and `attrs` because `parenting` and `trait_map` are
// deterministically calculated from `nodes` and `attrs`.
#[inline]
pub fn fingerprint(&self) -> Fingerprint {
let body = self.nodes.opt_hash.expect("HIR hash requested without needs_hir_hash");
let attrs = self.attrs.opt_hash.expect("HIR hash requested without needs_hir_hash");
body.combine(attrs)
}
}

#[derive(Copy, Clone, Debug, StableHash)]
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,8 +966,13 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
let definitions = FreezeLock::new(Definitions::new(stable_crate_id));

let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
let untracked =
Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions, stable_crate_ids };
let untracked = Untracked {
cstore,
source_span: AppendOnlyIndexVec::new(),
definitions,
stable_crate_ids,
local_crate_hash: OnceLock::new(),
};

// We're constructing the HIR here; we don't care what we will
// read, since we haven't even constructed the *input* to
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_metadata/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ rustc_structures = { path = "../rustc_structures" }
rustc_target = { path = "../rustc_target" }
tempfile = "3.7.1"
tracing = "0.1"
twox-hash = { version = "2", default-features = false, features = ["xxhash3_128", "std"] }
# tidy-alphabetical-end

[target.'cfg(target_os = "aix")'.dependencies]
Expand Down
39 changes: 33 additions & 6 deletions compiler/rustc_metadata/src/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ enum CrateOrigin<'a> {
parent_private: bool,
/// Dependency info about this crate.
dep: &'a CrateDep,
/// The dependency's `-C extra-filename`, used to narrow the search for it on disk. Stored
/// separately from `dep` because it is encoded outside the hashed crate root; see
/// `CrateRootUnhashed::dep_extra_filenames`.
dep_extra_filename: &'a str,
},
/// Injected by `rustc`.
Injected,
Expand All @@ -179,6 +183,14 @@ impl<'a> CrateOrigin<'a> {
}
}

/// Return the dependency's `-C extra-filename`, if any.
fn dep_extra_filename(&self) -> Option<&'a str> {
match self {
CrateOrigin::IndirectDependency { dep_extra_filename, .. } => Some(dep_extra_filename),
_ => None,
}
}

/// `Some(true)` if the dependency is private or its parent is private, `Some(false)` if the
/// dependency is not private, `None` if it could not be determined.
fn private_dep(&self) -> Option<bool> {
Expand Down Expand Up @@ -592,7 +604,8 @@ impl CStore {

let Library { source, metadata } = lib;
let crate_root = metadata.get_root();
let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
let unhashed = metadata.get_root_unhashed();
let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_crate_hash());
let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep);

// Claim this crate number and cache it
Expand Down Expand Up @@ -645,6 +658,7 @@ impl CStore {
tcx,
metadata,
crate_root,
unhashed,
raw_proc_macros,
cnum,
cnum_map,
Expand Down Expand Up @@ -787,7 +801,7 @@ impl CStore {
let dep = origin.dep();
let hash = dep.map(|d| d.hash);
let host_hash = dep.map(|d| d.host_hash).flatten();
let extra_filename = dep.map(|d| &d.extra_filename[..]);
let extra_filename = origin.dep_extra_filename();
let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate };
let private_dep = origin.private_dep();

Expand Down Expand Up @@ -868,10 +882,11 @@ impl CStore {
// against a hash, we could load a crate which has the same hash
// as an already loaded crate. If this is the case prevent
// duplicates by just using the first crate.
let root = library.metadata.get_root();
let root_name = library.metadata.get_root().name();
let root_hash = library.metadata.get_crate_hash();
let mut result = LoadResult::Loaded(library);
for (cnum, data) in self.iter_crate_data() {
if data.name() == root.name() && root.hash() == data.hash() {
if data.name() == root_name && data.hash() == root_hash {
assert!(locator.hash.is_none());
info!("load success, going to previous cnum: {}", cnum);
result = LoadResult::Previous(cnum);
Expand Down Expand Up @@ -905,15 +920,26 @@ impl CStore {
// We map 0 and all other holes in the map to our parent crate. The "additional"
// self-dependencies should be harmless.
let deps = crate_root.decode_crate_deps(metadata);
// Encoded outside the hashed crate root; see `CrateRootUnhashed::dep_extra_filenames`.
// Holds one entry per dep after the unused `LOCAL_CRATE` slot, so it lines up with `deps`
// once that slot is skipped.
let dep_extra_filenames = metadata.get_dep_extra_filenames();
assert_eq!(
dep_extra_filenames.len(),
deps.len() + 1,
"expected one dep_extra_filename per crate dep, plus the unused LOCAL_CRATE slot",
);
let mut crate_num_map = CrateNumMap::with_capacity(1 + deps.len());
crate_num_map.push(krate);
for dep in deps {
for (dep, dep_extra_filename) in
deps.zip(dep_extra_filenames.iter().skip(1).map(String::as_str))
{
info!(
"resolving dep `{}`->`{}` hash: `{}` extra filename: `{}` private {}",
crate_root.name(),
dep.name,
dep.hash,
dep.extra_filename,
dep_extra_filename,
dep.is_private,
);
let dep_kind = match dep_kind {
Expand All @@ -928,6 +954,7 @@ impl CStore {
dep_root_for_errors,
parent_private: parent_is_private,
dep: &dep,
dep_extra_filename,
},
)?;
crate_num_map.push(cnum);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ impl<'a> CrateLocator<'a> {
return None;
}

let hash = header.hash;
let hash = metadata.get_crate_hash();
if let Some(expected_hash) = self.hash {
if hash != expected_hash {
info!("Rejecting via hash: expected {} got {}", expected_hash, hash);
Expand Down
51 changes: 38 additions & 13 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ pub(crate) struct CrateMetadata {
// --- Some data pre-decoded from the metadata blob, usually for performance ---
/// Data about the top-level items in a crate, as well as various crate-level metadata.
root: CrateRoot,
/// Crate-level metadata that is not in the SVH.
unhashed: CrateRootUnhashed,
/// Trait impl data.
/// FIXME: Used only from queries and can use query cache,
/// so pre-decoding can probably be avoided.
Expand Down Expand Up @@ -717,8 +719,7 @@ impl MetadataBlob {
}

let found_version =
LazyValue::<String>::from_position(NonZero::new(METADATA_HEADER.len() + 8).unwrap())
.decode(self);
LazyValue::<String>::from_position(NonZero::new(VERSION_OFFSET).unwrap()).decode(self);
if rustc_version(cfg_version) != found_version {
return Err(Some(found_version));
}
Expand All @@ -727,8 +728,13 @@ impl MetadataBlob {
}

fn root_pos(&self) -> NonZero<usize> {
let offset = METADATA_HEADER.len();
let pos_bytes = self[offset..][..8].try_into().unwrap();
let pos_bytes = self[ROOT_POS_OFFSET..][..8].try_into().unwrap();
let pos = u64::from_le_bytes(pos_bytes);
NonZero::new(pos as usize).unwrap()
}

fn unhashed_pos(&self) -> NonZero<usize> {
let pos_bytes = self[UNHASHED_POS_OFFSET..][..8].try_into().unwrap();
let pos = u64::from_le_bytes(pos_bytes);
NonZero::new(pos as usize).unwrap()
}
Expand All @@ -743,12 +749,28 @@ impl MetadataBlob {
LazyValue::<CrateRoot>::from_position(pos).decode(self)
}

pub(crate) fn get_root_unhashed(&self) -> CrateRootUnhashed {
let pos = self.unhashed_pos();
LazyValue::<CrateRootUnhashed>::from_position(pos).decode(self)
}

pub(crate) fn get_dep_extra_filenames(&self) -> IndexVec<CrateNum, String> {
self.get_root_unhashed().dep_extra_filenames
}

pub(crate) fn get_crate_hash(&self) -> Svh {
let bytes: [u8; CRATE_HASH_LEN] =
self[CRATE_HASH_OFFSET..][..CRATE_HASH_LEN].try_into().unwrap();
Svh::new(Fingerprint::from_le_bytes(bytes))
}

pub(crate) fn list_crate_metadata(
&self,
out: &mut dyn io::Write,
ls_kinds: &[String],
) -> io::Result<()> {
let root = self.get_root();
let extra_filename = self.get_root_unhashed().extra_filename;

let all_ls_kinds = vec![
"root".to_owned(),
Expand All @@ -763,11 +785,11 @@ impl MetadataBlob {
match &**kind {
"root" => {
writeln!(out, "Crate info:")?;
writeln!(out, "name {}{}", root.name(), root.extra_filename)?;
writeln!(out, "name {}{}", root.name(), extra_filename)?;
writeln!(
out,
"hash {} stable_crate_id {:?}",
root.hash(),
self.get_crate_hash(),
root.stable_crate_id
)?;
writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
Expand Down Expand Up @@ -801,10 +823,15 @@ impl MetadataBlob {
writeln!(out, "=External Dependencies=")?;
let dylib_dependency_formats =
root.dylib_dependency_formats.decode(self).collect::<Vec<_>>();
// `extra_filename` is stored outside the hashed root; see
// `CrateRootUnhashed::dep_extra_filenames`.
let dep_extra_filenames = self.get_dep_extra_filenames();
for (i, dep) in root.crate_deps.decode(self).enumerate() {
let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } =
dep;
let CrateDep { name, hash, host_hash, kind, is_private } = dep;
let number = i + 1;
let extra_filename = dep_extra_filenames
.get(CrateNum::new(number))
.map_or("", |name| name.as_str());

writeln!(
out,
Expand Down Expand Up @@ -975,10 +1002,6 @@ impl CrateRoot {
self.header.name
}

pub(crate) fn hash(&self) -> Svh {
self.header.hash
}

pub(crate) fn stable_crate_id(&self) -> StableCrateId {
self.stable_crate_id
}
Expand Down Expand Up @@ -1944,6 +1967,7 @@ impl CrateMetadata {
tcx: TyCtxt<'_>,
blob: MetadataBlob,
root: CrateRoot,
unhashed: CrateRootUnhashed,
raw_proc_macros: Option<&'static [ProcMacroClient]>,
cnum: CrateNum,
cnum_map: CrateNumMap,
Expand All @@ -1967,6 +1991,7 @@ impl CrateMetadata {
let mut cdata = CrateMetadata {
blob,
root,
unhashed,
trait_impls,
incoherent_impls: Default::default(),
raw_proc_macros,
Expand Down Expand Up @@ -2108,7 +2133,7 @@ impl CrateMetadata {
}

pub(crate) fn hash(&self) -> Svh {
self.root.header.hash
self.blob.get_crate_hash()
}

pub(crate) fn has_async_drops(&self) -> bool {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,12 +377,12 @@ provide! { tcx, def_id, other, cdata,
}
native_libraries => { cdata.get_native_libraries(tcx).collect() }
foreign_modules => { cdata.get_foreign_modules(tcx).map(|m| (m.def_id, m)).collect() }
crate_hash => { cdata.root.header.hash }
crate_hash => { cdata.hash() }
crate_host_hash => { cdata.host_hash }
crate_name => { cdata.root.header.name }
num_extern_def_ids => { cdata.num_def_ids() }

extra_filename => { cdata.root.extra_filename.clone() }
extra_filename => { cdata.unhashed.extra_filename.clone() }

traits => { tcx.arena.alloc_from_iter(cdata.get_traits(tcx)) }
trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls(tcx)) }
Expand Down
Loading
Loading