diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-10-23 22:19:10 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-10-23 22:19:10 +0200 |
| commit | 7c043e284a9a3e71ee2e5d34be8e40abf1daa49e (patch) | |
| tree | cb01ad8e8d25608e0626c6596097108098606cf2 /src/librustc_interface | |
| parent | 4b9fbfbc29dbf0192dc0a9ed2bf6d61f2e7b971b (diff) | |
| parent | 4e8d1b229217c7c83ce96b44410ccae9470db973 (diff) | |
| download | rust-7c043e284a9a3e71ee2e5d34be8e40abf1daa49e.tar.gz rust-7c043e284a9a3e71ee2e5d34be8e40abf1daa49e.zip | |
Rollup merge of #65193 - Mark-Simulacrum:lockless-lintstore, r=nikomatsakis
Lockless LintStore
This removes mutability from the lint store after registration. Each commit stands alone, for the most part, though they don't make sense out of sequence.
The intent here is to move LintStore to a more parallel-friendly architecture, although also just a cleaner one from an implementation perspective. Specifically, this has the following changes:
* We no longer implicitly register lints when registering lint passes
* For the most part this means that registration calls now likely want to call something like:
`lint_store.register_lints(&Pass::get_lints())` as well as `register_*_pass`.
* In theory this is a simplification as it's much easier for folks to just register lints and then have passes that implement whichever lint however they want, rather than necessarily tying passes to lints.
* Lint passes still have a list of associated lints, but a followup PR could plausibly change that
* This list must be known for a given pass type, not instance, i.e., `fn get_lints()` is the signature instead of `fn get_lints(&self)` as before.
* We do not store pass objects, instead storing constructor functions. This means we always get new passes when running lints (this happens approximately once though for a given compiler session, so no behavior change is expected).
* Registration API is _much_ simpler: generally all functions are just taking `Fn() -> PassObject` rather than several different `bool`s.
Diffstat (limited to 'src/librustc_interface')
| -rw-r--r-- | src/librustc_interface/interface.rs | 9 | ||||
| -rw-r--r-- | src/librustc_interface/passes.rs | 44 | ||||
| -rw-r--r-- | src/librustc_interface/queries.rs | 28 | ||||
| -rw-r--r-- | src/librustc_interface/util.rs | 6 |
4 files changed, 56 insertions, 31 deletions
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 5e1ad3e61dd..24ea0fc8bf6 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -39,6 +39,7 @@ pub struct Compiler { pub(crate) queries: Queries, pub(crate) cstore: Lrc<CStore>, pub(crate) crate_name: Option<String>, + pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>, } impl Compiler { @@ -137,6 +138,13 @@ pub struct Config { pub crate_name: Option<String>, pub lint_caps: FxHashMap<lint::LintId, lint::Level>, + + /// 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. + /// + /// Note that if you find a Some here you probably want to call that function in the new + /// function being registered. + pub register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>, } pub fn run_compiler_in_existing_thread_pool<F, R>(config: Config, f: F) -> R @@ -165,6 +173,7 @@ where output_file: config.output_file, queries: Default::default(), crate_name: config.crate_name, + register_lints: config.register_lints, }; let _sess_abort_error = OnDrop(|| { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 89de5714695..2044b73db8a 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -117,6 +117,7 @@ declare_box_region_type!( /// Returns `None` if we're aborting after handling -W help. pub fn configure_and_expand( sess: Lrc<Session>, + lint_store: Lrc<lint::LintStore>, cstore: Lrc<CStore>, krate: ast::Crate, crate_name: &str, @@ -134,6 +135,7 @@ pub fn configure_and_expand( let resolver_arenas = Resolver::arenas(); let res = configure_and_expand_inner( sess, + &lint_store, &*cstore, krate, &crate_name, @@ -225,9 +227,10 @@ pub struct PluginInfo { pub fn register_plugins<'a>( sess: &'a Session, cstore: &'a CStore, + register_lints: impl Fn(&Session, &mut lint::LintStore), mut krate: ast::Crate, crate_name: &str, -) -> Result<(ast::Crate, PluginInfo)> { +) -> Result<(ast::Crate, PluginInfo, Lrc<lint::LintStore>)> { krate = time(sess, "attributes injection", || { syntax_ext::cmdline_attrs::inject( krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr @@ -278,7 +281,14 @@ pub fn register_plugins<'a>( ) }); - let mut registry = Registry::new(sess, krate.span); + let mut lint_store = rustc_lint::new_lint_store( + sess.opts.debugging_opts.no_interleave_lints, + sess.unstable_options(), + ); + + (register_lints)(&sess, &mut lint_store); + + let mut registry = Registry::new(sess, &mut lint_store, krate.span); time(sess, "plugin registration", || { for registrar in registrars { @@ -289,34 +299,20 @@ pub fn register_plugins<'a>( let Registry { syntax_exts, - early_lint_passes, - late_lint_passes, - lint_groups, llvm_passes, attributes, .. } = registry; - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, false, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, false, false, pass); - } - - for (name, (to, deprecated_name)) in lint_groups { - ls.register_group(Some(sess), true, name, deprecated_name, to); - } - *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; *sess.plugin_attributes.borrow_mut() = attributes; - Ok((krate, PluginInfo { syntax_exts })) + Ok((krate, PluginInfo { syntax_exts }, Lrc::new(lint_store))) } fn configure_and_expand_inner<'a>( sess: &'a Session, + lint_store: &'a lint::LintStore, cstore: &'a CStore, mut krate: ast::Crate, crate_name: &str, @@ -327,6 +323,7 @@ fn configure_and_expand_inner<'a>( time(sess, "pre-AST-expansion lint checks", || { lint::check_ast_crate( sess, + lint_store, &krate, true, rustc_lint::BuiltinCombinedPreExpansionLintPass::new()); @@ -536,6 +533,7 @@ fn configure_and_expand_inner<'a>( pub fn lower_to_hir( sess: &Session, + lint_store: &lint::LintStore, cstore: &CStore, resolver: &mut Resolver<'_>, dep_graph: &DepGraph, @@ -554,7 +552,13 @@ pub fn lower_to_hir( }); time(sess, "early lint checks", || { - lint::check_ast_crate(sess, &krate, false, rustc_lint::BuiltinCombinedEarlyLintPass::new()) + lint::check_ast_crate( + sess, + lint_store, + &krate, + false, + rustc_lint::BuiltinCombinedEarlyLintPass::new(), + ) }); // Discard hygiene data, which isn't required after lowering to HIR. @@ -817,6 +821,7 @@ impl BoxedGlobalCtxt { pub fn create_global_ctxt( compiler: &Compiler, + lint_store: Lrc<lint::LintStore>, mut hir_forest: hir::map::Forest, defs: hir::map::Definitions, resolutions: Resolutions, @@ -854,6 +859,7 @@ pub fn create_global_ctxt( let gcx = TyCtxt::create_global_ctxt( sess, + lint_store, cstore, local_providers, extern_providers, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index cd72dc9453c..84648ca8326 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -2,9 +2,13 @@ use crate::interface::{Compiler, Result}; use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo}; use rustc_incremental::DepGraphFuture; +use rustc_data_structures::sync::Lrc; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::util::common::{time, ErrorReported}; use rustc::hir; +use rustc::lint; +use rustc::session::Session; +use rustc::lint::LintStore; use rustc::hir::def_id::LOCAL_CRATE; use rustc::ty::steal::Steal; use rustc::dep_graph::DepGraph; @@ -74,8 +78,8 @@ pub(crate) struct Queries { dep_graph_future: Query<Option<DepGraphFuture>>, parse: Query<ast::Crate>, crate_name: Query<String>, - register_plugins: Query<(ast::Crate, PluginInfo)>, - expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>)>, + register_plugins: Query<(ast::Crate, PluginInfo, Lrc<LintStore>)>, + expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>, dep_graph: Query<DepGraph>, lower_to_hir: Query<(Steal<hir::map::Forest>, ExpansionResult)>, prepare_outputs: Query<OutputFilenames>, @@ -106,14 +110,19 @@ impl Compiler { }) } - pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo)>> { + pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo, Lrc<LintStore>)>> { self.queries.register_plugins.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let krate = self.parse()?.take(); + let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {}; let result = passes::register_plugins( self.session(), self.cstore(), + self.register_lints + .as_ref() + .map(|p| &**p) + .unwrap_or_else(|| empty), krate, &crate_name, ); @@ -148,17 +157,20 @@ impl Compiler { pub fn expansion( &self - ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>)>> { + ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> { self.queries.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); - let (krate, plugin_info) = self.register_plugins()?.take(); + let (krate, plugin_info, lint_store) = self.register_plugins()?.take(); passes::configure_and_expand( self.sess.clone(), + lint_store.clone(), self.cstore().clone(), krate, &crate_name, plugin_info, - ).map(|(krate, resolver)| (krate, Steal::new(Rc::new(RefCell::new(resolver))))) + ).map(|(krate, resolver)| { + (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store) + }) }) } @@ -185,9 +197,11 @@ impl Compiler { let peeked = expansion_result.peek(); let krate = &peeked.0; let resolver = peeked.1.steal(); + let lint_store = &peeked.2; let hir = Steal::new(resolver.borrow_mut().access(|resolver| { passes::lower_to_hir( self.session(), + lint_store, self.cstore(), resolver, &*self.dep_graph()?.peek(), @@ -212,11 +226,13 @@ impl Compiler { self.queries.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone(); + let lint_store = self.expansion()?.peek().2.clone(); let hir = self.lower_to_hir()?; let hir = hir.peek(); let (ref hir_forest, ref expansion) = *hir; Ok(passes::create_global_ctxt( self, + lint_store, hir_forest.steal(), expansion.defs.steal(), expansion.resolutions.steal(), diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 0c272f0c456..8f11dc93727 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -13,7 +13,6 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_errors::registry::Registry; -use rustc_lint; use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_mir; use rustc_passes; @@ -108,11 +107,6 @@ pub fn create_session( let codegen_backend = get_codegen_backend(&sess); - rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); - if sess.unstable_options() { - rustc_lint::register_internals(&mut sess.lint_store.borrow_mut(), Some(&sess)); - } - let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg)); add_configuration(&mut cfg, &sess, &*codegen_backend); sess.parse_sess.config = cfg; |
