From a3b4961d5f4ddbb0e86d323ebaeccc391f04d8a7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 6 Nov 2023 16:52:38 +1100 Subject: [PATCH] Move `lint_store` from `GlobalCtxt` to `Session`. This was made possible by the removal of plugin support, which simplified lint store creation. This simplifies the places in rustc and rustdoc that call `describe_lints`, which are early on. The lint store is now built before those places, so they don't have to create their own lint store for temporary use, they can just use the main one. --- compiler/rustc_driver_impl/src/lib.rs | 22 +++++-------------- compiler/rustc_interface/src/interface.rs | 10 +++++++++ compiler/rustc_interface/src/passes.rs | 6 ++--- compiler/rustc_interface/src/queries.rs | 7 ------ compiler/rustc_lint/src/late.rs | 20 +++++++++++------ compiler/rustc_lint/src/levels.rs | 4 ++-- compiler/rustc_middle/src/ty/context.rs | 11 +--------- compiler/rustc_session/src/session.rs | 16 +++++++++++++- src/librustdoc/lib.rs | 9 +------- .../clippy/tests/ui/macro_use_imports.stderr | 18 +++++++-------- 10 files changed, 59 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b323ae8d29e..4ad7b9f6cd1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -33,7 +33,7 @@ use rustc_feature::find_gated_cfg; use rustc_fluent_macro::fluent_messages; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; -use rustc_lint::{unerased_lint_store, LintStore}; +use rustc_lint::unerased_lint_store; use rustc_metadata::locator; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths}; @@ -356,16 +356,7 @@ fn run_compiler( let handler = EarlyErrorHandler::new(sopts.error_format); if sopts.describe_lints { - let mut lint_store = - rustc_lint::new_lint_store(compiler.session().enable_internal_lints()); - let registered_lints = - if let Some(register_lints) = compiler.register_lints() { - register_lints(compiler.session(), &mut lint_store); - true - } else { - false - }; - describe_lints(compiler.session(), &lint_store, registered_lints); + describe_lints(compiler.session()); return; } let should_stop = print_crate_info( @@ -442,9 +433,7 @@ fn run_compiler( } if sess.opts.describe_lints { - queries - .global_ctxt()? - .enter(|tcx| describe_lints(sess, unerased_lint_store(tcx), true)); + describe_lints(sess); return early_exit(); } @@ -991,7 +980,7 @@ the command line flag directly. } /// Write to stdout lint command options, together with a list of all available lints -pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_lints: bool) { +pub fn describe_lints(sess: &Session) { safe_println!( " Available lint options: @@ -1017,6 +1006,7 @@ Available lint options: lints } + let lint_store = unerased_lint_store(sess); let (loaded, builtin): (Vec<_>, _) = lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_loaded); let loaded = sort_lints(sess, loaded); @@ -1094,7 +1084,7 @@ Available lint options: print_lint_groups(builtin_groups, true); - match (loaded_lints, loaded.len(), loaded_groups.len()) { + match (sess.registered_lints, loaded.len(), loaded_groups.len()) { (false, 0, _) | (false, _, 0) => { safe_println!("Lint tools like Clippy can load additional lints and lint groups."); } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 89125c54a6a..02a023885b7 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -485,6 +485,16 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se sess.opts.untracked_state_hash = hasher.finish() } + // Even though the session holds the lint store, we can't build the + // lint store until after the session exists. And we wait until now + // so that `register_lints` sees the fully initialized session. + let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); + if let Some(register_lints) = config.register_lints.as_deref() { + register_lints(&sess, &mut lint_store); + sess.registered_lints = true; + } + sess.lint_store = Some(Lrc::new(lint_store)); + let compiler = Compiler { sess: Lrc::new(sess), codegen_backend: Lrc::from(codegen_backend), diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 39bf96e5d8f..0baf77c4f7e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -127,7 +127,7 @@ fn configure_and_expand( let tcx = resolver.tcx(); let sess = tcx.sess; let features = tcx.features(); - let lint_store = unerased_lint_store(tcx); + let lint_store = unerased_lint_store(&tcx.sess); let crate_name = tcx.crate_name(LOCAL_CRATE); let lint_check_node = (&krate, pre_configured_attrs); pre_expansion_lint( @@ -319,7 +319,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { } }); - let lint_store = unerased_lint_store(tcx); + let lint_store = unerased_lint_store(&tcx.sess); rustc_lint::check_ast_node( sess, tcx.features(), @@ -634,7 +634,6 @@ pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, crate_types: Vec, stable_crate_id: StableCrateId, - lint_store: Lrc, dep_graph: DepGraph, untracked: Untracked, gcx_cell: &'tcx OnceLock>, @@ -665,7 +664,6 @@ pub fn create_global_ctxt<'tcx>( sess, crate_types, stable_crate_id, - lint_store, arena, hir_arena, untracked, diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 3e913b3cc01..ace5ec732fb 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -148,12 +148,6 @@ impl<'tcx> Queries<'tcx> { ); let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?; - let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); - if let Some(register_lints) = self.compiler.register_lints.as_deref() { - register_lints(sess, &mut lint_store); - } - let lint_store = Lrc::new(lint_store); - let cstore = FreezeLock::new(Box::new(CStore::new( self.codegen_backend().metadata_loader(), stable_crate_id, @@ -168,7 +162,6 @@ impl<'tcx> Queries<'tcx> { self.compiler, crate_types, stable_crate_id, - lint_store, dep_graph, untracked, &self.gcx_cell, diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 6d5bbadcbc2..10c4c0dc79f 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -17,22 +17,25 @@ use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore}; use rustc_ast as ast; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::join; +use rustc_data_structures::sync::{join, Lrc}; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit as hir_visit; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::LintPass; +use rustc_session::Session; use rustc_span::Span; use std::any::Any; use std::cell::Cell; /// Extract the `LintStore` from the query context. -/// This function exists because we've erased `LintStore` as `dyn Any` in the context. -pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { - let store: &dyn Any = &*tcx.lint_store; +/// This function exists because we've erased `LintStore` as `dyn Any` in the session. +pub fn unerased_lint_store(sess: &Session) -> &LintStore { + assert!(sess.lint_store.is_some()); + let store: &Lrc<_> = sess.lint_store.as_ref().unwrap(); + let store: &dyn Any = &**store; store.downcast_ref().unwrap() } @@ -361,8 +364,11 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( // Note: `passes` is often empty. In that case, it's faster to run // `builtin_lints` directly rather than bundling it up into the // `RuntimeCombinedLateLintPass`. - let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); + let mut passes: Vec<_> = unerased_lint_store(&tcx.sess) + .late_module_passes + .iter() + .map(|mk_pass| (mk_pass)(tcx)) + .collect(); if passes.is_empty() { late_lint_mod_inner(tcx, module_def_id, context, builtin_lints); } else { @@ -399,7 +405,7 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { // Note: `passes` is often empty. let mut passes: Vec<_> = - unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); + unerased_lint_store(&tcx.sess).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); if passes.is_empty() { return; diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index ecbb3426511..ee5fa87e45d 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -123,7 +123,7 @@ impl LintLevelSets { } fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { - let store = unerased_lint_store(tcx); + let store = unerased_lint_store(&tcx.sess); let mut builder = LintLevelsBuilder { sess: tcx.sess, @@ -152,7 +152,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp #[instrument(level = "trace", skip(tcx), ret)] fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap { - let store = unerased_lint_store(tcx); + let store = unerased_lint_store(&tcx.sess); let attrs = tcx.hir_attrs(owner); let mut levels = LintLevelsBuilder { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e635c3f96ec..ee23c9c4897 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -39,7 +39,7 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{FreezeReadGuard, Lock, WorkerLocal}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{ DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan, @@ -69,7 +69,6 @@ use rustc_type_ir::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; -use std::any::Any; use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; @@ -544,12 +543,6 @@ pub struct GlobalCtxt<'tcx> { /// `rustc_symbol_mangling` crate for more information. stable_crate_id: StableCrateId, - /// This only ever stores a `LintStore` but we don't want a dependency on that type here. - /// - /// FIXME(Centril): consider `dyn LintStoreMarker` once - /// we can upcast to `Any` for some additional type safety. - pub lint_store: Lrc, - pub dep_graph: DepGraph, pub prof: SelfProfilerRef, @@ -709,7 +702,6 @@ impl<'tcx> TyCtxt<'tcx> { s: &'tcx Session, crate_types: Vec, stable_crate_id: StableCrateId, - lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, untracked: Untracked, @@ -730,7 +722,6 @@ impl<'tcx> TyCtxt<'tcx> { sess: s, crate_types, stable_crate_id, - lint_store, arena, hir_arena, interners, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index e9655a5587d..38e09f47eac 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -16,7 +16,9 @@ use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; -use rustc_data_structures::sync::{AtomicU64, Lock, Lrc, OneThread, Ordering::SeqCst}; +use rustc_data_structures::sync::{ + AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread, Ordering::SeqCst, +}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; use rustc_errors::emitter::{DynEmitter, EmitterWriter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; @@ -37,6 +39,7 @@ use rustc_target::spec::{ DebuginfoKind, SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel, }; +use std::any::Any; use std::cell::{self, RefCell}; use std::env; use std::fmt; @@ -167,6 +170,15 @@ pub struct Session { /// false positives about a job server in our environment. pub jobserver: Client, + /// This only ever stores a `LintStore` but we don't want a dependency on that type here. + /// + /// FIXME(Centril): consider `dyn LintStoreMarker` once + /// we can upcast to `Any` for some additional type safety. + pub lint_store: Option>, + + /// Should be set if any lints are registered in `lint_store`. + pub registered_lints: bool, + /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap, @@ -1483,6 +1495,8 @@ pub fn build_session( optimization_fuel, print_fuel, jobserver: jobserver::client(), + lint_store: None, + registered_lints: false, driver_lint_caps, ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a43ea5582b7..5144bbdaf5e 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -797,14 +797,7 @@ fn main_args( let sess = compiler.session(); if sess.opts.describe_lints { - let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); - let registered_lints = if let Some(register_lints) = compiler.register_lints() { - register_lints(sess, &mut lint_store); - true - } else { - false - }; - rustc_driver::describe_lints(sess, &lint_store, registered_lints); + rustc_driver::describe_lints(sess); return Ok(()); } diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr index 6de869699ec..bafe8cfddb4 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.stderr +++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr @@ -1,17 +1,11 @@ -error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:25:5 - | -LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` - | - = note: `-D clippy::macro-use-imports` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::macro_use_imports)]` - error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:23:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};` + | + = note: `-D clippy::macro-use-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::macro_use_imports)]` error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:21:5 @@ -19,6 +13,12 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_imports.rs:25:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` + error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:19:5 |