Skip to content

Commit 8b4f538

Browse files
committed
Unify lint tool and lint name checking
This shares a little more code between checking command line and attribute lint specifications.
1 parent 1e0db4c commit 8b4f538

File tree

3 files changed

+73
-40
lines changed

3 files changed

+73
-40
lines changed

compiler/rustc_lint/src/context.rs

+37-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
1717
use self::TargetLint::*;
1818

19-
use crate::levels::LintLevelsBuilder;
19+
use crate::levels::{is_known_lint_tool, LintLevelsBuilder};
2020
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
2121
use rustc_ast as ast;
2222
use rustc_data_structures::fx::FxHashMap;
@@ -129,6 +129,8 @@ pub enum CheckLintNameResult<'a> {
129129
Ok(&'a [LintId]),
130130
/// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
131131
NoLint(Option<Symbol>),
132+
/// The lint refers to a tool that has not been registered.
133+
NoTool,
132134
/// The lint is either renamed or removed. This is the warning
133135
/// message, and an optional new name (`None` if removed).
134136
Warning(String, Option<String>),
@@ -334,16 +336,17 @@ impl LintStore {
334336
}
335337
}
336338

337-
/// Checks the validity of lint names derived from the command line. Returns
338-
/// true if the lint is valid, false otherwise.
339+
/// Checks the validity of lint names derived from the command line.
339340
pub fn check_lint_name_cmdline(
340341
&self,
341342
sess: &Session,
342343
lint_name: &str,
343-
level: Option<Level>,
344-
) -> bool {
344+
level: Level,
345+
crate_attrs: &[ast::Attribute],
346+
) {
345347
let (tool_name, lint_name) = parse_lint_and_tool_name(lint_name);
346-
let db = match self.check_lint_name(lint_name, tool_name) {
348+
349+
let db = match self.check_lint_and_tool_name(sess, tool_name, lint_name, crate_attrs) {
347350
CheckLintNameResult::Ok(_) => None,
348351
CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
349352
CheckLintNameResult::NoLint(suggestion) => {
@@ -365,6 +368,13 @@ impl LintStore {
365368
))),
366369
_ => None,
367370
},
371+
CheckLintNameResult::NoTool => Some(struct_span_err!(
372+
sess,
373+
DUMMY_SP,
374+
E0602,
375+
"unknown lint tool: `{}`",
376+
tool_name.unwrap()
377+
)),
368378
};
369379

370380
if let Some(mut db) = db {
@@ -398,6 +408,22 @@ impl LintStore {
398408
}
399409
}
400410

411+
pub fn check_lint_and_tool_name(
412+
&self,
413+
sess: &Session,
414+
tool_name: Option<Symbol>,
415+
lint_name: &str,
416+
crate_attrs: &[ast::Attribute],
417+
) -> CheckLintNameResult<'_> {
418+
if let Some(tool_name) = tool_name {
419+
if !is_known_lint_tool(tool_name, sess, crate_attrs) {
420+
return CheckLintNameResult::NoTool;
421+
}
422+
}
423+
424+
self.check_lint_name(lint_name, tool_name)
425+
}
426+
401427
/// Checks the name of a lint for its existence, and whether it was
402428
/// renamed or removed. Generates a DiagnosticBuilder containing a
403429
/// warning for renamed and removed lints. This is over both lint
@@ -1028,7 +1054,11 @@ impl<'tcx> LayoutOf for LateContext<'tcx> {
10281054

10291055
pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
10301056
match lint_name.split_once("::") {
1031-
Some((tool_name, lint_name)) => (Some(Symbol::intern(tool_name)), lint_name),
1057+
Some((tool_name, lint_name)) => {
1058+
let tool_name = Symbol::intern(tool_name);
1059+
1060+
(Some(tool_name), lint_name)
1061+
}
10321062
None => (None, lint_name),
10331063
}
10341064
}

compiler/rustc_lint/src/levels.rs

+32-29
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl<'s> LintLevelsBuilder<'s> {
8888
self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
8989

9090
for &(ref lint_name, level) in &sess.opts.lint_opts {
91-
store.check_lint_name_cmdline(sess, &lint_name, level);
91+
store.check_lint_name_cmdline(sess, &lint_name, level, self.crate_attrs);
9292
let orig_level = level;
9393

9494
// If the cap is less than this specified level, e.g., if we've got
@@ -110,7 +110,7 @@ impl<'s> LintLevelsBuilder<'s> {
110110
}
111111

112112
for lint_name in &sess.opts.force_warns {
113-
store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn);
113+
store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn, self.crate_attrs);
114114
let lints = store
115115
.find_lints(lint_name)
116116
.unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids"));
@@ -321,33 +321,15 @@ impl<'s> LintLevelsBuilder<'s> {
321321
continue;
322322
}
323323
};
324-
let tool_name = if meta_item.path.segments.len() > 1 {
325-
let tool_ident = meta_item.path.segments[0].ident;
326-
if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) {
327-
let mut err = struct_span_err!(
328-
sess,
329-
tool_ident.span,
330-
E0710,
331-
"unknown tool name `{}` found in scoped lint: `{}`",
332-
tool_ident.name,
333-
pprust::path_to_string(&meta_item.path),
334-
);
335-
if sess.is_nightly_build() {
336-
err.help(&format!(
337-
"add `#![register_tool({})]` to the crate root",
338-
tool_ident.name
339-
));
340-
}
341-
err.emit();
342-
continue;
343-
}
344-
345-
Some(meta_item.path.segments.remove(0).ident.name)
324+
let tool_ident = if meta_item.path.segments.len() > 1 {
325+
Some(meta_item.path.segments.remove(0).ident)
346326
} else {
347327
None
348328
};
329+
let tool_name = tool_ident.map(|ident| ident.name);
349330
let name = pprust::path_to_string(&meta_item.path);
350-
let lint_result = store.check_lint_name(&name, tool_name);
331+
let lint_result =
332+
store.check_lint_and_tool_name(sess, tool_name, &name, self.crate_attrs);
351333
match &lint_result {
352334
CheckLintNameResult::Ok(ids) => {
353335
let src = LintLevelSource::Node(
@@ -364,7 +346,8 @@ impl<'s> LintLevelsBuilder<'s> {
364346
CheckLintNameResult::Tool(result) => {
365347
match *result {
366348
Ok(ids) => {
367-
let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
349+
let complete_name =
350+
&format!("{}::{}", tool_ident.unwrap().name, name);
368351
let src = LintLevelSource::Node(
369352
Symbol::intern(complete_name),
370353
sp,
@@ -419,6 +402,26 @@ impl<'s> LintLevelsBuilder<'s> {
419402
}
420403
}
421404

405+
&CheckLintNameResult::NoTool => {
406+
let mut err = struct_span_err!(
407+
sess,
408+
tool_ident.map_or(DUMMY_SP, |ident| ident.span),
409+
E0710,
410+
"unknown tool name `{}` found in scoped lint: `{}::{}`",
411+
tool_name.unwrap(),
412+
tool_name.unwrap(),
413+
pprust::path_to_string(&meta_item.path),
414+
);
415+
if sess.is_nightly_build() {
416+
err.help(&format!(
417+
"add `#![register_tool({})]` to the crate root",
418+
tool_name.unwrap()
419+
));
420+
}
421+
err.emit();
422+
continue;
423+
}
424+
422425
_ if !self.warn_about_weird_lints => {}
423426

424427
CheckLintNameResult::Warning(msg, renamed) => {
@@ -450,8 +453,8 @@ impl<'s> LintLevelsBuilder<'s> {
450453
let (level, src) =
451454
self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
452455
struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
453-
let name = if let Some(tool_name) = tool_name {
454-
format!("{}::{}", tool_name, name)
456+
let name = if let Some(tool_ident) = tool_ident {
457+
format!("{}::{}", tool_ident.name, name)
455458
} else {
456459
name.to_string()
457460
};
@@ -578,7 +581,7 @@ impl<'s> LintLevelsBuilder<'s> {
578581
}
579582
}
580583

581-
fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
584+
pub fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
582585
if [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item) {
583586
return true;
584587
}

src/test/ui/lint/command-line-register-unknown-lint-tool.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0602]: unknown lint: `unknown_tool::foo`
1+
error[E0602]: unknown lint tool: `unknown_tool`
22
|
3-
= note: requested on the command line with `-A unknown_tool::foo`
3+
= note: requested on the command line with `-A foo`
44

5-
error[E0602]: unknown lint: `unknown_tool::foo`
5+
error[E0602]: unknown lint tool: `unknown_tool`
66
|
7-
= note: requested on the command line with `-A unknown_tool::foo`
7+
= note: requested on the command line with `-A foo`
88

99
error: aborting due to 2 previous errors
1010

0 commit comments

Comments
 (0)