diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index dcda42265514a..258320aeb636a 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -925,6 +925,20 @@ pub trait ResolverExpand { fn registered_tools(&self) -> &FxHashSet; } +pub trait LintStoreExpand { + fn pre_expansion_lint( + &self, + sess: &Session, + registered_tools: &FxHashSet, + node_id: NodeId, + attrs: &[Attribute], + items: &[P], + name: &str, + ); +} + +type LintStoreExpandDyn<'a> = Option<&'a (dyn LintStoreExpand + 'a)>; + #[derive(Clone, Default)] pub struct ModuleData { /// Path to the module starting from the crate name, like `my_crate::foo::bar`. @@ -959,10 +973,6 @@ pub struct ExpansionData { pub is_trailing_mac: bool, } -type OnExternModLoaded<'a> = Option< - &'a dyn Fn(NodeId, Vec, Vec>, Symbol) -> (Vec, Vec>), ->; - /// One of these is made during expansion and incrementally updated as we go; /// when a macro expansion occurs, the resulting nodes have the `backtrace() /// -> expn_data` of their expansion context stored into their span. @@ -977,10 +987,8 @@ pub struct ExtCtxt<'a> { /// (or during eager expansion, but that's a hack). pub force_mode: bool, pub expansions: FxHashMap>, - /// Called directly after having parsed an external `mod foo;` in expansion. - /// - /// `Ident` is the module name. - pub(super) extern_mod_loaded: OnExternModLoaded<'a>, + /// Used for running pre-expansion lints on freshly loaded modules. + pub(super) lint_store: LintStoreExpandDyn<'a>, /// When we 'expand' an inert attribute, we leave it /// in the AST, but insert it here so that we know /// not to expand it again. @@ -992,14 +1000,14 @@ impl<'a> ExtCtxt<'a> { sess: &'a Session, ecfg: expand::ExpansionConfig<'a>, resolver: &'a mut dyn ResolverExpand, - extern_mod_loaded: OnExternModLoaded<'a>, + lint_store: LintStoreExpandDyn<'a>, ) -> ExtCtxt<'a> { ExtCtxt { sess, ecfg, reduced_recursion_limit: None, resolver, - extern_mod_loaded, + lint_store, root_path: PathBuf::new(), current_expansion: ExpansionData { id: LocalExpnId::ROOT, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index ac637b7c7ed37..9a4daa6d7500a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1097,7 +1097,7 @@ impl InvocationCollectorNode for P { ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. let old_attrs_len = attrs.len(); - let ParsedExternalMod { mut items, inner_span, file_path, dir_path, dir_ownership } = + let ParsedExternalMod { items, inner_span, file_path, dir_path, dir_ownership } = parse_external_mod( &ecx.sess, ident, @@ -1107,12 +1107,14 @@ impl InvocationCollectorNode for P { &mut attrs, ); - if let Some(extern_mod_loaded) = ecx.extern_mod_loaded { - (attrs, items) = extern_mod_loaded( + if let Some(lint_store) = ecx.lint_store { + lint_store.pre_expansion_lint( + ecx.sess, + ecx.resolver.registered_tools(), ecx.current_expansion.lint_node_id, - attrs, - items, - ident.name, + &attrs, + &items, + ident.name.as_str(), ); } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a1b38b6fb9038..be31eb89f1b92 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -11,7 +11,7 @@ use rustc_data_structures::parallel; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{Applicability, ErrorReported, PResult}; -use rustc_expand::base::{ExtCtxt, ResolverExpand}; +use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::Crate; use rustc_lint::{EarlyCheckNode, LintStore}; @@ -253,6 +253,23 @@ fn pre_expansion_lint<'a>( }); } +// Cannot implement directly for `LintStore` due to trait coherence. +struct LintStoreExpandImpl<'a>(&'a LintStore); + +impl LintStoreExpand for LintStoreExpandImpl<'_> { + fn pre_expansion_lint( + &self, + sess: &Session, + registered_tools: &RegisteredTools, + node_id: ast::NodeId, + attrs: &[ast::Attribute], + items: &[rustc_ast::ptr::P], + name: &str, + ) { + pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name); + } +} + /// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, /// syntax expansion, secondary `cfg` expansion, synthesis of a test /// harness if one is to be provided, injection of a dependency on the @@ -321,18 +338,8 @@ pub fn configure_and_expand( ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; - let registered_tools = resolver.registered_tools().clone(); - let extern_mod_loaded = |node_id, attrs: Vec<_>, items: Vec<_>, name: Symbol| { - pre_expansion_lint( - sess, - lint_store, - ®istered_tools, - (node_id, &*attrs, &*items), - name.as_str(), - ); - (attrs, items) - }; - let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&extern_mod_loaded)); + let lint_store = LintStoreExpandImpl(lint_store); + let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&lint_store)); // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));