From 7c071685c98d1bc74f6a215e20afa0d98ce1c531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 28 Feb 2024 22:42:31 +0100 Subject: [PATCH] Make incremental sessions identity on longer depend on the crate names provided by source code --- compiler/rustc_driver_impl/src/lib.rs | 3 +- compiler/rustc_incremental/src/persist/fs.rs | 22 +++--- .../rustc_incremental/src/persist/load.rs | 12 ++-- compiler/rustc_interface/messages.ftl | 3 - compiler/rustc_interface/src/errors.rs | 9 --- compiler/rustc_interface/src/queries.rs | 6 +- compiler/rustc_interface/src/util.rs | 68 ++----------------- compiler/rustc_session/messages.ftl | 3 + compiler/rustc_session/src/errors.rs | 9 ++- compiler/rustc_session/src/output.rs | 65 +++++++++++++++++- 10 files changed, 101 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 692c059beb0c4..7b78a0209172b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -26,7 +26,7 @@ use rustc_errors::{ markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult, }; use rustc_feature::find_gated_cfg; -use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; +use rustc_interface::util::{self, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; @@ -35,6 +35,7 @@ use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType}; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; +use rustc_session::output::collect_crate_types; use rustc_session::{config, EarlyDiagCtxt, Session}; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::FileLoader; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index dd9c16d006a96..1462037c8c8e7 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -110,8 +110,9 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::{base_n, flock}; use rustc_errors::ErrorGuaranteed; use rustc_fs_util::{link_or_copy, try_canonicalize, LinkOrCopy}; +use rustc_session::config::CrateType; +use rustc_session::output::{collect_crate_types, find_crate_name}; use rustc_session::{Session, StableCrateId}; -use rustc_span::Symbol; use std::fs as std_fs; use std::io::{self, ErrorKind}; @@ -205,11 +206,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu /// The garbage collection will take care of it. /// /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph -pub(crate) fn prepare_session_directory( - sess: &Session, - crate_name: Symbol, - stable_crate_id: StableCrateId, -) -> Result<(), ErrorGuaranteed> { +pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuaranteed> { if sess.opts.incremental.is_none() { return Ok(()); } @@ -219,7 +216,7 @@ pub(crate) fn prepare_session_directory( debug!("prepare_session_directory"); // {incr-comp-dir}/{crate-name-and-disambiguator} - let crate_dir = crate_path(sess, crate_name, stable_crate_id); + let crate_dir = crate_path(sess); debug!("crate-dir: {}", crate_dir.display()); create_dir(sess, &crate_dir, "crate")?; @@ -604,9 +601,18 @@ fn string_to_timestamp(s: &str) -> Result { Ok(UNIX_EPOCH + duration) } -fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf { +fn crate_path(sess: &Session) -> PathBuf { let incr_dir = sess.opts.incremental.as_ref().unwrap().clone(); + let crate_name = find_crate_name(sess, &[]); + let crate_types = collect_crate_types(sess, &[]); + let stable_crate_id = StableCrateId::new( + crate_name, + crate_types.contains(&CrateType::Executable), + sess.opts.cg.metadata.clone(), + sess.cfg_version, + ); + let stable_crate_id = base_n::encode(stable_crate_id.as_u64() as u128, INT_ENCODE_BASE); let crate_name = format!("{crate_name}-{stable_crate_id}"); diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 96bfe766c20f5..357f2ae92d4c3 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -8,8 +8,8 @@ use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::Decodable; use rustc_session::config::IncrementalStateAssertion; -use rustc_session::{Session, StableCrateId}; -use rustc_span::{ErrorGuaranteed, Symbol}; +use rustc_session::Session; +use rustc_span::ErrorGuaranteed; use std::path::{Path, PathBuf}; use super::data::*; @@ -190,13 +190,9 @@ pub fn load_query_result_cache(sess: &Session) -> Option> { /// Setups the dependency graph by loading an existing graph from disk and set up streaming of a /// new graph to an incremental session directory. -pub fn setup_dep_graph( - sess: &Session, - crate_name: Symbol, - stable_crate_id: StableCrateId, -) -> Result { +pub fn setup_dep_graph(sess: &Session) -> Result { // `load_dep_graph` can only be called after `prepare_session_directory`. - prepare_session_directory(sess, crate_name, stable_crate_id)?; + prepare_session_directory(sess)?; let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess)); diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index bd9fad8b04296..47dfbc1d7fbf1 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -48,6 +48,3 @@ interface_rustc_error_unexpected_annotation = interface_temps_dir_error = failed to find or create the directory specified by `--temps-dir` - -interface_unsupported_crate_type_for_target = - dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index a9ab2720d89a5..29294003b8f29 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,7 +1,5 @@ use rustc_macros::Diagnostic; -use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; -use rustc_target::spec::TargetTriple; use std::io; use std::path::Path; @@ -90,13 +88,6 @@ pub struct FailedWritingFile<'a> { #[diag(interface_proc_macro_crate_panic_abort)] pub struct ProcMacroCratePanicAbort; -#[derive(Diagnostic)] -#[diag(interface_unsupported_crate_type_for_target)] -pub struct UnsupportedCrateTypeForTarget<'a> { - pub crate_type: CrateType, - pub target_triple: &'a TargetTriple, -} - #[derive(Diagnostic)] #[diag(interface_multiple_output_types_adaption)] pub struct MultipleOutputTypesAdaption; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 86858bfe41d81..f5b14348663e8 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::{GlobalCtxt, TyCtxt}; use rustc_serialize::opaque::FileEncodeResult; use rustc_session::config::{self, CrateType, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; -use rustc_session::output::find_crate_name; +use rustc_session::output::{collect_crate_types, find_crate_name}; use rustc_session::Session; use rustc_span::symbol::sym; use std::any::Any; @@ -129,7 +129,7 @@ impl<'tcx> Queries<'tcx> { // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. let crate_name = find_crate_name(sess, &pre_configured_attrs); - let crate_types = util::collect_crate_types(sess, &pre_configured_attrs); + let crate_types = collect_crate_types(sess, &pre_configured_attrs); let stable_crate_id = StableCrateId::new( crate_name, crate_types.contains(&CrateType::Executable), @@ -137,7 +137,7 @@ impl<'tcx> Queries<'tcx> { sess.cfg_version, ); let outputs = util::build_output_filenames(&pre_configured_attrs, sess); - let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?; + let dep_graph = setup_dep_graph(sess)?; let cstore = FreezeLock::new(Box::new(CStore::new( self.compiler.codegen_backend.metadata_loader(), diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 823614e1f0619..aa028651445fa 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -7,13 +7,14 @@ use rustc_data_structures::sync; use rustc_metadata::{load_symbol_from_dylib, DylibError}; use rustc_parse::validate_attr; use rustc_session as session; -use rustc_session::config::{self, Cfg, CrateType, OutFileName, OutputFilenames, OutputTypes}; +use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; -use rustc_session::{filesearch, output, Session}; +use rustc_session::{filesearch, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; +use session::output::{categorize_crate_type, CRATE_TYPES}; use session::EarlyDiagCtxt; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; @@ -378,67 +379,6 @@ pub(crate) fn check_attr_crate_type( } } -const CRATE_TYPES: &[(Symbol, CrateType)] = &[ - (sym::rlib, CrateType::Rlib), - (sym::dylib, CrateType::Dylib), - (sym::cdylib, CrateType::Cdylib), - (sym::lib, config::default_lib_output()), - (sym::staticlib, CrateType::Staticlib), - (sym::proc_dash_macro, CrateType::ProcMacro), - (sym::bin, CrateType::Executable), -]; - -fn categorize_crate_type(s: Symbol) -> Option { - Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1) -} - -pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { - // If we're generating a test executable, then ignore all other output - // styles at all other locations - if session.opts.test { - return vec![CrateType::Executable]; - } - - // Only check command line flags if present. If no types are specified by - // command line, then reuse the empty `base` Vec to hold the types that - // will be found in crate attributes. - // JUSTIFICATION: before wrapper fn is available - #[allow(rustc::bad_opt_access)] - let mut base = session.opts.crate_types.clone(); - if base.is_empty() { - let attr_types = attrs.iter().filter_map(|a| { - if a.has_name(sym::crate_type) - && let Some(s) = a.value_str() - { - categorize_crate_type(s) - } else { - None - } - }); - base.extend(attr_types); - if base.is_empty() { - base.push(output::default_output_for_target(session)); - } else { - base.sort(); - base.dedup(); - } - } - - base.retain(|crate_type| { - if output::invalid_output_for_target(session, *crate_type) { - session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget { - crate_type: *crate_type, - target_triple: &session.opts.target_triple, - }); - false - } else { - true - } - }); - - base -} - fn multiple_output_types_to_stdout( output_types: &OutputTypes, single_output_file_is_stdout: bool, diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index af8c962a2ed6a..4e4a6cef5ab51 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -112,3 +112,6 @@ session_unleashed_feature_help_unnamed = skipping check that does not even have session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto` session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5 + +session_unsupported_crate_type_for_target = + dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 73373e9ba5874..ce5ee077ec3ce 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -10,7 +10,7 @@ use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; -use crate::parse::ParseSess; +use crate::{config::CrateType, parse::ParseSess}; pub struct FeatureGateError { pub span: MultiSpan, @@ -345,6 +345,13 @@ pub(crate) struct BinaryFloatLiteralNotSupported { pub span: Span, } +#[derive(Diagnostic)] +#[diag(session_unsupported_crate_type_for_target)] +pub struct UnsupportedCrateTypeForTarget<'a> { + pub crate_type: CrateType, + pub target_triple: &'a TargetTriple, +} + pub fn report_lit_error( sess: &ParseSess, err: LitError, diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 74d26237f2463..35cd3cbab66ce 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -1,7 +1,7 @@ //! Related to out filenames of compilation (e.g. binaries). -use crate::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; +use crate::config::{self, CrateType, Input, OutFileName, OutputFilenames, OutputType}; use crate::errors::{ - CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable, + self, CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable, InvalidCharacterInCrateName, InvalidCrateNameHelp, }; use crate::Session; @@ -200,3 +200,64 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool false } + +pub const CRATE_TYPES: &[(Symbol, CrateType)] = &[ + (sym::rlib, CrateType::Rlib), + (sym::dylib, CrateType::Dylib), + (sym::cdylib, CrateType::Cdylib), + (sym::lib, config::default_lib_output()), + (sym::staticlib, CrateType::Staticlib), + (sym::proc_dash_macro, CrateType::ProcMacro), + (sym::bin, CrateType::Executable), +]; + +pub fn categorize_crate_type(s: Symbol) -> Option { + Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1) +} + +pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { + // If we're generating a test executable, then ignore all other output + // styles at all other locations + if session.opts.test { + return vec![CrateType::Executable]; + } + + // Only check command line flags if present. If no types are specified by + // command line, then reuse the empty `base` Vec to hold the types that + // will be found in crate attributes. + // JUSTIFICATION: before wrapper fn is available + #[allow(rustc::bad_opt_access)] + let mut base = session.opts.crate_types.clone(); + if base.is_empty() { + let attr_types = attrs.iter().filter_map(|a| { + if a.has_name(sym::crate_type) + && let Some(s) = a.value_str() + { + categorize_crate_type(s) + } else { + None + } + }); + base.extend(attr_types); + if base.is_empty() { + base.push(default_output_for_target(session)); + } else { + base.sort(); + base.dedup(); + } + } + + base.retain(|crate_type| { + if invalid_output_for_target(session, *crate_type) { + session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget { + crate_type: *crate_type, + target_triple: &session.opts.target_triple, + }); + false + } else { + true + } + }); + + base +}