diff options
Diffstat (limited to 'compiler/rustc_interface/src')
| -rw-r--r-- | compiler/rustc_interface/src/errors.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 97 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/lib.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 248 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/proc_macro_decls.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/queries.rs | 120 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/util.rs | 26 |
8 files changed, 294 insertions, 229 deletions
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index 29543fe2f93..0eedee25026 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -32,10 +32,6 @@ pub struct MixedBinCrate; pub struct MixedProcMacroCrate; #[derive(Diagnostic)] -#[diag(interface_proc_macro_doc_without_arg)] -pub struct ProcMacroDocWithoutArg; - -#[derive(Diagnostic)] #[diag(interface_error_writing_dependencies)] pub struct ErrorWritingDependencies<'a> { pub path: &'a Path, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index d504aea77d0..4a2ca85060a 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -9,10 +9,12 @@ use rustc_data_structures::OnDrop; use rustc_errors::registry::Registry; use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_lint::LintStore; -use rustc_middle::ty; +use rustc_middle::{bug, ty}; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; -use rustc_session::config::{self, CheckCfg, ErrorOutputType, Input, OutputFilenames}; +use rustc_query_system::query::print_query_stack; +use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames}; +use rustc_session::config::{CheckCfg, ExpectedValues}; use rustc_session::lint; use rustc_session::parse::{CrateConfig, ParseSess}; use rustc_session::Session; @@ -58,6 +60,11 @@ impl Compiler { } } +#[allow(rustc::bad_opt_access)] +pub fn set_thread_safe_mode(sopts: &config::UnstableOptions) { + rustc_data_structures::sync::set_dyn_thread_safe_mode(sopts.threads > 1); +} + /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> { rustc_span::create_default_session_if_not_set_then(move |_| { @@ -120,9 +127,9 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg { rustc_span::create_default_session_if_not_set_then(move |_| { - let mut cfg = CheckCfg::default(); + let mut check_cfg = CheckCfg::default(); - 'specs: for s in specs { + for s in specs { let sess = ParseSess::with_silent_emitter(Some(format!( "this error occurred on the command line: `--check-cfg={s}`" ))); @@ -136,40 +143,63 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg { concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s ), - ); + ) }; } + let expected_error = || { + error!( + "expected `names(name1, name2, ... nameN)` or \ + `values(name, \"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 let Some(args) = meta_item.meta_item_list() { if meta_item.has_name(sym::names) { - let names_valid = - cfg.names_valid.get_or_insert_with(|| FxHashSet::default()); + 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"); - names_valid.insert(ident.name.to_string()); + check_cfg + .expecteds + .entry(ident.name.to_string()) + .or_insert(ExpectedValues::Any); } else { error!("`names()` arguments must be simple identifiers"); } } - continue 'specs; } else if meta_item.has_name(sym::values) { 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 ident_values = cfg - .values_valid + let expected_values = check_cfg + .expecteds .entry(ident.name.to_string()) - .or_insert_with(|| FxHashSet::default()); + .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) { - ident_values.insert(s.to_string()); + expected_values.insert(Some(s.to_string())); } else { error!( "`values()` arguments must be string literals" @@ -177,35 +207,40 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg { } } - continue 'specs; + if values.is_empty() { + expected_values.insert(None); + } } else { error!( "`values()` first argument must be a simple identifier" ); } } else if args.is_empty() { - cfg.well_known_values = true; - continue 'specs; + check_cfg.exhaustive_values = true; + } else { + expected_error(); } + } else { + expected_error(); } + } else { + expected_error(); } } - Ok(..) => {} - Err(err) => err.cancel(), + Ok(..) => expected_error(), + Err(err) => { + err.cancel(); + expected_error(); + } }, - Err(errs) => drop(errs), + Err(errs) => { + drop(errs); + expected_error(); + } } - - error!( - "expected `names(name1, name2, ... nameN)` or \ - `values(name, \"value1\", \"value2\", ... \"valueN\")`" - ); } - if let Some(names_valid) = &mut cfg.names_valid { - names_valid.extend(cfg.values_valid.keys().cloned()); - } - cfg + check_cfg }) } @@ -222,6 +257,7 @@ pub struct Config { pub output_dir: Option<PathBuf>, pub output_file: Option<PathBuf>, pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>, + pub locale_resources: &'static [&'static str], pub lint_caps: FxHashMap<lint::LintId, lint::Level>, @@ -267,6 +303,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se config.opts, config.crate_cfg, config.crate_check_cfg, + config.locale_resources, config.file_loader, CompilerIO { input: config.input, @@ -290,7 +327,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se override_queries: config.override_queries, }; - rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || { + rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || { let r = { let _sess_abort_error = OnDrop(|| { compiler.sess.finish_diagnostics(registry); @@ -315,7 +352,7 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) { // state if it was responsible for triggering the panic. let i = ty::tls::with_context_opt(|icx| { if let Some(icx) = icx { - QueryCtxt::from_tcx(icx.tcx).try_print_query_stack(icx.query, handler, num_frames) + print_query_stack(QueryCtxt::new(icx.tcx), icx.query, handler, num_frames) } else { 0 } diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 82bc4770b6b..51bd8381e93 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -2,7 +2,7 @@ #![feature(decl_macro)] #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] -#![feature(once_cell)] +#![feature(lazy_cell)] #![feature(try_blocks)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] @@ -12,6 +12,9 @@ #[macro_use] extern crate tracing; +use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; +use rustc_fluent_macro::fluent_messages; + mod callbacks; mod errors; pub mod interface; @@ -27,3 +30,5 @@ pub use queries::Queries; #[cfg(test)] mod tests; + +fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 6a94d19001e..d3af01474b8 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -3,16 +3,17 @@ use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; use crate::util; -use ast::CRATE_NODE_ID; use rustc_ast::{self as ast, visit}; use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; +use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; -use rustc_errors::{ErrorGuaranteed, PResult}; -use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; +use rustc_errors::PResult; +use rustc_expand::base::{ExtCtxt, LintStoreExpand}; +use rustc_fs_util::try_canonicalize; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; -use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore}; +use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; @@ -22,10 +23,9 @@ 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, hir_stats, layout_test}; use rustc_plugin_impl as plugin; -use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::Resolver; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; -use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, Untracked}; +use rustc_session::cstore::{MetadataLoader, Untracked}; use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; @@ -75,22 +75,14 @@ pub fn register_plugins<'a>( sess: &'a Session, metadata_loader: &'a dyn MetadataLoader, register_lints: impl Fn(&Session, &mut LintStore), - mut krate: ast::Crate, + pre_configured_attrs: &[ast::Attribute], crate_name: Symbol, -) -> Result<(ast::Crate, LintStore)> { - krate = sess.time("attributes_injection", || { - rustc_builtin_macros::cmdline_attrs::inject( - krate, - &sess.parse_sess, - &sess.opts.unstable_opts.crate_attr, - ) - }); - - let (krate, features) = rustc_expand::config::features(sess, krate, CRATE_NODE_ID); +) -> Result<LintStore> { // these need to be set "early" so that expansion sees `quote` if enabled. + let features = rustc_expand::config::features(sess, pre_configured_attrs); sess.init_features(features); - let crate_types = util::collect_crate_types(sess, &krate.attrs); + let crate_types = util::collect_crate_types(sess, pre_configured_attrs); sess.init_crate_types(crate_types); let stable_crate_id = StableCrateId::new( @@ -116,8 +108,9 @@ pub fn register_plugins<'a>( let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); register_lints(sess, &mut lint_store); - let registrars = - sess.time("plugin_loading", || plugin::load::load_plugins(sess, metadata_loader, &krate)); + 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 { @@ -125,7 +118,7 @@ pub fn register_plugins<'a>( } }); - Ok((krate, lint_store)) + Ok(lint_store) } fn pre_expansion_lint<'a>( @@ -171,22 +164,30 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { /// syntax expansion, secondary `cfg` expansion, synthesis of a test /// harness if one is to be provided, injection of a dependency on the /// standard library and prelude, and name resolution. -pub fn configure_and_expand( - sess: &Session, - lint_store: &LintStore, +#[instrument(level = "trace", skip(krate, resolver))] +fn configure_and_expand( mut krate: ast::Crate, - crate_name: Symbol, + pre_configured_attrs: &[ast::Attribute], resolver: &mut Resolver<'_, '_>, -) -> Result<ast::Crate> { - trace!("configure_and_expand"); - pre_expansion_lint(sess, lint_store, resolver.registered_tools(), &krate, crate_name); +) -> ast::Crate { + let tcx = resolver.tcx(); + let sess = tcx.sess; + let lint_store = unerased_lint_store(tcx); + let crate_name = tcx.crate_name(LOCAL_CRATE); + let lint_check_node = (&krate, pre_configured_attrs); + pre_expansion_lint(sess, lint_store, tcx.registered_tools(()), lint_check_node, crate_name); rustc_builtin_macros::register_builtin_macros(resolver); - krate = sess.time("crate_injection", || { - rustc_builtin_macros::standard_library_imports::inject(krate, resolver, sess) + let num_standard_library_imports = sess.time("crate_injection", || { + rustc_builtin_macros::standard_library_imports::inject( + &mut krate, + pre_configured_attrs, + resolver, + sess, + ) }); - util::check_attr_crate_type(sess, &krate.attrs, &mut resolver.lint_buffer()); + util::check_attr_crate_type(sess, pre_configured_attrs, &mut resolver.lint_buffer()); // Expand all macros krate = sess.time("macro_expand_crate", || { @@ -223,12 +224,12 @@ pub fn configure_and_expand( // Create the config for macro expansion let features = sess.features_untracked(); - let recursion_limit = get_recursion_limit(&krate.attrs, sess); + let recursion_limit = get_recursion_limit(pre_configured_attrs, sess); let cfg = rustc_expand::expand::ExpansionConfig { features: Some(features), recursion_limit, trace_mac: sess.opts.unstable_opts.trace_macros, - should_test: sess.opts.test, + should_test: sess.is_test_crate(), span_debug: sess.opts.unstable_opts.span_debug, proc_macro_backtrace: sess.opts.unstable_opts.proc_macro_backtrace, ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) @@ -236,6 +237,7 @@ pub fn configure_and_expand( let lint_store = LintStoreExpandImpl(lint_store); let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&lint_store)); + ecx.num_standard_library_imports = num_standard_library_imports; // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); @@ -249,23 +251,22 @@ pub fn configure_and_expand( ecx.check_unused_macros(); }); - let recursion_limit_hit = ecx.reduced_recursion_limit.is_some(); + // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed + // with a large AST + if ecx.reduced_recursion_limit.is_some() { + sess.abort_if_errors(); + unreachable!(); + } if cfg!(windows) { env::set_var("PATH", &old_path); } - if recursion_limit_hit { - // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed - // with a large AST - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - } else { - Ok(krate) - } - })?; + krate + }); sess.time("maybe_building_test_harness", || { - rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate) + rustc_builtin_macros::test_harness::inject(&mut krate, sess, resolver) }); let has_proc_macro_decls = sess.time("AST_validation", || { @@ -289,31 +290,31 @@ pub fn configure_and_expand( sess.emit_warning(errors::ProcMacroCratePanicAbort); } - // For backwards compatibility, we don't try to run proc macro injection - // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being - // specified. This should only affect users who manually invoke 'rustdoc', as - // 'cargo doc' will automatically pass the proper '--crate-type' flags. - // However, we do emit a warning, to let such users know that they should - // start passing '--crate-type proc-macro' - if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate { - sess.emit_warning(errors::ProcMacroDocWithoutArg); - } else { - krate = sess.time("maybe_create_a_macro_crate", || { - let is_test_crate = sess.opts.test; - rustc_builtin_macros::proc_macro_harness::inject( - sess, - resolver, - krate, - is_proc_macro_crate, - has_proc_macro_decls, - is_test_crate, - sess.diagnostic(), - ) - }); - } + sess.time("maybe_create_a_macro_crate", || { + let is_test_crate = sess.is_test_crate(); + rustc_builtin_macros::proc_macro_harness::inject( + &mut krate, + sess, + resolver, + is_proc_macro_crate, + has_proc_macro_decls, + is_test_crate, + sess.diagnostic(), + ) + }); // Done with macro expansion! + resolver.resolve_crate(&krate); + + krate +} + +fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { + let sess = tcx.sess; + let (resolver, krate) = &*tcx.resolver_for_lowering(()).borrow(); + let mut lint_buffer = resolver.lint_buffer.steal(); + if sess.opts.unstable_opts.input_stats { eprintln!("Post-expansion node count: {}", count_nodes(&krate)); } @@ -322,8 +323,6 @@ pub fn configure_and_expand( hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS", "ast-stats-2"); } - resolver.resolve_crate(&krate); - // Needs to go *after* expansion to be able to check the results of macro expansion. sess.time("complete_gated_feature_checking", || { rustc_ast_passes::feature_gate::check_crate(&krate, sess); @@ -333,7 +332,7 @@ pub fn configure_and_expand( sess.parse_sess.buffered_lints.with_lock(|buffered_lints| { info!("{} parse sess buffered_lints", buffered_lints.len()); for early_lint in buffered_lints.drain(..) { - resolver.lint_buffer().add_early_lint(early_lint); + lint_buffer.add_early_lint(early_lint); } }); @@ -352,20 +351,16 @@ pub fn configure_and_expand( } }); - sess.time("early_lint_checks", || { - let lint_buffer = Some(std::mem::take(resolver.lint_buffer())); - rustc_lint::check_ast_node( - sess, - false, - lint_store, - resolver.registered_tools(), - lint_buffer, - rustc_lint::BuiltinCombinedEarlyLintPass::new(), - &krate, - ) - }); - - Ok(krate) + let lint_store = unerased_lint_store(tcx); + rustc_lint::check_ast_node( + sess, + false, + lint_store, + tcx.registered_tools(()), + Some(lint_buffer), + rustc_lint::BuiltinCombinedEarlyLintPass::new(), + (&**krate, &*krate.attrs), + ) } // Returns all the paths that correspond to generated files. @@ -413,12 +408,12 @@ where } fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool { - let input_path = input_path.canonicalize().ok(); + let input_path = try_canonicalize(input_path).ok(); if input_path.is_none() { return false; } let check = |output_path: &PathBuf| { - if output_path.canonicalize().ok() == input_path { Some(()) } else { None } + if try_canonicalize(output_path).ok() == input_path { Some(()) } else { None } }; check_output(output_paths, check).is_some() } @@ -450,13 +445,9 @@ fn escape_dep_env(symbol: Symbol) -> String { escaped } -fn write_out_deps( - sess: &Session, - cstore: &CrateStoreDyn, - outputs: &OutputFilenames, - out_filenames: &[PathBuf], -) { +fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[PathBuf]) { // Write out dependency rules to the dep-info file if requested + let sess = tcx.sess; if !sess.opts.output_types.contains_key(&OutputType::DepInfo) { return; } @@ -504,9 +495,8 @@ fn write_out_deps( } } - let cstore = cstore.as_any().downcast_ref::<CStore>().unwrap(); - for cnum in cstore.crates_untracked() { - let source = cstore.crate_source_untracked(cnum); + for &cnum in tcx.crates(()) { + let source = tcx.used_crate_source(cnum); if let Some((path, _)) = &source.dylib { files.push(escape_dep_filename(&path.display().to_string())); } @@ -564,6 +554,29 @@ fn write_out_deps( } } +fn resolver_for_lowering<'tcx>( + tcx: TyCtxt<'tcx>, + (): (), +) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> { + let arenas = Resolver::arenas(); + let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`. + let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal(); + let mut resolver = Resolver::new(tcx, &pre_configured_attrs, krate.spans.inner_span, &arenas); + let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver); + + // Make sure we don't mutate the cstore from here on. + tcx.untracked().cstore.leak(); + + let ty::ResolverOutputs { + global_ctxt: untracked_resolutions, + ast_lowering: untracked_resolver_for_lowering, + } = resolver.into_outputs(); + + let feed = tcx.feed_unit_query(); + feed.resolutions(tcx.arena.alloc(untracked_resolutions)); + tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))) +} + fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> { let sess = tcx.sess; let _timer = sess.timer("prepare_outputs"); @@ -597,7 +610,7 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> { } } - write_out_deps(sess, tcx.cstore_untracked(), &outputs, &output_paths); + write_out_deps(tcx, &outputs, &output_paths); let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1; @@ -618,6 +631,8 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { providers.analysis = analysis; providers.hir_crate = rustc_ast_lowering::lower_to_hir; providers.output_filenames = output_filenames; + providers.resolver_for_lowering = resolver_for_lowering; + providers.early_lint_checks = early_lint_checks; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); @@ -626,6 +641,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { rustc_mir_transform::provide(providers); rustc_monomorphize::provide(providers); rustc_privacy::provide(providers); + rustc_resolve::provide(providers); rustc_hir_analysis::provide(providers); rustc_hir_typeck::provide(providers); ty::provide(providers); @@ -652,7 +668,6 @@ pub fn create_global_ctxt<'tcx>( lint_store: Lrc<LintStore>, dep_graph: DepGraph, untracked: Untracked, - queries: &'tcx OnceCell<TcxQueries<'tcx>>, gcx_cell: &'tcx OnceCell<GlobalCtxt<'tcx>>, arena: &'tcx WorkerLocal<Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>, @@ -676,10 +691,6 @@ pub fn create_global_ctxt<'tcx>( callback(sess, &mut local_providers, &mut extern_providers); } - let queries = queries.get_or_init(|| { - TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache) - }); - sess.time("setup_global_ctxt", || { gcx_cell.get_or_init(move || { TyCtxt::create_global_ctxt( @@ -689,9 +700,12 @@ pub fn create_global_ctxt<'tcx>( hir_arena, untracked, dep_graph, - queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), - queries.as_dyn(), rustc_query_impl::query_callbacks(arena), + rustc_query_impl::query_system( + local_providers, + extern_providers, + query_result_on_disk_cache, + ), ) }) }) @@ -744,27 +758,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // passes are timed inside typeck rustc_hir_analysis::check_crate(tcx)?; - sess.time("misc_checking_2", || { - parallel!( - { - sess.time("match_checking", || { - tcx.hir().par_body_owners(|def_id| tcx.ensure().check_match(def_id.to_def_id())) - }); - }, - { - sess.time("liveness_checking", || { - tcx.hir().par_body_owners(|def_id| { - // this must run before MIR dump, because - // "not all control paths return a value" is reported here. - // - // maybe move the check to a MIR pass? - tcx.ensure().check_liveness(def_id.to_def_id()); - }); - }); - } - ); - }); - sess.time("MIR_borrow_checking", || { tcx.hir().par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); }); @@ -777,9 +770,14 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { } tcx.ensure().has_ffi_unwind_calls(def_id); - if tcx.hir().body_const_context(def_id).is_some() { - tcx.ensure() - .mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(def_id)); + // If we need to codegen, ensure that we emit all errors from + // `mir_drops_elaborated_and_const_checked` now, to avoid discovering + // them later during codegen. + if tcx.sess.opts.output_types.should_codegen() + || tcx.hir().body_const_context(def_id).is_some() + { + tcx.ensure().mir_drops_elaborated_and_const_checked(def_id); + tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id())); } } }); diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 9bf7778bfb2..1c58caa0353 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -1,3 +1,4 @@ +use rustc_ast::attr; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -8,7 +9,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { for id in tcx.hir().items() { let attrs = tcx.hir().attrs(id.hir_id()); - if tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { + if attr::contains_name(attrs, sym::rustc_proc_macro_decls) { decls = Some(id.owner_id.def_id); } } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index d727efdafc2..6483d51a0b9 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -7,16 +7,17 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceCell, RwLock, WorkerLocal}; +use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::definitions::Definitions; use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; +use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; -use rustc_middle::ty::{self, GlobalCtxt, TyCtxt}; -use rustc_query_impl::Queries as TcxQueries; -use rustc_resolve::Resolver; +use rustc_middle::ty::{GlobalCtxt, TyCtxt}; use rustc_session::config::{self, OutputFilenames, OutputType}; +use rustc_session::cstore::Untracked; use rustc_session::{output::find_crate_name, Session}; use rustc_span::symbol::sym; use rustc_span::Symbol; @@ -79,15 +80,15 @@ impl<T> Default for Query<T> { pub struct Queries<'tcx> { compiler: &'tcx Compiler, gcx_cell: OnceCell<GlobalCtxt<'tcx>>, - queries: OnceCell<TcxQueries<'tcx>>, arena: WorkerLocal<Arena<'tcx>>, hir_arena: WorkerLocal<rustc_hir::Arena<'tcx>>, dep_graph_future: Query<Option<DepGraphFuture>>, parse: Query<ast::Crate>, + pre_configure: Query<(ast::Crate, ast::AttrVec)>, crate_name: Query<Symbol>, - register_plugins: Query<(ast::Crate, Lrc<LintStore>)>, + register_plugins: Query<(ast::Crate, ast::AttrVec, Lrc<LintStore>)>, dep_graph: Query<DepGraph>, // This just points to what's in `gcx_cell`. gcx: Query<&'tcx GlobalCtxt<'tcx>>, @@ -99,11 +100,11 @@ impl<'tcx> Queries<'tcx> { Queries { compiler, gcx_cell: OnceCell::new(), - queries: OnceCell::new(), arena: WorkerLocal::new(|_| Arena::default()), hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), + pre_configure: Default::default(), crate_name: Default::default(), register_plugins: Default::default(), dep_graph: Default::default(), @@ -131,17 +132,36 @@ impl<'tcx> Queries<'tcx> { .compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit())) } - pub fn register_plugins(&self) -> Result<QueryResult<'_, (ast::Crate, Lrc<LintStore>)>> { + pub fn pre_configure(&self) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec)>> { + self.pre_configure.compute(|| { + let mut krate = self.parse()?.steal(); + + let sess = self.session(); + rustc_builtin_macros::cmdline_attrs::inject( + &mut krate, + &sess.parse_sess, + &sess.opts.unstable_opts.crate_attr, + ); + + let pre_configured_attrs = + rustc_expand::config::pre_configure_attrs(sess, &krate.attrs); + Ok((krate, pre_configured_attrs)) + }) + } + + pub fn register_plugins( + &self, + ) -> Result<QueryResult<'_, (ast::Crate, ast::AttrVec, Lrc<LintStore>)>> { self.register_plugins.compute(|| { let crate_name = *self.crate_name()?.borrow(); - let krate = self.parse()?.steal(); + let (krate, pre_configured_attrs) = self.pre_configure()?.steal(); let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {}; - let (krate, lint_store) = passes::register_plugins( + let lint_store = passes::register_plugins( self.session(), &*self.codegen_backend().metadata_loader(), self.compiler.register_lints.as_deref().unwrap_or_else(|| empty), - krate, + &pre_configured_attrs, crate_name, )?; @@ -152,17 +172,17 @@ impl<'tcx> Queries<'tcx> { // called, which happens within passes::register_plugins(). self.dep_graph_future().ok(); - Ok((krate, Lrc::new(lint_store))) + Ok((krate, pre_configured_attrs, Lrc::new(lint_store))) }) } fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> { self.crate_name.compute(|| { Ok({ - let parse_result = self.parse()?; - let krate = parse_result.borrow(); + let pre_configure_result = self.pre_configure()?; + let (_, pre_configured_attrs) = &*pre_configure_result.borrow(); // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. - find_crate_name(self.session(), &krate.attrs) + find_crate_name(self.session(), pre_configured_attrs) }) }) } @@ -186,57 +206,39 @@ impl<'tcx> Queries<'tcx> { pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> { self.gcx.compute(|| { let crate_name = *self.crate_name()?.borrow(); - let (krate, lint_store) = self.register_plugins()?.steal(); - let (krate, resolver_outputs) = { - let _timer = self.session().timer("configure_and_expand"); - let sess = self.session(); - - let arenas = Resolver::arenas(); - let mut resolver = Resolver::new( - sess, - &krate, - crate_name, - self.codegen_backend().metadata_loader(), - &arenas, - ); - let krate = passes::configure_and_expand( - sess, - &lint_store, - krate, - crate_name, - &mut resolver, - )?; - (Lrc::new(krate), resolver.into_outputs()) - }; - - let ty::ResolverOutputs { - untracked, - global_ctxt: untracked_resolutions, - ast_lowering: untracked_resolver_for_lowering, - } = resolver_outputs; + let (krate, pre_configured_attrs, lint_store) = self.register_plugins()?.steal(); - let gcx = passes::create_global_ctxt( + let sess = self.session(); + + let cstore = RwLock::new(Box::new(CStore::new(sess)) as _); + let definitions = RwLock::new(Definitions::new(sess.local_stable_crate_id())); + let source_span = AppendOnlyIndexVec::new(); + let _id = source_span.push(krate.spans.inner_span); + debug_assert_eq!(_id, CRATE_DEF_ID); + let untracked = Untracked { cstore, source_span, definitions }; + + let qcx = passes::create_global_ctxt( self.compiler, lint_store, self.dep_graph()?.steal(), untracked, - &self.queries, &self.gcx_cell, &self.arena, &self.hir_arena, ); - gcx.enter(|tcx| { + qcx.enter(|tcx| { + let feed = tcx.feed_local_crate(); + feed.crate_name(crate_name); + let feed = tcx.feed_unit_query(); - feed.resolver_for_lowering( - tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, krate))), + feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); + feed.metadata_loader( + tcx.arena.alloc(Steal::new(self.codegen_backend().metadata_loader())), ); - feed.resolutions(tcx.arena.alloc(untracked_resolutions)); feed.features_query(tcx.sess.features_untracked()); - let feed = tcx.feed_local_crate(); - feed.crate_name(crate_name); }); - Ok(gcx) + Ok(qcx) }) } @@ -299,7 +301,11 @@ impl<'tcx> Queries<'tcx> { let codegen_backend = self.codegen_backend().clone(); let (crate_hash, prepare_outputs, dep_graph) = self.global_ctxt()?.enter(|tcx| { - (tcx.crate_hash(LOCAL_CRATE), tcx.output_filenames(()).clone(), tcx.dep_graph.clone()) + ( + if tcx.sess.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None }, + tcx.output_filenames(()).clone(), + tcx.dep_graph.clone(), + ) }); let ongoing_codegen = self.ongoing_codegen()?.steal(); @@ -323,7 +329,8 @@ pub struct Linker { // compilation outputs dep_graph: DepGraph, prepare_outputs: Arc<OutputFilenames>, - crate_hash: Svh, + // Only present when incr. comp. is enabled. + crate_hash: Option<Svh>, ongoing_codegen: Box<dyn Any>, } @@ -361,9 +368,8 @@ impl Linker { } if sess.opts.unstable_opts.no_link { - let encoded = CodegenResults::serialize_rlink(&codegen_results); let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT); - std::fs::write(&rlink_file, encoded) + CodegenResults::serialize_rlink(&rlink_file, &codegen_results) .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?; return Ok(()); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ac32988d3ac..1bae771e373 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -2,8 +2,10 @@ use crate::interface::parse_cfgspecs; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::rustc_optgroups; +use rustc_session::config::DebugInfo; use rustc_session::config::Input; use rustc_session::config::InstrumentXRay; use rustc_session::config::TraitSolver; @@ -50,7 +52,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) { output_file: None, temps_dir, }; - let sess = build_session(sessopts, io, None, registry, Default::default(), None, None); + let sess = build_session(sessopts, io, None, registry, vec![], Default::default(), None, None); (sess, cfg) } @@ -67,6 +69,7 @@ where is_private_dep: false, add_prelude: true, nounused_dep: false, + force: false, } } @@ -545,6 +548,7 @@ fn test_codegen_options_tracking_hash() { untracked!(ar, String::from("abc")); untracked!(codegen_units, Some(42)); untracked!(default_linker_libraries, true); + untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe"))); untracked!(extra_filename, String::from("extra-filename")); untracked!(incremental, Some(String::from("abc"))); // `link_arg` is omitted because it just forwards to `link_args`. @@ -573,7 +577,7 @@ fn test_codegen_options_tracking_hash() { tracked!(code_model, Some(CodeModel::Large)); tracked!(control_flow_guard, CFGuard::Checks); tracked!(debug_assertions, Some(true)); - tracked!(debuginfo, 0xdeadbeef); + tracked!(debuginfo, DebugInfo::Limited); tracked!(embed_bitcode, false); tracked!(force_frame_pointers, Some(false)); tracked!(force_unwind_tables, Some(true)); @@ -649,7 +653,6 @@ fn test_unstable_options_tracking_hash() { untracked!(assert_incr_state, Some(String::from("loaded"))); untracked!(deduplicate_diagnostics, false); untracked!(dep_tasks, true); - untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe"))); untracked!(dont_buffer_diagnostics, true); untracked!(dump_dep_graph, true); untracked!(dump_drop_tracking_cfg, Some("cfg.dot".to_string())); @@ -699,6 +702,7 @@ fn test_unstable_options_tracking_hash() { untracked!(threads, 99); untracked!(time_llvm_passes, true); untracked!(time_passes, true); + untracked!(time_passes_format, TimePassesFormat::Json); untracked!(trace_macros, true); untracked!(track_diagnostics, true); untracked!(trim_diagnostic_paths, false); @@ -744,6 +748,7 @@ fn test_unstable_options_tracking_hash() { tracked!(emit_thin_lto, false); tracked!(export_executable_symbols, true); tracked!(fewer_names, Some(true)); + tracked!(flatten_format_args, false); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_sections, Some(false)); @@ -756,6 +761,7 @@ fn test_unstable_options_tracking_hash() { tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); tracked!(instrument_xray, Some(InstrumentXRay::default())); + tracked!(link_directives, false); tracked!(link_only, true); tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); @@ -763,6 +769,7 @@ fn test_unstable_options_tracking_hash() { tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]); + tracked!(mir_keep_place_mention, true); tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, false); @@ -776,7 +783,6 @@ fn test_unstable_options_tracking_hash() { tracked!(packed_bundled_libs, true); tracked!(panic_abort_tests, true); tracked!(panic_in_drop, PanicStrategy::Abort); - tracked!(pick_stable_methods_before_any_unstable, false); tracked!(plt, Some(true)); tracked!(polonius, true); tracked!(precise_enum_drop_elaboration, false); @@ -790,12 +796,16 @@ fn test_unstable_options_tracking_hash() { tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); tracked!(report_delayed_bugs, true); tracked!(sanitizer, SanitizerSet::ADDRESS); + tracked!(sanitizer_cfi_canonical_jump_tables, None); + tracked!(sanitizer_cfi_generalize_pointers, Some(true)); + tracked!(sanitizer_cfi_normalize_integers, Some(true)); tracked!(sanitizer_memory_track_origins, 2); tracked!(sanitizer_recover, SanitizerSet::ADDRESS); tracked!(saturating_float_casts, Some(true)); tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); + 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)); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index e4b4d5375e6..8d37b1053d8 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -4,6 +4,8 @@ use libloading::Library; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +#[cfg(parallel_compiler)] +use rustc_data_structures::sync; use rustc_errors::registry::Registry; use rustc_parse::validate_attr; use rustc_session as session; @@ -14,8 +16,8 @@ use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; use rustc_session::parse::CrateConfig; use rustc_session::{early_error, filesearch, output, Session}; +use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; -use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::FileLoader; use rustc_span::symbol::{sym, Symbol}; use session::CompilerIO; @@ -34,7 +36,7 @@ pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>; /// specific features (SSE, NEON etc.). /// /// This is performed by checking whether a set of permitted features -/// is available on the target machine, by querying LLVM. +/// is available on the target machine, by querying the codegen backend. pub fn add_configuration( cfg: &mut CrateConfig, sess: &mut Session, @@ -59,6 +61,7 @@ pub fn create_session( sopts: config::Options, cfg: FxHashSet<(String, Option<String>)>, check_cfg: CheckCfg, + locale_resources: &'static [&'static str], file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>, io: CompilerIO, lint_caps: FxHashMap<lint::LintId, lint::Level>, @@ -89,11 +92,15 @@ pub fn create_session( } }; + let mut locale_resources = Vec::from(locale_resources); + locale_resources.push(codegen_backend.locale_resource()); + let mut sess = session::build_session( sopts, io, bundle, descriptions, + locale_resources, lint_caps, file_loader, target_override, @@ -105,7 +112,7 @@ pub fn create_session( add_configuration(&mut cfg, &mut sess, &*codegen_backend); let mut check_cfg = config::to_crate_check_config(check_cfg); - check_cfg.fill_well_known(); + check_cfg.fill_well_known(&sess.target); sess.parse_sess.config = cfg; sess.parse_sess.check_config = check_cfg; @@ -163,8 +170,10 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( ) -> R { use rustc_data_structures::jobserver; use rustc_middle::ty::tls; - use rustc_query_impl::{deadlock, QueryContext, QueryCtxt}; + use rustc_query_impl::QueryCtxt; + use rustc_query_system::query::{deadlock, QueryContext}; + let registry = sync::Registry::new(threads); let mut builder = rayon::ThreadPoolBuilder::new() .thread_name(|_| "rustc".to_string()) .acquire_thread_handler(jobserver::acquire_thread) @@ -174,11 +183,11 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( // On deadlock, creates a new thread and forwards information in thread // locals to it. The new thread runs the deadlock handler. let query_map = tls::with(|tcx| { - QueryCtxt::from_tcx(tcx) + QueryCtxt::new(tcx) .try_collect_active_jobs() .expect("active jobs shouldn't be locked in deadlock handler") }); - let registry = rustc_rayon_core::Registry::current(); + let registry = rayon_core::Registry::current(); thread::spawn(move || deadlock(query_map, ®istry)); }); if let Some(size) = get_stack_size() { @@ -195,6 +204,9 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>( .build_scoped( // Initialize each new worker thread when created. move |thread: rayon::ThreadBuilder| { + // Register the thread for use with the `WorkerLocal` type. + registry.register(); + rustc_span::set_session_globals_then(session_globals, || thread.run()) }, // Run `f` on the first thread in the thread pool. @@ -500,7 +512,7 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu .opts .crate_name .clone() - .or_else(|| rustc_attr::find_crate_name(sess, attrs).map(|n| n.to_string())) + .or_else(|| rustc_attr::find_crate_name(attrs).map(|n| n.to_string())) .unwrap_or_else(|| sess.io.input.filestem().to_owned()); OutputFilenames::new( |
