@@ -42,11 +42,12 @@ use util::nodemap::FxHashMap;
4242use  std:: default:: Default  as  StdDefault ; 
4343use  syntax:: ast; 
4444use  syntax:: edition; 
45- use  syntax_pos:: { MultiSpan ,  Span ,  symbol:: LocalInternedString } ; 
45+ use  syntax_pos:: { MultiSpan ,  Span ,  symbol:: { LocalInternedString ,   Symbol } } ; 
4646use  errors:: DiagnosticBuilder ; 
4747use  hir; 
4848use  hir:: def_id:: LOCAL_CRATE ; 
4949use  hir:: intravisit as  hir_visit; 
50+ use  syntax:: util:: lev_distance:: find_best_match_for_name; 
5051use  syntax:: visit as  ast_visit; 
5152
5253/// Information about the registered lints. 
@@ -139,8 +140,8 @@ struct LintGroup {
139140
140141pub  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} 
0 commit comments