@@ -302,7 +302,57 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
302302 spans. sort ( ) ;
303303 if ident == sym:: ferris {
304304 let first_span = spans[ 0 ] ;
305- sess. dcx ( ) . emit_err ( errors:: FerrisIdentifier { spans, first_span } ) ;
305+
306+ enum FerrisFix {
307+ SnakeCase ,
308+ ScreamingSnakeCase ,
309+ PascalCase ,
310+ }
311+
312+ impl FerrisFix {
313+ const fn as_str ( self ) -> & ' static str {
314+ match self {
315+ FerrisFix :: SnakeCase => "ferris" ,
316+ FerrisFix :: ScreamingSnakeCase => "FERRIS" ,
317+ FerrisFix :: PascalCase => "Ferris" ,
318+ }
319+ }
320+ }
321+
322+ // Obtain the symbol that is before Ferris.
323+ let symbols = & sess. psess . symbol_gallery . symbols . lock ( ) ;
324+ let mut symbols: Vec < _ > = symbols. iter ( ) . collect ( ) ;
325+
326+ // sort by spans
327+ symbols. sort_unstable_by_key ( |k| k. 1 ) ;
328+ let ferris_fix = match symbols. binary_search_by ( |( _, span) | span. cmp ( & & first_span) )
329+ {
330+ Ok ( index) | Err ( index) if index > 0 => {
331+ let keyword = symbols[ index - 1 ] . 0 . as_str ( ) ;
332+ // if we have e.g. `static mut`
333+ if keyword == "mut" {
334+ let keyword_before =
335+ symbols. get ( index - 2 ) . map ( |s| s. 0 . as_str ( ) ) . unwrap_or_default ( ) ;
336+ if keyword_before == "static" {
337+ FerrisFix :: ScreamingSnakeCase
338+ } else {
339+ FerrisFix :: SnakeCase
340+ }
341+ } else {
342+ match keyword {
343+ "const" | "static" => FerrisFix :: ScreamingSnakeCase ,
344+ "struct" | "trait" | "mod" | "union" | "type" | "enum" => {
345+ FerrisFix :: PascalCase
346+ }
347+ _ => FerrisFix :: SnakeCase ,
348+ }
349+ }
350+ }
351+ _ => FerrisFix :: SnakeCase ,
352+ }
353+ . as_str ( ) ;
354+
355+ sess. dcx ( ) . emit_err ( errors:: FerrisIdentifier { spans, first_span, ferris_fix } ) ;
306356 } else {
307357 sess. dcx ( ) . emit_err ( errors:: EmojiIdentifier { spans, ident } ) ;
308358 }
0 commit comments