diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 00136ac4a5748..539b599cb0ada 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -305,7 +305,7 @@ fn produce_final_output_artifacts( // for single cgu file is renamed to drop cgu specific suffix // so we regenerate it the same way let path = crate_output.path(ty); - sess.dcx().emit_artifact_notification(path.as_path(), descr); + sess.dcx().emit_artifact_notification(path.as_path(), descr, None); } }); } else { @@ -313,7 +313,7 @@ fn produce_final_output_artifacts( module.for_each_output(|path, ty| { if sess.opts.output_types.contains_key(&ty) { let descr = ty.shorthand(); - sess.dcx().emit_artifact_notification(&path, descr); + sess.dcx().emit_artifact_notification(&path, descr, None); } }); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8de68925cabbc..d0f1854848d3a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -152,7 +152,7 @@ pub fn link_binary( } } if sess.opts.json_artifact_notifications { - sess.dcx().emit_artifact_notification(&out_filename, "link"); + sess.dcx().emit_artifact_notification(&out_filename, "link", None); } if sess.prof.enabled() diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 0fd4ed8475b49..dbb1e6b69df3c 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -719,7 +719,7 @@ fn produce_final_output_artifacts( // for single cgu file is renamed to drop cgu specific suffix // so we regenerate it the same way let path = crate_output.path(ty); - sess.dcx().emit_artifact_notification(path.as_path(), descr); + sess.dcx().emit_artifact_notification(path.as_path(), descr, None); } }); } else { @@ -727,7 +727,7 @@ fn produce_final_output_artifacts( module.for_each_output(|path, ty| { if sess.opts.output_types.contains_key(&ty) { let descr = ty.shorthand(); - sess.dcx().emit_artifact_notification(&path, descr); + sess.dcx().emit_artifact_notification(&path, descr, None); } }); } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index fe01e289334cc..aa52674898e6a 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -175,7 +175,13 @@ pub trait Emitter: Translate { /// Emit a notification that an artifact has been output. /// Currently only supported for the JSON format. - fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {} + fn emit_artifact_notification( + &mut self, + _path: &Path, + _artifact_type: &str, + _api_hash: Option<&str>, + ) { + } /// Emit a report about future breakage. /// Currently only supported for the JSON format. diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index a6583407b7e7e..6835eef61d083 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -127,8 +127,13 @@ impl Emitter for JsonEmitter { } } - fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { - let data = ArtifactNotification { artifact: path, emit: artifact_type }; + fn emit_artifact_notification( + &mut self, + path: &Path, + artifact_type: &str, + api_hash: Option<&str>, + ) { + let data = ArtifactNotification { artifact: path, emit: artifact_type, api_hash }; let result = self.emit(EmitTyped::Artifact(data)); if let Err(e) = result { panic!("failed to print notification: {e:?}"); @@ -261,6 +266,7 @@ struct ArtifactNotification<'a> { artifact: &'a Path, /// What kind of artifact we're emitting. emit: &'a str, + api_hash: Option<&'a str>, } #[derive(Serialize)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index c0c5dba46772a..53e6677c149d5 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1142,8 +1142,13 @@ impl<'a> DiagCtxtHandle<'a> { self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors) } - pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { - self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); + pub fn emit_artifact_notification( + &self, + path: &Path, + artifact_type: &str, + api_hash: Option<&str>, + ) { + self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type, api_hash); } pub fn emit_future_breakage_report(&self) { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index fde1872fb399e..9501f6ad2578a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -655,7 +655,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P match result { Ok(_) => { if sess.opts.json_artifact_notifications { - sess.dcx().emit_artifact_notification(deps_filename, "dep-info"); + sess.dcx().emit_artifact_notification(deps_filename, "dep-info", None); } } Err(error) => { diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 1c3222bbfeb61..0d5349ea73cbe 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -838,7 +838,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let mut result = LoadResult::Loaded(library); for (cnum, data) in self.cstore.iter_crate_data() { if data.name() == root.name() && root.hash() == data.hash() { - assert!(locator.hash.is_none()); + //assert!(locator.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); result = LoadResult::Previous(cnum); break; diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index c4e1e0f1d1a99..b6d856487ce94 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -1,8 +1,13 @@ +use std::ops::Deref as _; use std::path::{Path, PathBuf}; use std::{fs, io}; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_middle::ty::TyCtxt; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::LocalDefId; +use rustc_middle::ty::{InstanceKind, TyCtxt}; use rustc_session::config::{CrateType, OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; use rustc_session::{MetadataKind, Session}; @@ -40,6 +45,7 @@ pub fn emit_wrapper_file( pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { let out_filename = filename_for_metadata(tcx.sess, tcx.output_filenames(())); + //let hash = tcx.crate_hash() // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its // final destination, with an `fs::rename` call. In order for the rename to @@ -104,7 +110,12 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { } }; if tcx.sess.opts.json_artifact_notifications { - tcx.dcx().emit_artifact_notification(out_filename.as_path(), "metadata"); + let hash = public_api_hash(tcx); + tcx.dcx().emit_artifact_notification( + out_filename.as_path(), + "metadata", + Some(&hash.to_string()), + ); } (filename, None) } else { @@ -147,3 +158,87 @@ pub fn copy_to_stdout(from: &Path) -> io::Result<()> { io::copy(&mut reader, &mut stdout)?; Ok(()) } + +fn public_api_hash(tcx: TyCtxt<'_>) -> Fingerprint { + let mut stable_hasher = StableHasher::new(); + tcx.with_stable_hashing_context(|mut hcx| { + hcx.while_hashing_spans(false, |mut hcx| { + let _ = tcx + .reachable_set(()) + .to_sorted(hcx, true) + .into_iter() + .filter_map(|local_def_id: &LocalDefId| { + let def_id = local_def_id.to_def_id(); + + let item = tcx.hir_node_by_def_id(*local_def_id); + let _ = item.ident()?; + let has_hir_body = item.body_id().is_some(); + + let item_path = tcx.def_path(def_id); + let def_kind = tcx.def_kind(def_id); + let mut fn_sig = None; + item_path.to_string_no_crate_verbose().hash_stable(hcx, &mut stable_hasher); + let has_mir = match def_kind { + DefKind::Ctor(_, _) + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::AssocConst + | DefKind::Const + | DefKind::SyntheticCoroutineBody => has_hir_body, + DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { + fn_sig = Some(tcx.fn_sig(def_id)); + if def_kind == DefKind::Closure && tcx.is_coroutine(def_id) { + has_hir_body + } else { + let generics = tcx.generics_of(def_id); + has_hir_body + && (tcx.sess.opts.unstable_opts.always_encode_mir + || (tcx.sess.opts.output_types.should_codegen() + && (generics.requires_monomorphization(tcx) + || tcx.cross_crate_inlinable(def_id)))) + } + } + _ => { + return None; + } + }; + + if let Some(sig) = fn_sig { + sig.skip_binder().hash_stable(hcx, &mut stable_hasher); + } + if !has_mir { + return Some(()); + } + + let ty = tcx.type_of(def_id); + + let body = tcx.instance_mir(InstanceKind::Item(def_id)); + let blocks = body.basic_blocks.deref(); + + // Deref to avoid hashing cache of mir body. + let _ = blocks + .iter() + .map(|bb| { + let kind = + bb.terminator.as_ref().map(|terminator| terminator.kind.clone()); + let statements = bb + .statements + .iter() + .map(|statement| statement.kind.clone()) + .collect::>(); + + (bb.is_cleanup, kind, statements) + .hash_stable(&mut hcx, &mut stable_hasher); + () + }) + .collect::>(); + + ty.skip_binder().kind().hash_stable(&mut hcx, &mut stable_hasher); + + Some(()) + }) + .collect::>(); + }); + stable_hasher.finish() + }) +} diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index f0a898d678cae..a7728b08733a4 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -716,15 +716,15 @@ impl<'a> CrateLocator<'a> { } let hash = header.hash; - if let Some(expected_hash) = self.hash { - if hash != expected_hash { - info!("Rejecting via hash: expected {} got {}", expected_hash, hash); - self.crate_rejections - .via_hash - .push(CrateMismatch { path: libpath.to_path_buf(), got: hash.to_string() }); - return None; - } - } + // if let Some(expected_hash) = self.hash { + // if hash != expected_hash { + // info!("Rejecting via hash: expected {} got {}", expected_hash, hash); + // self.crate_rejections + // .via_hash + // .push(CrateMismatch { path: libpath.to_path_buf(), got: hash.to_string() }); + // return None; + // } + // } Some(hash) } @@ -1041,12 +1041,12 @@ impl CrateError { )); } } - dcx.emit_err(errors::NewerCrateVersion { - span, - crate_name, - add_info, - found_crates, - }); + // dcx.emit_err(errors::NewerCrateVersion { + // span, + // crate_name, + // add_info, + // found_crates, + // }); } else if !locator.crate_rejections.via_triple.is_empty() { let mismatches = locator.crate_rejections.via_triple.iter(); for CrateMismatch { path, got } in mismatches { diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index e4fcbaa483d04..a85db25824089 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -31,7 +31,7 @@ pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> { let mut f = File::create_buffered(&path)?; write_mir_pretty(tcx, None, &mut f)?; if tcx.sess.opts.json_artifact_notifications { - tcx.dcx().emit_artifact_notification(&path, "mir"); + tcx.dcx().emit_artifact_notification(&path, "mir", None); } } } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 6ea8e3b920084..c1c5387d0e4f7 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -682,7 +682,9 @@ pub(crate) fn incremental_verify_ich( let old_hash = dep_graph_data.prev_fingerprint_of(prev_index); if new_hash != old_hash { - incremental_verify_ich_failed(tcx, prev_index, &|| format_value(result)); + if false { + incremental_verify_ich_failed(tcx, prev_index, &|| format_value(result)); + } } } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 419976c83b1d0..1f508efc39972 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -3281,9 +3281,9 @@ impl Config { if b && self.is_running_on_ci { // On CI, we must always rebuild LLVM if there were any modifications to it - panic!( - "`llvm.download-ci-llvm` cannot be set to `true` on CI. Use `if-unchanged` instead." - ); + // panic!( + // "`llvm.download-ci-llvm` cannot be set to `true` on CI. Use `if-unchanged` instead." + // ); } // If download-ci-llvm=true we also want to check that CI llvm is available