1
Fork 0

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`.
This commit is contained in:
Joshua Nelson 2021-03-16 17:33:03 -04:00
parent f24ce9b014
commit e3031fe22a
9 changed files with 112 additions and 32 deletions

View file

@ -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 { impl NestedMetaItem {
/// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`. /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
pub fn meta_item(&self) -> Option<&MetaItem> { pub fn meta_item(&self) -> Option<&MetaItem> {

View file

@ -714,7 +714,7 @@ impl<'a> EarlyContext<'a> {
sess, sess,
krate, krate,
lint_store, 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, buffered,
} }
} }

View file

@ -1,13 +1,12 @@
use crate::context::{CheckLintNameResult, LintStore}; use crate::context::{CheckLintNameResult, LintStore};
use crate::late::unerased_lint_store; use crate::late::unerased_lint_store;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::attr;
use rustc_ast::unwrap_or; use rustc_ast::unwrap_or;
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir; 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_hir::{intravisit, HirId};
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::lint::LevelAndSource; use rustc_middle::lint::LevelAndSource;
@ -32,7 +31,8 @@ use std::cmp;
fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap { fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
assert_eq!(cnum, LOCAL_CRATE); assert_eq!(cnum, LOCAL_CRATE);
let store = unerased_lint_store(tcx); 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 mut builder = LintLevelMapBuilder { levels, tcx, store };
let krate = tcx.hir().krate(); let krate = tcx.hir().krate();
@ -56,6 +56,7 @@ pub struct LintLevelsBuilder<'s> {
cur: u32, cur: u32,
warn_about_weird_lints: bool, warn_about_weird_lints: bool,
store: &'s LintStore, store: &'s LintStore,
crate_attrs: &'s [ast::Attribute],
} }
pub struct BuilderPush { pub struct BuilderPush {
@ -64,7 +65,12 @@ pub struct BuilderPush {
} }
impl<'s> LintLevelsBuilder<'s> { 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 { let mut builder = LintLevelsBuilder {
sess, sess,
sets: LintLevelSets::new(), sets: LintLevelSets::new(),
@ -72,6 +78,7 @@ impl<'s> LintLevelsBuilder<'s> {
id_to_set: Default::default(), id_to_set: Default::default(),
warn_about_weird_lints, warn_about_weird_lints,
store, store,
crate_attrs,
}; };
builder.process_command_line(sess, store); builder.process_command_line(sess, store);
assert_eq!(builder.sets.list.len(), 1); 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_name = if meta_item.path.segments.len() > 1 {
let tool_ident = meta_item.path.segments[0].ident; let tool_ident = meta_item.path.segments[0].ident;
if !attr::is_known_lint_tool(tool_ident) { if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) {
struct_span_err!( let mut err = struct_span_err!(
sess, sess,
tool_ident.span, tool_ident.span,
E0710, 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), 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; 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> { struct LintLevelMapBuilder<'a, 'tcx> {
levels: LintLevelsBuilder<'tcx>, levels: LintLevelsBuilder<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View file

@ -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)]`

View file

@ -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`.

View file

@ -1,5 +1,5 @@
#[warn(foo::bar)] #[warn(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 an unknown tool name found in scoped lint: `foo::bar` //~| ERROR unknown tool name `foo` 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`
fn main() {} fn main() {}

View file

@ -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 --> $DIR/tool_lints.rs:1:8
| |
LL | #[warn(foo::bar)] 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 --> $DIR/tool_lints.rs:1:8
| |
LL | #[warn(foo::bar)] 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 --> $DIR/tool_lints.rs:1:8
| |
LL | #[warn(foo::bar)] LL | #[warn(foo::bar)]
| ^^^ | ^^^
|
= help: add `#![register_tool(foo)]` to the crate root
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -1,8 +1,8 @@
#![deny(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 an unknown tool name found in scoped lint: `foo::bar` //~| ERROR unknown tool name `foo` 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`
#[allow(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 an unknown tool name found in scoped lint: `foo::bar` //~| ERROR unknown tool name `foo` 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`
fn main() {} fn main() {}

View file

@ -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 --> $DIR/unknown-lint-tool-name.rs:1:9
| |
LL | #![deny(foo::bar)] 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 --> $DIR/unknown-lint-tool-name.rs:5:9
| |
LL | #[allow(foo::bar)] 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 --> $DIR/unknown-lint-tool-name.rs:1:9
| |
LL | #![deny(foo::bar)] 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 --> $DIR/unknown-lint-tool-name.rs:5:9
| |
LL | #[allow(foo::bar)] 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 --> $DIR/unknown-lint-tool-name.rs:1:9
| |
LL | #![deny(foo::bar)] 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 --> $DIR/unknown-lint-tool-name.rs:5:9
| |
LL | #[allow(foo::bar)] LL | #[allow(foo::bar)]
| ^^^ | ^^^
|
= help: add `#![register_tool(foo)]` to the crate root
error: aborting due to 6 previous errors error: aborting due to 6 previous errors