about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-09-27 18:21:14 +0000
committerbors <bors@rust-lang.org>2021-09-27 18:21:14 +0000
commit98c8619502093f34ca82f8f26ccf32e753924440 (patch)
treeb82a6ad2a09d4e6861de78dc9ed8c94aa07b529a /compiler
parent2b6ed3b675475abc01ce7e68bb75b457f0c85684 (diff)
parent1e15bbe55214e5b9c56fae5809d387a12c98fd6e (diff)
downloadrust-98c8619502093f34ca82f8f26ccf32e753924440.tar.gz
rust-98c8619502093f34ca82f8f26ccf32e753924440.zip
Auto merge of #89214 - smoelius:register_tool, r=petrochenkov
Pass real crate-level attributes to `pre_expansion_lint`

The PR concerns the unstable feature `register_tool` (#66079).

The feature's implementation requires the attributes of the crate being compiled, so that when attributes like `allow(foo::bar)` are encountered, it can be verified that `register_tool(foo)` appears in the crate root.

However, the crate's attributes are not readily available during early lint passes. Specifically, on this line, `krate.attrs` appears to be the attributes of the current source file, not the attributes of the whole crate: https://github.com/rust-lang/rust/blob/bf642323d621dcefeef1d8ab4711aae36e357615/compiler/rustc_lint/src/context.rs#L815

Consequently, "unknown tool" errors were being produced when `allow(foo::bar)` appeared in a submodule, even though `register_tool(foo)` appeared in the crate root.

EDITED: The proposed fix is to obtain the real crate-level attributes in `configure_and_expand` and pass them to `pre_expansion_lint`. (See `@petrochenkov's` [comment](https://github.com/rust-lang/rust/pull/89214#issuecomment-926927072) below.)

The original "prosed fix" text follows.

---

The proposed fix is to add an `error_on_unknown_tool` flag to `LintLevelsBuilder`. The flag controls whether "unknown tool" errors are emitted. The flag is set during late passes, but not earlier.

More specifically, this PR contains two commits:

* The first adds a `known-tool-in-submodule` UI test that does not currently pass.
* The second adds the `error_on_unknown_tool` flag. The new test passes with the addition of this flag.

This change has the added benefit of eliminating some errors that were duplicated in existing tests.

To the reviewer: please check that I implemented the UI test correctly.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_interface/src/passes.rs8
-rw-r--r--compiler/rustc_lint/src/context.rs3
-rw-r--r--compiler/rustc_lint/src/early.rs24
3 files changed, 29 insertions, 6 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 0a6d76c99b7..45ad2df8245 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -240,6 +240,7 @@ fn pre_expansion_lint(
     sess: &Session,
     lint_store: &LintStore,
     krate: &ast::Crate,
+    crate_attrs: &[ast::Attribute],
     crate_name: &str,
 ) {
     sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", crate_name).run(|| {
@@ -247,6 +248,7 @@ fn pre_expansion_lint(
             sess,
             lint_store,
             &krate,
+            crate_attrs,
             true,
             None,
             rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
@@ -266,7 +268,7 @@ pub fn configure_and_expand(
     resolver: &mut Resolver<'_>,
 ) -> Result<ast::Crate> {
     tracing::trace!("configure_and_expand");
-    pre_expansion_lint(sess, lint_store, &krate, crate_name);
+    pre_expansion_lint(sess, lint_store, &krate, &krate.attrs, crate_name);
     rustc_builtin_macros::register_builtin_macros(resolver);
 
     krate = sess.time("crate_injection", || {
@@ -322,9 +324,10 @@ pub fn configure_and_expand(
             ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string())
         };
 
+        let crate_attrs = krate.attrs.clone();
         let extern_mod_loaded = |ident: Ident, attrs, items, span| {
             let krate = ast::Crate { attrs, items, span };
-            pre_expansion_lint(sess, lint_store, &krate, &ident.name.as_str());
+            pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, &ident.name.as_str());
             (krate.attrs, krate.items)
         };
         let mut ecx = ExtCtxt::new(&sess, cfg, resolver, Some(&extern_mod_loaded));
@@ -468,6 +471,7 @@ pub fn lower_to_hir<'res, 'tcx>(
             sess,
             lint_store,
             &krate,
+            &krate.attrs,
             false,
             Some(std::mem::take(resolver.lint_buffer())),
             rustc_lint::BuiltinCombinedEarlyLintPass::new(),
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 4c45e33db79..8cbd2ddcbfd 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -805,6 +805,7 @@ impl<'a> EarlyContext<'a> {
         sess: &'a Session,
         lint_store: &'a LintStore,
         krate: &'a ast::Crate,
+        crate_attrs: &'a [ast::Attribute],
         buffered: LintBuffer,
         warn_about_weird_lints: bool,
     ) -> EarlyContext<'a> {
@@ -812,7 +813,7 @@ impl<'a> EarlyContext<'a> {
             sess,
             krate,
             lint_store,
-            builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, &krate.attrs),
+            builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, crate_attrs),
             buffered,
         }
     }
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 7a8b731da5c..0bba66d3838 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -329,12 +329,20 @@ fn early_lint_crate<T: EarlyLintPass>(
     sess: &Session,
     lint_store: &LintStore,
     krate: &ast::Crate,
+    crate_attrs: &[ast::Attribute],
     pass: T,
     buffered: LintBuffer,
     warn_about_weird_lints: bool,
 ) -> LintBuffer {
     let mut cx = EarlyContextAndPass {
-        context: EarlyContext::new(sess, lint_store, krate, buffered, warn_about_weird_lints),
+        context: EarlyContext::new(
+            sess,
+            lint_store,
+            krate,
+            crate_attrs,
+            buffered,
+            warn_about_weird_lints,
+        ),
         pass,
     };
 
@@ -355,6 +363,7 @@ pub fn check_ast_crate<T: EarlyLintPass>(
     sess: &Session,
     lint_store: &LintStore,
     krate: &ast::Crate,
+    crate_attrs: &[ast::Attribute],
     pre_expansion: bool,
     lint_buffer: Option<LintBuffer>,
     builtin_lints: T,
@@ -365,14 +374,22 @@ pub fn check_ast_crate<T: EarlyLintPass>(
     let mut buffered = lint_buffer.unwrap_or_default();
 
     if !sess.opts.debugging_opts.no_interleave_lints {
-        buffered =
-            early_lint_crate(sess, lint_store, krate, builtin_lints, buffered, pre_expansion);
+        buffered = early_lint_crate(
+            sess,
+            lint_store,
+            krate,
+            crate_attrs,
+            builtin_lints,
+            buffered,
+            pre_expansion,
+        );
 
         if !passes.is_empty() {
             buffered = early_lint_crate(
                 sess,
                 lint_store,
                 krate,
+                crate_attrs,
                 EarlyLintPassObjects { lints: &mut passes[..] },
                 buffered,
                 false,
@@ -386,6 +403,7 @@ pub fn check_ast_crate<T: EarlyLintPass>(
                         sess,
                         lint_store,
                         krate,
+                        crate_attrs,
                         EarlyLintPassObjects { lints: slice::from_mut(pass) },
                         buffered,
                         pre_expansion && i == 0,