about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoshua Nelson <jyn514@gmail.com>2021-03-16 17:33:03 -0400
committerJoshua Nelson <jyn514@gmail.com>2021-03-16 17:33:03 -0400
commite3031fe22ae19965967f4fdf8bf46b017902a06a (patch)
tree3d1678090dc5f7d1bf459e2b3879b92d6ff2d4c3
parentf24ce9b0140d9be5a336954e878d0c1522966bb8 (diff)
downloadrust-e3031fe22ae19965967f4fdf8bf46b017902a06a.tar.gz
rust-e3031fe22ae19965967f4fdf8bf46b017902a06a.zip
Allow registering tool lints with `register_tool`
Previously, there was no way to add a custom tool prefix, even if the tool
itself had registered a lint:

 ```
 #![feature(register_tool)]
 #![register_tool(xyz)]
 #![warn(xyz::my_lint)]
 ```

```
$ rustc unknown-lint.rs  --crate-type lib
error[E0710]: an unknown tool name found in scoped lint: `xyz::my_lint`
 --> unknown-lint.rs:3:9
  |
3 | #![warn(xyz::my_lint)]
  |         ^^^
```

This allows opting-in to lints from other tools using `register_tool`.
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs4
-rw-r--r--compiler/rustc_lint/src/context.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs46
-rw-r--r--src/test/ui/lint/register-tool-lint.rs11
-rw-r--r--src/test/ui/lint/register-tool-lint.stderr27
-rw-r--r--src/test/ui/tool_lints.rs6
-rw-r--r--src/test/ui/tool_lints.stderr12
-rw-r--r--src/test/ui/unknown-lint-tool-name.rs12
-rw-r--r--src/test/ui/unknown-lint-tool-name.stderr24
9 files changed, 112 insertions, 32 deletions
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 40b0cefd83a..2c5e180f80d 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -33,10 +33,6 @@ impl MarkedAttrs {
     }
 }
 
-pub fn is_known_lint_tool(m_item: Ident) -> bool {
-    [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item.name)
-}
-
 impl NestedMetaItem {
     /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
     pub fn meta_item(&self) -> Option<&MetaItem> {
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 42ead89ca4f..1e98464f13a 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -714,7 +714,7 @@ impl<'a> EarlyContext<'a> {
             sess,
             krate,
             lint_store,
-            builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store),
+            builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, &krate.attrs),
             buffered,
         }
     }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index b3bdaf5bdc7..360cccb58d5 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,13 +1,12 @@
 use crate::context::{CheckLintNameResult, LintStore};
 use crate::late::unerased_lint_store;
 use rustc_ast as ast;
-use rustc_ast::attr;
 use rustc_ast::unwrap_or;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::{intravisit, HirId};
 use rustc_middle::hir::map::Map;
 use rustc_middle::lint::LevelAndSource;
@@ -32,7 +31,8 @@ use std::cmp;
 fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
     assert_eq!(cnum, LOCAL_CRATE);
     let store = unerased_lint_store(tcx);
-    let levels = LintLevelsBuilder::new(tcx.sess, false, &store);
+    let crate_attrs = tcx.get_attrs(DefId { krate: cnum, index: CRATE_DEF_INDEX });
+    let levels = LintLevelsBuilder::new(tcx.sess, false, &store, crate_attrs);
     let mut builder = LintLevelMapBuilder { levels, tcx, store };
     let krate = tcx.hir().krate();
 
@@ -56,6 +56,7 @@ pub struct LintLevelsBuilder<'s> {
     cur: u32,
     warn_about_weird_lints: bool,
     store: &'s LintStore,
+    crate_attrs: &'s [ast::Attribute],
 }
 
 pub struct BuilderPush {
@@ -64,7 +65,12 @@ pub struct BuilderPush {
 }
 
 impl<'s> LintLevelsBuilder<'s> {
-    pub fn new(sess: &'s Session, warn_about_weird_lints: bool, store: &'s LintStore) -> Self {
+    pub fn new(
+        sess: &'s Session,
+        warn_about_weird_lints: bool,
+        store: &'s LintStore,
+        crate_attrs: &'s [ast::Attribute],
+    ) -> Self {
         let mut builder = LintLevelsBuilder {
             sess,
             sets: LintLevelSets::new(),
@@ -72,6 +78,7 @@ impl<'s> LintLevelsBuilder<'s> {
             id_to_set: Default::default(),
             warn_about_weird_lints,
             store,
+            crate_attrs,
         };
         builder.process_command_line(sess, store);
         assert_eq!(builder.sets.list.len(), 1);
@@ -304,15 +311,22 @@ impl<'s> LintLevelsBuilder<'s> {
                 };
                 let tool_name = if meta_item.path.segments.len() > 1 {
                     let tool_ident = meta_item.path.segments[0].ident;
-                    if !attr::is_known_lint_tool(tool_ident) {
-                        struct_span_err!(
+                    if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) {
+                        let mut err = struct_span_err!(
                             sess,
                             tool_ident.span,
                             E0710,
-                            "an unknown tool name found in scoped lint: `{}`",
+                            "unknown tool name `{}` found in scoped lint: `{}`",
+                            tool_ident.name,
                             pprust::path_to_string(&meta_item.path),
-                        )
-                        .emit();
+                        );
+                        if sess.is_nightly_build() {
+                            err.help(&format!(
+                                "add `#![register_tool({})]` to the crate root",
+                                tool_ident.name
+                            ));
+                        }
+                        err.emit();
                         continue;
                     }
 
@@ -559,6 +573,20 @@ impl<'s> LintLevelsBuilder<'s> {
     }
 }
 
+fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
+    if [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item) {
+        return true;
+    }
+    // Look for registered tools
+    // NOTE: does no error handling; error handling is done by rustc_resolve.
+    sess.filter_by_name(attrs, sym::register_tool)
+        .filter_map(|attr| attr.meta_item_list())
+        .flat_map(std::convert::identity)
+        .filter_map(|nested_meta| nested_meta.ident())
+        .map(|ident| ident.name)
+        .any(|name| name == m_item)
+}
+
 struct LintLevelMapBuilder<'a, 'tcx> {
     levels: LintLevelsBuilder<'tcx>,
     tcx: TyCtxt<'tcx>,
diff --git a/src/test/ui/lint/register-tool-lint.rs b/src/test/ui/lint/register-tool-lint.rs
new file mode 100644
index 00000000000..0ba5a37b167
--- /dev/null
+++ b/src/test/ui/lint/register-tool-lint.rs
@@ -0,0 +1,11 @@
+#![crate_type = "lib"]
+#![feature(register_tool)]
+#![register_tool(xyz)]
+#![warn(xyz::my_lint)] // this should not error
+#![warn(abc::my_lint)]
+//~^ ERROR unknown tool name `abc` found in scoped lint
+//~| HELP add `#![register_tool(abc)]`
+//~| ERROR unknown tool name `abc`
+//~| HELP add `#![register_tool(abc)]`
+//~| ERROR unknown tool name `abc`
+//~| HELP add `#![register_tool(abc)]`
diff --git a/src/test/ui/lint/register-tool-lint.stderr b/src/test/ui/lint/register-tool-lint.stderr
new file mode 100644
index 00000000000..750c74cec1e
--- /dev/null
+++ b/src/test/ui/lint/register-tool-lint.stderr
@@ -0,0 +1,27 @@
+error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint`
+  --> $DIR/register-tool-lint.rs:5:9
+   |
+LL | #![warn(abc::my_lint)]
+   |         ^^^
+   |
+   = help: add `#![register_tool(abc)]` to the crate root
+
+error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint`
+  --> $DIR/register-tool-lint.rs:5:9
+   |
+LL | #![warn(abc::my_lint)]
+   |         ^^^
+   |
+   = help: add `#![register_tool(abc)]` to the crate root
+
+error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint`
+  --> $DIR/register-tool-lint.rs:5:9
+   |
+LL | #![warn(abc::my_lint)]
+   |         ^^^
+   |
+   = help: add `#![register_tool(abc)]` to the crate root
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0710`.
diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs
index 9c8540eede7..9e4aa7a939a 100644
--- a/src/test/ui/tool_lints.rs
+++ b/src/test/ui/tool_lints.rs
@@ -1,5 +1,5 @@
 #[warn(foo::bar)]
-//~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
-//~| ERROR an unknown tool name found in scoped lint: `foo::bar`
-//~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+//~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
 fn main() {}
diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr
index 1bcd7fd735d..e06f6ddc1ca 100644
--- a/src/test/ui/tool_lints.stderr
+++ b/src/test/ui/tool_lints.stderr
@@ -1,20 +1,26 @@
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/tool_lints.rs:1:8
    |
 LL | #[warn(foo::bar)]
    |        ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/tool_lints.rs:1:8
    |
 LL | #[warn(foo::bar)]
    |        ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/tool_lints.rs:1:8
    |
 LL | #[warn(foo::bar)]
    |        ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/unknown-lint-tool-name.rs b/src/test/ui/unknown-lint-tool-name.rs
index 182aec34b47..84ab7c1944a 100644
--- a/src/test/ui/unknown-lint-tool-name.rs
+++ b/src/test/ui/unknown-lint-tool-name.rs
@@ -1,8 +1,8 @@
-#![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
-                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
-                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+#![deny(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+                   //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+                   //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
 
-#[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
-                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
-                   //~| ERROR an unknown tool name found in scoped lint: `foo::bar`
+#[allow(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+                   //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
+                   //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
 fn main() {}
diff --git a/src/test/ui/unknown-lint-tool-name.stderr b/src/test/ui/unknown-lint-tool-name.stderr
index 414816d229c..1d145515abf 100644
--- a/src/test/ui/unknown-lint-tool-name.stderr
+++ b/src/test/ui/unknown-lint-tool-name.stderr
@@ -1,38 +1,50 @@
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:1:9
    |
 LL | #![deny(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:5:9
    |
 LL | #[allow(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:1:9
    |
 LL | #![deny(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:5:9
    |
 LL | #[allow(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:1:9
    |
 LL | #![deny(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
-error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
+error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:5:9
    |
 LL | #[allow(foo::bar)]
    |         ^^^
+   |
+   = help: add `#![register_tool(foo)]` to the crate root
 
 error: aborting due to 6 previous errors