@@ -3519,23 +3519,68 @@ pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
35193519
35203520/// Whether the original and suggested code are visually similar enough to warrant extra wording. 
35213521pub  fn  is_case_difference ( sm :  & SourceMap ,  suggested :  & str ,  sp :  Span )  -> bool  { 
3522-     // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode. 
35233522    let  found = match  sm. span_to_snippet ( sp)  { 
35243523        Ok ( snippet)  => snippet, 
35253524        Err ( e)  => { 
35263525            warn ! ( error = ?e,  "Invalid span {:?}" ,  sp) ; 
35273526            return  false ; 
35283527        } 
35293528    } ; 
3530-     let  ascii_confusables = & [ 'c' ,  'f' ,  'i' ,  'k' ,  'o' ,  's' ,  'u' ,  'v' ,  'w' ,  'x' ,  'y' ,  'z' ] ; 
3531-     // All the chars that differ in capitalization are confusable (above): 
3532-     let  confusable = iter:: zip ( found. chars ( ) ,  suggested. chars ( ) ) 
3533-         . filter ( |( f,  s) | f != s) 
3534-         . all ( |( f,  s) | ascii_confusables. contains ( & f)  || ascii_confusables. contains ( & s) ) ; 
3535-     confusable && found. to_lowercase ( )  == suggested. to_lowercase ( ) 
3536-             // FIXME: We sometimes suggest the same thing we already have, which is a 
3537-             //        bug, but be defensive against that here. 
3538-             && found != suggested
3529+ 
3530+     // Check if the strings are identical after case normalization 
3531+     if  found. to_lowercase ( )  == suggested. to_lowercase ( )  { 
3532+         // Check if they differ only in case 
3533+         let  ascii_confusables = & [ 'c' ,  'f' ,  'i' ,  'k' ,  'o' ,  's' ,  'u' ,  'v' ,  'w' ,  'x' ,  'y' ,  'z' ] ; 
3534+         let  confusable = iter:: zip ( found. chars ( ) ,  suggested. chars ( ) ) 
3535+             . filter ( |( f,  s) | f != s) 
3536+             . all ( |( f,  s) | ascii_confusables. contains ( & f)  || ascii_confusables. contains ( & s) ) ; 
3537+ 
3538+         if  confusable
3539+         // FIXME: We sometimes suggest the same thing we already have, which is a 
3540+         // bug, but be defensive against that here. 
3541+         && found != suggested
3542+         { 
3543+             return  true ; 
3544+         } 
3545+     } 
3546+ 
3547+     // Check for digit-letter confusables (like 0 vs O, 1 vs l, etc.) 
3548+     if  found. len ( )  == suggested. len ( )  { 
3549+         let  digit_letter_confusables = [ 
3550+             ( '0' ,  'O' ) , 
3551+             ( 'O' ,  '0' ) , 
3552+             ( '1' ,  'l' ) , 
3553+             ( 'l' ,  '1' ) , 
3554+             ( '5' ,  'S' ) , 
3555+             ( 'S' ,  '5' ) , 
3556+             ( '8' ,  'B' ) , 
3557+             ( 'B' ,  '8' ) , 
3558+             ( '9' ,  'g' ) , 
3559+             ( 'g' ,  '9' ) , 
3560+         ] ; 
3561+ 
3562+         let  mut  has_confusable = false ; 
3563+         // To ensure all the differences are confusables, 
3564+         // we need to check that all the differences 
3565+         let  mut  all_confusable = true ; 
3566+ 
3567+         for  ( f,  s)  in  iter:: zip ( found. chars ( ) ,  suggested. chars ( ) )  { 
3568+             if  f != s { 
3569+                 if  digit_letter_confusables. contains ( & ( f,  s) )  { 
3570+                     has_confusable = true ; 
3571+                 }  else  { 
3572+                     all_confusable = false ; 
3573+                     break ; 
3574+                 } 
3575+             } 
3576+         } 
3577+ 
3578+         if  has_confusable && all_confusable && found != suggested { 
3579+             return  true ; 
3580+         } 
3581+     } 
3582+ 
3583+     false 
35393584} 
35403585
35413586pub ( crate )  fn  should_show_source_code ( 
0 commit comments