@@ -117,7 +117,7 @@ struct LintGroup {
117117pub enum CheckLintNameResult < ' a > {
118118 Ok ( & ' a [ LintId ] ) ,
119119 /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
120- NoLint ( Option < Symbol > ) ,
120+ NoLint ( Option < ( Symbol , bool ) > ) ,
121121 /// The lint refers to a tool that has not been registered.
122122 NoTool ,
123123 /// The lint has been renamed to a new name.
@@ -377,7 +377,7 @@ impl LintStore {
377377 debug ! ( "lints={:?}" , self . by_name. keys( ) . collect:: <Vec <_>>( ) ) ;
378378 let tool_prefix = format ! ( "{tool_name}::" ) ;
379379 return if self . by_name . keys ( ) . any ( |lint| lint. starts_with ( & tool_prefix) ) {
380- self . no_lint_suggestion ( & complete_name)
380+ self . no_lint_suggestion ( & complete_name, tool_name . as_str ( ) )
381381 } else {
382382 // 2. The tool isn't currently running, so no lints will be registered.
383383 // To avoid giving a false positive, ignore all unknown lints.
@@ -419,29 +419,49 @@ impl LintStore {
419419 }
420420 }
421421
422- fn no_lint_suggestion ( & self , lint_name : & str ) -> CheckLintNameResult < ' _ > {
422+ fn no_lint_suggestion ( & self , lint_name : & str , tool_name : & str ) -> CheckLintNameResult < ' _ > {
423423 let name_lower = lint_name. to_lowercase ( ) ;
424424
425425 if lint_name. chars ( ) . any ( char:: is_uppercase) && self . find_lints ( & name_lower) . is_ok ( ) {
426426 // First check if the lint name is (partly) in upper case instead of lower case...
427- return CheckLintNameResult :: NoLint ( Some ( Symbol :: intern ( & name_lower) ) ) ;
427+ return CheckLintNameResult :: NoLint ( Some ( ( Symbol :: intern ( & name_lower) , false ) ) ) ;
428428 }
429+
429430 // ...if not, search for lints with a similar name
430- // Note: find_best_match_for_name depends on the sort order of its input vector.
431- // To ensure deterministic output, sort elements of the lint_groups hash map.
432431 // Also, never suggest deprecated lint groups.
433- // We will soon sort, so the initial order does not matter.
434432 #[ allow( rustc:: potential_query_instability) ]
435- let mut groups: Vec < _ > = self
433+ let groups: Vec < _ > = self
436434 . lint_groups
437435 . iter ( )
438436 . filter_map ( |( k, LintGroup { depr, .. } ) | depr. is_none ( ) . then_some ( k) )
439437 . collect ( ) ;
440- groups. sort ( ) ;
441438 let groups = groups. iter ( ) . map ( |k| Symbol :: intern ( k) ) ;
442439 let lints = self . lints . iter ( ) . map ( |l| Symbol :: intern ( & l. name_lower ( ) ) ) ;
443- let names: Vec < Symbol > = groups. chain ( lints) . collect ( ) ;
444- let suggestion = find_best_match_for_name ( & names, Symbol :: intern ( & name_lower) , None ) ;
440+ let mut names: Vec < Symbol > = groups. chain ( lints) . collect ( ) ;
441+ // Here, a little bit of extra hack
442+ // we use the lint names from rustc and to mock the tool name,
443+ // if it's selected we then strip to the right suggestion with `true` for from_rustc
444+ // so we can handle these cases:
445+ // 1. suggest `missing_docs` from rustc for `clippy::missing_docs`
446+ // 2. suggest `dead_code` from rustc for `clippy::dead_cod`
447+ let rustc_names = self
448+ . by_name
449+ . keys ( )
450+ . map ( |k| Symbol :: intern ( & format ! ( "{tool_name}::{k}" ) ) )
451+ . collect :: < Vec < _ > > ( ) ;
452+ names. extend ( rustc_names. clone ( ) ) ;
453+ // Note: find_best_match_for_name depends on the sort order of its input vector.
454+ // Sort elements here to ensure deterministic output
455+ names. sort ( ) ;
456+ let suggestion =
457+ find_best_match_for_name ( & names, Symbol :: intern ( & name_lower) , None ) . map ( |s| {
458+ if rustc_names. contains ( & s) {
459+ let stripped = s. as_str ( ) . strip_prefix ( & format ! ( "{tool_name}::" ) ) . unwrap ( ) ;
460+ ( Symbol :: intern ( stripped) , true )
461+ } else {
462+ ( s, false )
463+ }
464+ } ) ;
445465 CheckLintNameResult :: NoLint ( suggestion)
446466 }
447467
@@ -454,7 +474,7 @@ impl LintStore {
454474 match self . by_name . get ( & complete_name) {
455475 None => match self . lint_groups . get ( & * complete_name) {
456476 // Now we are sure, that this lint exists nowhere
457- None => self . no_lint_suggestion ( lint_name) ,
477+ None => self . no_lint_suggestion ( lint_name, tool_name ) ,
458478 Some ( LintGroup { lint_ids, depr, .. } ) => {
459479 // Reaching this would be weird, but let's cover this case anyway
460480 if let Some ( LintAlias { name, silent } ) = depr {
0 commit comments