Skip to content

Commit 7bb40eb

Browse files
committed
Rollup merge of rust-lang#56992 - euclio:unknown-lint-suggestion, r=oli-obk
suggest similar lint names for unknown lints Fixes rust-lang#54737.
2 parents 10e4330 + 90726e1 commit 7bb40eb

7 files changed

+69
-47
lines changed

src/librustc/lint/context.rs

+23-7
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ use util::nodemap::FxHashMap;
4242
use std::default::Default as StdDefault;
4343
use syntax::ast;
4444
use syntax::edition;
45-
use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString};
45+
use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}};
4646
use errors::DiagnosticBuilder;
4747
use hir;
4848
use hir::def_id::LOCAL_CRATE;
4949
use hir::intravisit as hir_visit;
50+
use syntax::util::lev_distance::find_best_match_for_name;
5051
use syntax::visit as ast_visit;
5152

5253
/// Information about the registered lints.
@@ -139,8 +140,8 @@ struct LintGroup {
139140

140141
pub enum CheckLintNameResult<'a> {
141142
Ok(&'a [LintId]),
142-
/// Lint doesn't exist
143-
NoLint,
143+
/// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
144+
NoLint(Option<Symbol>),
144145
/// The lint is either renamed or removed. This is the warning
145146
/// message, and an optional new name (`None` if removed).
146147
Warning(String, Option<String>),
@@ -359,8 +360,14 @@ impl LintStore {
359360
CheckLintNameResult::Warning(ref msg, _) => {
360361
Some(sess.struct_warn(msg))
361362
},
362-
CheckLintNameResult::NoLint => {
363-
Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name))
363+
CheckLintNameResult::NoLint(suggestion) => {
364+
let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name);
365+
366+
if let Some(suggestion) = suggestion {
367+
err.help(&format!("did you mean: `{}`", suggestion));
368+
}
369+
370+
Some(err)
364371
}
365372
CheckLintNameResult::Tool(result) => match result {
366373
Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
@@ -464,7 +471,16 @@ impl LintStore {
464471
match self.by_name.get(&complete_name) {
465472
None => match self.lint_groups.get(&*complete_name) {
466473
// Now we are sure, that this lint exists nowhere
467-
None => CheckLintNameResult::NoLint,
474+
None => {
475+
let symbols = self.by_name.keys()
476+
.map(|name| Symbol::intern(&name))
477+
.collect::<Vec<_>>();
478+
479+
let suggestion =
480+
find_best_match_for_name(symbols.iter(), &lint_name.to_lowercase(), None);
481+
482+
CheckLintNameResult::NoLint(suggestion)
483+
}
468484
Some(LintGroup { lint_ids, depr, .. }) => {
469485
// Reaching this would be weird, but let's cover this case anyway
470486
if let Some(LintAlias { name, silent }) = depr {
@@ -484,7 +500,7 @@ impl LintStore {
484500
Some(&Id(ref id)) => {
485501
CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
486502
}
487-
_ => CheckLintNameResult::NoLint,
503+
_ => CheckLintNameResult::NoLint(None),
488504
}
489505
}
490506
}

src/librustc/lint/levels.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ impl<'a> LintLevelsBuilder<'a> {
385385
}
386386
err.emit();
387387
}
388-
CheckLintNameResult::NoLint => {
388+
CheckLintNameResult::NoLint(suggestion) => {
389389
let lint = builtin::UNKNOWN_LINTS;
390390
let (level, src) = self.sets.get_lint_level(lint,
391391
self.cur,
@@ -398,22 +398,17 @@ impl<'a> LintLevelsBuilder<'a> {
398398
src,
399399
Some(li.span.into()),
400400
&msg);
401-
if name.as_str().chars().any(|c| c.is_uppercase()) {
402-
let name_lower = name.as_str().to_lowercase().to_string();
403-
if let CheckLintNameResult::NoLint =
404-
store.check_lint_name(&name_lower, tool_name) {
405-
db.emit();
406-
} else {
407-
db.span_suggestion_with_applicability(
408-
li.span,
409-
"lowercase the lint name",
410-
name_lower,
411-
Applicability::MachineApplicable
412-
).emit();
413-
}
414-
} else {
415-
db.emit();
401+
402+
if let Some(suggestion) = suggestion {
403+
db.span_suggestion_with_applicability(
404+
li.span,
405+
"did you mean",
406+
suggestion.to_string(),
407+
Applicability::MachineApplicable,
408+
);
416409
}
410+
411+
db.emit();
417412
}
418413
}
419414
}

src/test/ui/lint/lint-unknown-lint-cmdline.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags:-D bogus
11+
// compile-flags:-D bogus -D dead_cod
1212

13-
// error-pattern:unknown lint
13+
// error-pattern:unknown lint: `bogus`
1414
// error-pattern:requested on the command line with `-D bogus`
15+
// error-pattern:unknown lint: `dead_cod`
16+
// error-pattern:requested on the command line with `-D dead_cod`
17+
// error-pattern:did you mean: `dead_code`
1518

1619
fn main() { }

src/test/ui/lint/lint-unknown-lint-cmdline.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ error[E0602]: unknown lint: `bogus`
22
|
33
= note: requested on the command line with `-D bogus`
44

5-
error: aborting due to previous error
5+
error[E0602]: unknown lint: `dead_cod`
6+
|
7+
= help: did you mean: `dead_code`
8+
= note: requested on the command line with `-D dead_cod`
9+
10+
error: aborting due to 2 previous errors
611

712
For more information about this error, try `rustc --explain E0602`.

src/test/ui/lint/lint-unknown-lint.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#![allow(not_a_real_lint)] //~ WARN unknown lint
12-
#![deny(unused)]
13-
fn main() { let unused = (); } //~ ERROR unused variable
11+
#![deny(unknown_lints)]
12+
13+
#![allow(not_a_real_lint)] //~ ERROR unknown lint
14+
15+
#![deny(dead_cod)] //~ ERROR unknown lint
16+
//~| HELP did you mean
17+
//~| SUGGESTION dead_code
18+
19+
fn main() {}
+13-16
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
1-
warning: unknown lint: `not_a_real_lint`
2-
--> $DIR/lint-unknown-lint.rs:11:10
1+
error: unknown lint: `not_a_real_lint`
2+
--> $DIR/lint-unknown-lint.rs:13:10
33
|
4-
LL | #![allow(not_a_real_lint)] //~ WARN unknown lint
4+
LL | #![allow(not_a_real_lint)] //~ ERROR unknown lint
55
| ^^^^^^^^^^^^^^^
66
|
7-
= note: #[warn(unknown_lints)] on by default
8-
9-
error: unused variable: `unused`
10-
--> $DIR/lint-unknown-lint.rs:13:17
11-
|
12-
LL | fn main() { let unused = (); } //~ ERROR unused variable
13-
| ^^^^^^ help: consider using `_unused` instead
14-
|
157
note: lint level defined here
16-
--> $DIR/lint-unknown-lint.rs:12:9
8+
--> $DIR/lint-unknown-lint.rs:11:9
9+
|
10+
LL | #![deny(unknown_lints)]
11+
| ^^^^^^^^^^^^^
12+
13+
error: unknown lint: `dead_cod`
14+
--> $DIR/lint-unknown-lint.rs:15:9
1715
|
18-
LL | #![deny(unused)]
19-
| ^^^^^^
20-
= note: #[deny(unused_variables)] implied by #[deny(unused)]
16+
LL | #![deny(dead_cod)] //~ ERROR unknown lint
17+
| ^^^^^^^^ help: did you mean: `dead_code`
2118

22-
error: aborting due to previous error
19+
error: aborting due to 2 previous errors
2320

src/test/ui/lint/not_found.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ warning: unknown lint: `DEAD_CODE`
1010
--> $DIR/not_found.rs:18:8
1111
|
1212
LL | #[warn(DEAD_CODE)]
13-
| ^^^^^^^^^ help: lowercase the lint name: `dead_code`
13+
| ^^^^^^^^^ help: did you mean: `dead_code`
1414

1515
warning: unknown lint: `Warnings`
1616
--> $DIR/not_found.rs:20:8
1717
|
1818
LL | #[deny(Warnings)]
19-
| ^^^^^^^^ help: lowercase the lint name: `warnings`
19+
| ^^^^^^^^ help: did you mean: `warnings`
2020

0 commit comments

Comments
 (0)