diff options
Diffstat (limited to 'compiler/rustc_interface/src')
| -rw-r--r-- | compiler/rustc_interface/src/callbacks.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 547 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 64 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/queries.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 33 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/util.rs | 116 |
6 files changed, 317 insertions, 455 deletions
diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 6fa989bb96c..ef00ced67ff 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -33,9 +33,7 @@ fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnost tls::with_context_opt(|icx| { if let Some(icx) = icx { if let Some(diagnostics) = icx.diagnostics { - let mut diagnostics = diagnostics.lock(); - diagnostics.extend(Some(diagnostic.clone())); - std::mem::drop(diagnostics); + diagnostics.lock().extend(Some(diagnostic.clone())); } // Diagnostics are tracked, we can ignore the dependency. diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index e703fe228c3..c4962707f69 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -18,12 +18,12 @@ use rustc_query_system::query::print_query_stack; use rustc_session::config::{ self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames, }; +use rustc_session::filesearch::sysroot_candidates; use rustc_session::parse::ParseSess; -use rustc_session::CompilerIO; -use rustc_session::Session; -use rustc_session::{lint, EarlyErrorHandler}; -use rustc_span::source_map::{FileLoader, FileName}; +use rustc_session::{lint, CompilerIO, EarlyErrorHandler, Session}; +use rustc_span::source_map::FileLoader; use rustc_span::symbol::sym; +use rustc_span::FileName; use std::path::PathBuf; use std::result; use std::sync::Arc; @@ -64,296 +64,266 @@ impl Compiler { } /// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`. -pub fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec<String>) -> Cfg<String> { - // This creates a short-lived `SessionGlobals`, containing an interner. The - // parsed values are converted from symbols to strings before exiting - // because the symbols are meaningless once the interner is gone. - rustc_span::create_default_session_if_not_set_then(move |_| { - cfgs.into_iter() - .map(|s| { - let sess = ParseSess::with_silent_emitter(Some(format!( - "this error occurred on the command line: `--cfg={s}`" - ))); - let filename = FileName::cfg_spec_source_code(&s); - - macro_rules! error { - ($reason: expr) => { - handler.early_error(format!( - concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), - s - )); - }; - } - - match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { - Ok(mut parser) => match parser.parse_meta_item() { - Ok(meta_item) if parser.token == token::Eof => { - if meta_item.path.segments.len() != 1 { - error!("argument key must be an identifier"); - } - match &meta_item.kind { - MetaItemKind::List(..) => {} - MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { - error!("argument value must be a string"); - } - MetaItemKind::NameValue(..) | MetaItemKind::Word => { - let ident = meta_item.ident().expect("multi-segment cfg key"); - return ( - ident.name.to_string(), - meta_item.value_str().map(|sym| sym.to_string()), - ); - } - } - } - Ok(..) => {} - Err(err) => err.cancel(), - }, - Err(errs) => drop(errs), - } - - // If the user tried to use a key="value" flag, but is missing the quotes, provide - // a hint about how to resolve this. - if s.contains('=') && !s.contains("=\"") && !s.ends_with('"') { - error!(concat!( - r#"expected `key` or `key="value"`, ensure escaping is appropriate"#, - r#" for your shell, try 'key="value"' or key=\"value\""# - )); - } else { - error!(r#"expected `key` or `key="value"`"#); - } - }) - .collect::<Cfg<String>>() - }) -} - -/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. -pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg<String> { - // The comment about `SessionGlobals` and symbols in `parse_cfg` above - // applies here too. - rustc_span::create_default_session_if_not_set_then(move |_| { - // If any --check-cfg is passed then exhaustive_values and exhaustive_names - // are enabled by default. - let exhaustive_names = !specs.is_empty(); - let exhaustive_values = !specs.is_empty(); - let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; - - let mut old_syntax = None; - for s in specs { +pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec<String>) -> Cfg { + cfgs.into_iter() + .map(|s| { let sess = ParseSess::with_silent_emitter(Some(format!( - "this error occurred on the command line: `--check-cfg={s}`" + "this error occurred on the command line: `--cfg={s}`" ))); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { - ($reason:expr) => { + ($reason: expr) => { handler.early_error(format!( - concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), + concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s - )) + )); }; } - let expected_error = || -> ! { - error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") - }; + match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + Ok(mut parser) => match parser.parse_meta_item() { + Ok(meta_item) if parser.token == token::Eof => { + if meta_item.path.segments.len() != 1 { + error!("argument key must be an identifier"); + } + match &meta_item.kind { + MetaItemKind::List(..) => {} + MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { + error!("argument value must be a string"); + } + MetaItemKind::NameValue(..) | MetaItemKind::Word => { + let ident = meta_item.ident().expect("multi-segment cfg key"); + return (ident.name, meta_item.value_str()); + } + } + } + Ok(..) => {} + Err(err) => err.cancel(), + }, + Err(errs) => drop(errs), + } - let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string()) - else { - expected_error(); - }; + // If the user tried to use a key="value" flag, but is missing the quotes, provide + // a hint about how to resolve this. + if s.contains('=') && !s.contains("=\"") && !s.ends_with('"') { + error!(concat!( + r#"expected `key` or `key="value"`, ensure escaping is appropriate"#, + r#" for your shell, try 'key="value"' or key=\"value\""# + )); + } else { + error!(r#"expected `key` or `key="value"`"#); + } + }) + .collect::<Cfg>() +} - let meta_item = match parser.parse_meta_item() { - Ok(meta_item) if parser.token == token::Eof => meta_item, - Ok(..) => expected_error(), - Err(err) => { - err.cancel(); - expected_error(); - } +/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. +pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg { + // If any --check-cfg is passed then exhaustive_values and exhaustive_names + // are enabled by default. + let exhaustive_names = !specs.is_empty(); + let exhaustive_values = !specs.is_empty(); + let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; + + let mut old_syntax = None; + for s in specs { + let sess = ParseSess::with_silent_emitter(Some(format!( + "this error occurred on the command line: `--check-cfg={s}`" + ))); + let filename = FileName::cfg_spec_source_code(&s); + + macro_rules! error { + ($reason:expr) => { + handler.early_error(format!( + concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), + s + )) }; + } + + let expected_error = || -> ! { + error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") + }; + + let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string()) + else { + expected_error(); + }; - let Some(args) = meta_item.meta_item_list() else { + let meta_item = match parser.parse_meta_item() { + Ok(meta_item) if parser.token == token::Eof => meta_item, + Ok(..) => expected_error(), + Err(err) => { + err.cancel(); expected_error(); - }; + } + }; - if meta_item.has_name(sym::names) { - // defaults are flipped for the old syntax - if old_syntax == None { - check_cfg.exhaustive_names = false; - check_cfg.exhaustive_values = false; - } - old_syntax = Some(true); - - check_cfg.exhaustive_names = true; - for arg in args { - if arg.is_word() && arg.ident().is_some() { - let ident = arg.ident().expect("multi-segment cfg key"); - check_cfg - .expecteds - .entry(ident.name.to_string()) - .or_insert(ExpectedValues::Any); - } else { - error!("`names()` arguments must be simple identifiers"); - } - } - } else if meta_item.has_name(sym::values) { - // defaults are flipped for the old syntax - if old_syntax == None { - check_cfg.exhaustive_names = false; - check_cfg.exhaustive_values = false; + let Some(args) = meta_item.meta_item_list() else { + expected_error(); + }; + + let mut set_old_syntax = || { + // defaults are flipped for the old syntax + if old_syntax == None { + check_cfg.exhaustive_names = false; + check_cfg.exhaustive_values = false; + } + old_syntax = Some(true); + }; + + if meta_item.has_name(sym::names) { + set_old_syntax(); + + check_cfg.exhaustive_names = true; + for arg in args { + if arg.is_word() && let Some(ident) = arg.ident() { + check_cfg.expecteds.entry(ident.name).or_insert(ExpectedValues::Any); + } else { + error!("`names()` arguments must be simple identifiers"); } - old_syntax = Some(true); - - if let Some((name, values)) = args.split_first() { - if name.is_word() && name.ident().is_some() { - let ident = name.ident().expect("multi-segment cfg key"); - let expected_values = check_cfg - .expecteds - .entry(ident.name.to_string()) - .and_modify(|expected_values| match expected_values { - ExpectedValues::Some(_) => {} - ExpectedValues::Any => { - // handle the case where names(...) was done - // before values by changing to a list - *expected_values = ExpectedValues::Some(FxHashSet::default()); - } - }) - .or_insert_with(|| ExpectedValues::Some(FxHashSet::default())); - - let ExpectedValues::Some(expected_values) = expected_values else { - bug!("`expected_values` should be a list a values") - }; - - for val in values { - if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) { - expected_values.insert(Some(s.to_string())); - } else { - error!("`values()` arguments must be string literals"); + } + } else if meta_item.has_name(sym::values) { + set_old_syntax(); + + if let Some((name, values)) = args.split_first() { + if name.is_word() && let Some(ident) = name.ident() { + let expected_values = check_cfg + .expecteds + .entry(ident.name) + .and_modify(|expected_values| match expected_values { + ExpectedValues::Some(_) => {} + ExpectedValues::Any => { + // handle the case where names(...) was done + // before values by changing to a list + *expected_values = ExpectedValues::Some(FxHashSet::default()); } - } + }) + .or_insert_with(|| ExpectedValues::Some(FxHashSet::default())); - if values.is_empty() { - expected_values.insert(None); + let ExpectedValues::Some(expected_values) = expected_values else { + bug!("`expected_values` should be a list a values") + }; + + for val in values { + if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) { + expected_values.insert(Some(*s)); + } else { + error!("`values()` arguments must be string literals"); } - } else { - error!("`values()` first argument must be a simple identifier"); } - } else if args.is_empty() { - check_cfg.exhaustive_values = true; + + if values.is_empty() { + expected_values.insert(None); + } } else { - expected_error(); + error!("`values()` first argument must be a simple identifier"); } - } else if meta_item.has_name(sym::cfg) { - old_syntax = Some(false); + } else if args.is_empty() { + check_cfg.exhaustive_values = true; + } else { + expected_error(); + } + } else if meta_item.has_name(sym::cfg) { + old_syntax = Some(false); - let mut names = Vec::new(); - let mut values: FxHashSet<_> = Default::default(); + let mut names = Vec::new(); + let mut values: FxHashSet<_> = Default::default(); - let mut any_specified = false; - let mut values_specified = false; - let mut values_any_specified = false; + let mut any_specified = false; + let mut values_specified = false; + let mut values_any_specified = false; - for arg in args { - if arg.is_word() && let Some(ident) = arg.ident() { - if values_specified { - error!("`cfg()` names cannot be after values"); - } - names.push(ident); - } else if arg.has_name(sym::any) - && let Some(args) = arg.meta_item_list() - { - if any_specified { - error!("`any()` cannot be specified multiple times"); - } - any_specified = true; - if !args.is_empty() { - error!("`any()` must be empty"); - } - } else if arg.has_name(sym::values) - && let Some(args) = arg.meta_item_list() - { - if names.is_empty() { - error!("`values()` cannot be specified before the names"); - } else if values_specified { - error!("`values()` cannot be specified multiple times"); - } - values_specified = true; - - for arg in args { - if let Some(LitKind::Str(s, _)) = - arg.lit().map(|lit| &lit.kind) - { - values.insert(Some(s.to_string())); - } else if arg.has_name(sym::any) - && let Some(args) = arg.meta_item_list() - { - if values_any_specified { - error!( - "`any()` in `values()` cannot be specified multiple times" - ); - } - values_any_specified = true; - if !args.is_empty() { - error!("`any()` must be empty"); - } - } else { - error!( - "`values()` arguments must be string literals or `any()`" - ); + for arg in args { + if arg.is_word() && let Some(ident) = arg.ident() { + if values_specified { + error!("`cfg()` names cannot be after values"); + } + names.push(ident); + } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() { + if any_specified { + error!("`any()` cannot be specified multiple times"); + } + any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else if arg.has_name(sym::values) && let Some(args) = arg.meta_item_list() { + if names.is_empty() { + error!("`values()` cannot be specified before the names"); + } else if values_specified { + error!("`values()` cannot be specified multiple times"); + } + values_specified = true; + + for arg in args { + if let Some(LitKind::Str(s, _)) = arg.lit().map(|lit| &lit.kind) { + values.insert(Some(*s)); + } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() { + if values_any_specified { + error!("`any()` in `values()` cannot be specified multiple times"); + } + values_any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); } + } else { + error!("`values()` arguments must be string literals or `any()`"); } - } else { - error!( - "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`" - ); } - } - - if values.is_empty() && !values_any_specified && !any_specified { - values.insert(None); - } else if !values.is_empty() && values_any_specified { + } else { error!( - "`values()` arguments cannot specify string literals and `any()` at the same time" + "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`" ); } + } - if any_specified { - if names.is_empty() - && values.is_empty() - && !values_specified - && !values_any_specified - { - check_cfg.exhaustive_names = false; - } else { - error!("`cfg(any())` can only be provided in isolation"); - } + if values.is_empty() && !values_any_specified && !any_specified { + values.insert(None); + } else if !values.is_empty() && values_any_specified { + error!( + "`values()` arguments cannot specify string literals and `any()` at the same time" + ); + } + + if any_specified { + if names.is_empty() + && values.is_empty() + && !values_specified + && !values_any_specified + { + check_cfg.exhaustive_names = false; } else { - for name in names { - check_cfg - .expecteds - .entry(name.to_string()) - .and_modify(|v| match v { - ExpectedValues::Some(v) if !values_any_specified => { - v.extend(values.clone()) - } - ExpectedValues::Some(_) => *v = ExpectedValues::Any, - ExpectedValues::Any => {} - }) - .or_insert_with(|| { - if values_any_specified { - ExpectedValues::Any - } else { - ExpectedValues::Some(values.clone()) - } - }); - } + error!("`cfg(any())` can only be provided in isolation"); } } else { - expected_error(); + for name in names { + check_cfg + .expecteds + .entry(name.name) + .and_modify(|v| match v { + ExpectedValues::Some(v) if !values_any_specified => { + v.extend(values.clone()) + } + ExpectedValues::Some(_) => *v = ExpectedValues::Any, + ExpectedValues::Any => {} + }) + .or_insert_with(|| { + if values_any_specified { + ExpectedValues::Any + } else { + ExpectedValues::Some(values.clone()) + } + }); + } } + } else { + expected_error(); } + } - check_cfg - }) + check_cfg } /// The compiler configuration @@ -361,9 +331,9 @@ pub struct Config { /// Command line options pub opts: config::Options, - /// cfg! configuration in addition to the default ones - pub crate_cfg: Cfg<String>, - pub crate_check_cfg: CheckCfg<String>, + /// Unparsed cfg! configuration in addition to the default ones. + pub crate_cfg: Vec<String>, + pub crate_check_cfg: Vec<String>, pub input: Input, pub output_dir: Option<PathBuf>, @@ -384,7 +354,7 @@ pub struct Config { pub hash_untracked_state: Option<Box<dyn FnOnce(&Session, &mut StableHasher) + Send>>, /// This is a callback from the driver that is called when we're registering lints; - /// it is called during plugin registration when we have the LintStore in a non-shared state. + /// it is called during lint loading when we have the LintStore in a non-shared state. /// /// Note that if you find a Some here you probably want to call that function in the new /// function being registered. @@ -428,32 +398,71 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se || { crate::callbacks::setup_callbacks(); - let registry = &config.registry; - let handler = EarlyErrorHandler::new(config.opts.error_format); + let codegen_backend = if let Some(make_codegen_backend) = config.make_codegen_backend { + make_codegen_backend(&config.opts) + } else { + util::get_codegen_backend( + &handler, + &config.opts.maybe_sysroot, + config.opts.unstable_opts.codegen_backend.as_deref(), + ) + }; + let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); - let (mut sess, codegen_backend) = util::create_session( + + let bundle = match rustc_errors::fluent_bundle( + config.opts.maybe_sysroot.clone(), + sysroot_candidates().to_vec(), + config.opts.unstable_opts.translate_lang.clone(), + config.opts.unstable_opts.translate_additional_ftl.as_deref(), + config.opts.unstable_opts.translate_directionality_markers, + ) { + Ok(bundle) => bundle, + Err(e) => { + handler.early_error(format!("failed to load fluent bundle: {e}")); + } + }; + + let mut locale_resources = Vec::from(config.locale_resources); + locale_resources.push(codegen_backend.locale_resource()); + + // target_override is documented to be called before init(), so this is okay + let target_override = codegen_backend.target_override(&config.opts); + + let mut sess = rustc_session::build_session( &handler, config.opts, - config.crate_cfg, - config.crate_check_cfg, - config.locale_resources, - config.file_loader, CompilerIO { input: config.input, output_dir: config.output_dir, output_file: config.output_file, temps_dir, }, + bundle, + config.registry.clone(), + locale_resources, config.lint_caps, - config.make_codegen_backend, - registry.clone(), + config.file_loader, + target_override, + util::rustc_version_str().unwrap_or("unknown"), config.ice_file, config.using_internal_features, config.expanded_args, ); + codegen_backend.init(&sess); + + let cfg = parse_cfg(&handler, config.crate_cfg); + let mut cfg = config::build_configuration(&sess, cfg); + util::add_configuration(&mut cfg, &mut sess, &*codegen_backend); + sess.parse_sess.config = cfg; + + let mut check_cfg = parse_check_cfg(&handler, config.crate_check_cfg); + check_cfg.fill_well_known(&sess.target); + sess.parse_sess.check_config = check_cfg; + if let Some(parse_sess_created) = config.parse_sess_created { parse_sess_created(&mut sess.parse_sess); } @@ -474,7 +483,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || { let r = { let _sess_abort_error = defer(|| { - compiler.sess.finish_diagnostics(registry); + compiler.sess.finish_diagnostics(&config.registry); }); f(&compiler) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 884afae23d8..7d14d088e59 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -23,11 +23,10 @@ use rustc_middle::util::Providers; use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; use rustc_passes::{self, abi_test, hir_stats, layout_test}; -use rustc_plugin_impl as plugin; use rustc_resolve::Resolver; use rustc_session::code_stats::VTableSizeInfo; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; -use rustc_session::cstore::{MetadataLoader, Untracked}; +use rustc_session::cstore::Untracked; use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; @@ -75,25 +74,12 @@ fn count_nodes(krate: &ast::Crate) -> usize { pub(crate) fn create_lint_store( sess: &Session, - metadata_loader: &dyn MetadataLoader, register_lints: Option<impl Fn(&Session, &mut LintStore)>, - pre_configured_attrs: &[ast::Attribute], ) -> LintStore { let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); if let Some(register_lints) = register_lints { register_lints(sess, &mut lint_store); } - - let registrars = sess.time("plugin_loading", || { - plugin::load::load_plugins(sess, metadata_loader, pre_configured_attrs) - }); - sess.time("plugin_registration", || { - let mut registry = plugin::Registry { lint_store: &mut lint_store }; - for registrar in registrars { - registrar(&mut registry); - } - }); - lint_store } @@ -392,34 +378,16 @@ fn generated_output_paths( out_filenames } -// Runs `f` on every output file path and returns the first non-None result, or None if `f` -// returns None for every file path. -fn check_output<F, T>(output_paths: &[PathBuf], f: F) -> Option<T> -where - F: Fn(&PathBuf) -> Option<T>, -{ - for output_path in output_paths { - if let Some(result) = f(output_path) { - return Some(result); - } - } - None -} - fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool { let input_path = try_canonicalize(input_path).ok(); if input_path.is_none() { return false; } - let check = |output_path: &PathBuf| { - if try_canonicalize(output_path).ok() == input_path { Some(()) } else { None } - }; - check_output(output_paths, check).is_some() + output_paths.iter().any(|output_path| try_canonicalize(output_path).ok() == input_path) } -fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> { - let check = |output_path: &PathBuf| output_path.is_dir().then(|| output_path.clone()); - check_output(output_paths, check) +fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<&PathBuf> { + output_paths.iter().find(|output_path| output_path.is_dir()) } fn escape_dep_filename(filename: &str) -> String { @@ -602,9 +570,7 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> { let (_, krate) = &*tcx.resolver_for_lowering(()).borrow(); let crate_name = tcx.crate_name(LOCAL_CRATE); - // FIXME: rustdoc passes &[] instead of &krate.attrs here let outputs = util::build_output_filenames(&krate.attrs, sess); - let output_paths = generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name); @@ -882,16 +848,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr)); - // A slightly edited version of the code in `rustc_trait_selection::traits::vtable::vtable_entries`, - // that works without self type and just counts number of entries. + // A slightly edited version of the code in + // `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self + // type and just counts number of entries. // - // Note that this is technically wrong, for traits which have associated types in supertraits: + // Note that this is technically wrong, for traits which have associated types in + // supertraits: // // trait A: AsRef<Self::T> + AsRef<()> { type T; } // - // Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>` and - // `AsRef<()>` are the same trait, thus we assume that those are different, and potentially - // over-estimate how many vtable entries there are. + // Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>` + // and `AsRef<()>` are the same trait, thus we assume that those are different, and + // potentially over-estimate how many vtable entries there are. // // Similarly this is wrong for traits that have methods with possibly-impossible bounds. // For example: @@ -918,10 +886,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { let own_existential_entries = tcx.own_existential_vtable_entries(trait_ref.def_id()); - // The original code here ignores the method if its predicates are impossible. - // We can't really do that as, for example, all not trivial bounds on generic - // parameters are impossible (since we don't know the parameters...), - // see the comment above. + // The original code here ignores the method if its predicates are + // impossible. We can't really do that as, for example, all not trivial + // bounds on generic parameters are impossible (since we don't know the + // parameters...), see the comment above. entries_ignoring_upcasting += own_existential_entries.len(); if emit_vptr { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 4fb295da640..3a5f788e8dd 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -148,12 +148,8 @@ impl<'tcx> Queries<'tcx> { ); let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?; - let lint_store = Lrc::new(passes::create_lint_store( - sess, - &*self.codegen_backend().metadata_loader(), - self.compiler.register_lints.as_deref(), - &pre_configured_attrs, - )); + let lint_store = + Lrc::new(passes::create_lint_store(sess, self.compiler.register_lints.as_deref())); let cstore = FreezeLock::new(Box::new(CStore::new( self.codegen_backend().metadata_loader(), stable_crate_id, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 57ca709267a..8e66083a390 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -2,32 +2,21 @@ use crate::interface::parse_cfg; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; -use rustc_session::config::rustc_optgroups; -use rustc_session::config::Cfg; -use rustc_session::config::DebugInfo; -use rustc_session::config::Input; -use rustc_session::config::InstrumentXRay; -use rustc_session::config::LinkSelfContained; -use rustc_session::config::Polonius; -use rustc_session::config::TraitSolver; -use rustc_session::config::{build_configuration, build_session_options}; use rustc_session::config::{ - BranchProtection, Externs, OomStrategy, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, - ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel, + build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, + DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, Input, + InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, + MirSpanview, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, + Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, + TraitSolver, WasiExecModel, }; -use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; -use rustc_session::config::{DumpMonoStatsFormat, MirSpanview}; -use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip}; -use rustc_session::config::{InstrumentCoverage, Passes}; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; -use rustc_session::{build_session, getopts, Session}; -use rustc_session::{CompilerIO, EarlyErrorHandler}; +use rustc_session::{build_session, getopts, CompilerIO, EarlyErrorHandler, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; -use rustc_span::FileName; -use rustc_span::SourceFileHashAlgorithm; +use rustc_span::{FileName, SourceFileHashAlgorithm}; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel}; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; @@ -35,10 +24,7 @@ use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; use std::sync::Arc; -fn mk_session( - handler: &mut EarlyErrorHandler, - matches: getopts::Matches, -) -> (Session, Cfg<String>) { +fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, Cfg) { let registry = registry::Registry::new(&[]); let sessopts = build_session_options(handler, &matches); let cfg = parse_cfg(handler, matches.opt_strs("cfg")); @@ -831,7 +817,6 @@ fn test_unstable_options_tracking_hash() { tracked!(split_lto_unit, Some(true)); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); tracked!(stack_protector, StackProtector::All); - tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 4d0be65697a..22d12793464 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -3,29 +3,24 @@ use info; use libloading::Library; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::fx::FxHashMap; #[cfg(parallel_compiler)] use rustc_data_structures::sync; -use rustc_errors::registry::Registry; use rustc_parse::validate_attr; use rustc_session as session; -use rustc_session::config::{ - self, Cfg, CheckCfg, CrateType, OutFileName, OutputFilenames, OutputTypes, -}; +use rustc_session::config::{self, Cfg, CrateType, OutFileName, OutputFilenames, OutputTypes}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; use rustc_session::{filesearch, output, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; -use rustc_span::source_map::FileLoader; use rustc_span::symbol::{sym, Symbol}; -use session::{CompilerIO, EarlyErrorHandler}; +use session::EarlyErrorHandler; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::mem; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, OnceLock}; +use std::sync::OnceLock; use std::thread; /// Function pointer type that constructs a new CodegenBackend. @@ -36,11 +31,7 @@ pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>; /// /// This is performed by checking whether a set of permitted features /// is available on the target machine, by querying the codegen backend. -pub fn add_configuration( - cfg: &mut Cfg<Symbol>, - sess: &mut Session, - codegen_backend: &dyn CodegenBackend, -) { +pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dyn CodegenBackend) { let tf = sym::target_feature; let unstable_target_features = codegen_backend.target_features(sess, true); @@ -56,83 +47,6 @@ pub fn add_configuration( } } -pub fn create_session( - handler: &EarlyErrorHandler, - sopts: config::Options, - cfg: Cfg<String>, - check_cfg: CheckCfg<String>, - locale_resources: &'static [&'static str], - file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>, - io: CompilerIO, - lint_caps: FxHashMap<lint::LintId, lint::Level>, - make_codegen_backend: Option< - Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>, - >, - descriptions: Registry, - ice_file: Option<PathBuf>, - using_internal_features: Arc<AtomicBool>, - expanded_args: Vec<String>, -) -> (Session, Box<dyn CodegenBackend>) { - let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { - make_codegen_backend(&sopts) - } else { - get_codegen_backend( - handler, - &sopts.maybe_sysroot, - sopts.unstable_opts.codegen_backend.as_deref(), - ) - }; - - // target_override is documented to be called before init(), so this is okay - let target_override = codegen_backend.target_override(&sopts); - - let bundle = match rustc_errors::fluent_bundle( - sopts.maybe_sysroot.clone(), - sysroot_candidates().to_vec(), - sopts.unstable_opts.translate_lang.clone(), - sopts.unstable_opts.translate_additional_ftl.as_deref(), - sopts.unstable_opts.translate_directionality_markers, - ) { - Ok(bundle) => bundle, - Err(e) => { - handler.early_error(format!("failed to load fluent bundle: {e}")); - } - }; - - let mut locale_resources = Vec::from(locale_resources); - locale_resources.push(codegen_backend.locale_resource()); - - let mut sess = session::build_session( - handler, - sopts, - io, - bundle, - descriptions, - locale_resources, - lint_caps, - file_loader, - target_override, - rustc_version_str().unwrap_or("unknown"), - ice_file, - using_internal_features, - expanded_args, - ); - - codegen_backend.init(&sess); - - let mut cfg = config::build_configuration(&sess, cfg); - add_configuration(&mut cfg, &mut sess, &*codegen_backend); - - let mut check_cfg = check_cfg.intern(); - check_cfg.fill_well_known(&sess.target); - - // These configs use symbols, rather than strings. - sess.parse_sess.config = cfg; - sess.parse_sess.check_config = check_cfg; - - (sess, codegen_backend) -} - const STACK_SIZE: usize = 8 * 1024 * 1024; fn get_stack_size() -> Option<usize> { @@ -487,21 +401,6 @@ fn categorize_crate_type(s: Symbol) -> Option<CrateType> { } pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<CrateType> { - // Unconditionally collect crate types from attributes to make them used - let attr_types: Vec<CrateType> = attrs - .iter() - .filter_map(|a| { - if a.has_name(sym::crate_type) { - match a.value_str() { - Some(s) => categorize_crate_type(s), - _ => None, - } - } else { - None - } - }) - .collect(); - // If we're generating a test executable, then ignore all other output // styles at all other locations if session.opts.test { @@ -515,6 +414,13 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C #[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)); |
