Rollup merge of #86639 - eholk:lint-tool, r=petrochenkov

Support lint tool names in rustc command line options

When rustc is running without a lint tool such as clippy enabled, options for lints such as `clippy::foo` are meant to be ignored. This was already working for those specified by attrs, such as `#![allow(clippy::foo)]`, but this did not work for command line arguments like `-A clippy::foo`. This PR fixes that issue.

Note that we discovered this issue while discussing https://github.com/rust-lang/cargo/issues/5034.

Fixes #86628.
This commit is contained in:
Yuki Okushi
2021-07-08 10:44:29 +09:00
committed by GitHub
7 changed files with 123 additions and 34 deletions

View File

@@ -89,7 +89,7 @@ impl<'s> LintLevelsBuilder<'s> {
self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
for &(ref lint_name, level) in &sess.opts.lint_opts {
store.check_lint_name_cmdline(sess, &lint_name, level);
store.check_lint_name_cmdline(sess, &lint_name, level, self.crate_attrs);
let orig_level = level;
// If the cap is less than this specified level, e.g., if we've got
@@ -111,7 +111,7 @@ impl<'s> LintLevelsBuilder<'s> {
}
for lint_name in &sess.opts.force_warns {
store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn);
store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn, self.crate_attrs);
let lints = store
.find_lints(lint_name)
.unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids"));
@@ -322,33 +322,14 @@ impl<'s> LintLevelsBuilder<'s> {
continue;
}
};
let tool_name = if meta_item.path.segments.len() > 1 {
let tool_ident = meta_item.path.segments[0].ident;
if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) {
let mut err = struct_span_err!(
sess,
tool_ident.span,
E0710,
"unknown tool name `{}` found in scoped lint: `{}`",
tool_ident.name,
pprust::path_to_string(&meta_item.path),
);
if sess.is_nightly_build() {
err.help(&format!(
"add `#![register_tool({})]` to the crate root",
tool_ident.name
));
}
err.emit();
continue;
}
Some(meta_item.path.segments.remove(0).ident.name)
let tool_ident = if meta_item.path.segments.len() > 1 {
Some(meta_item.path.segments.remove(0).ident)
} else {
None
};
let tool_name = tool_ident.map(|ident| ident.name);
let name = pprust::path_to_string(&meta_item.path);
let lint_result = store.check_lint_name(&name, tool_name);
let lint_result = store.check_lint_name(sess, &name, tool_name, self.crate_attrs);
match &lint_result {
CheckLintNameResult::Ok(ids) => {
let src = LintLevelSource::Node(
@@ -365,7 +346,8 @@ impl<'s> LintLevelsBuilder<'s> {
CheckLintNameResult::Tool(result) => {
match *result {
Ok(ids) => {
let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
let complete_name =
&format!("{}::{}", tool_ident.unwrap().name, name);
let src = LintLevelSource::Node(
Symbol::intern(complete_name),
sp,
@@ -420,6 +402,26 @@ impl<'s> LintLevelsBuilder<'s> {
}
}
&CheckLintNameResult::NoTool => {
let mut err = struct_span_err!(
sess,
tool_ident.map_or(DUMMY_SP, |ident| ident.span),
E0710,
"unknown tool name `{}` found in scoped lint: `{}::{}`",
tool_name.unwrap(),
tool_name.unwrap(),
pprust::path_to_string(&meta_item.path),
);
if sess.is_nightly_build() {
err.help(&format!(
"add `#![register_tool({})]` to the crate root",
tool_name.unwrap()
));
}
err.emit();
continue;
}
_ if !self.warn_about_weird_lints => {}
CheckLintNameResult::Warning(msg, renamed) => {
@@ -451,8 +453,8 @@ impl<'s> LintLevelsBuilder<'s> {
let (level, src) =
self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
let name = if let Some(tool_name) = tool_name {
format!("{}::{}", tool_name, name)
let name = if let Some(tool_ident) = tool_ident {
format!("{}::{}", tool_ident.name, name)
} else {
name.to_string()
};
@@ -475,7 +477,9 @@ impl<'s> LintLevelsBuilder<'s> {
if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result {
// Ignore any errors or warnings that happen because the new name is inaccurate
// NOTE: `new_name` already includes the tool name, so we don't have to add it again.
if let CheckLintNameResult::Ok(ids) = store.check_lint_name(&new_name, None) {
if let CheckLintNameResult::Ok(ids) =
store.check_lint_name(sess, &new_name, None, self.crate_attrs)
{
let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason);
for &id in ids {
self.check_gated_lint(id, attr.span);
@@ -578,7 +582,7 @@ impl<'s> LintLevelsBuilder<'s> {
}
}
fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
pub 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;
}