Rollup merge of #83216 - jyn514:register-tool, r=petrochenkov

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:

 ```rust
 #![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`.

cc https://github.com/rust-lang/rust/issues/66079#issuecomment-788589193, ``@chorman0773``
r? ``@petrochenkov``
This commit is contained in:
Dylan DPC 2021-03-18 00:28:14 +01:00 committed by GitHub
commit bcb9226efb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 {
/// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
pub fn meta_item(&self) -> Option<&MetaItem> {

View File

@ -748,7 +748,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,
}
}

View File

@ -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>,

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)]
//~^ 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() {}

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
|
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

View File

@ -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() {}

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
|
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