about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias KrΓΌger <matthias.krueger@famsik.de>2025-02-22 11:36:44 +0100
committerGitHub <noreply@github.com>2025-02-22 11:36:44 +0100
commit72e41e5d650a392914a6faa56b81072a2fe16ea2 (patch)
tree7c0ba6ee1278477de69beaeaf15e88b8bfcbdfc8
parent37e0d138cffd8d3b3d9b9da75f2645e1ba87dacb (diff)
parentec88bc2e00985e99923ff3de966a947daa63c567 (diff)
downloadrust-72e41e5d650a392914a6faa56b81072a2fe16ea2.tar.gz
rust-72e41e5d650a392914a6faa56b81072a2fe16ea2.zip
Rollup merge of #137356 - nik-rev:FERRIS, r=compiler-errors
Ferris πŸ¦€ Identifier naming conventions

You cannot use Ferris as an identifier in Rust, this code will suggest to correct the  πŸ¦€ to `ferris`:

```rs
fn main() {
  let  πŸ¦€ = 4;
}
```

But it also suggests to correct to `ferris` in these cases, too:

```rs
struct  πŸ¦€ {}
fn main() {}
```

^ suggests: `ferris`
~ with this PR: `Ferris`

```rs
static πŸ¦€: &str = "ferris!";
fn main() {}
```

^ suggests: `ferris`
~ with this PR: `FERRIS`

This is my first pull requests here!
-rw-r--r--compiler/rustc_interface/src/errors.rs3
-rw-r--r--compiler/rustc_interface/src/passes.rs35
-rw-r--r--tests/ui/parser/ferris-static-mut.rs3
-rw-r--r--tests/ui/parser/ferris-static-mut.stderr8
-rw-r--r--tests/ui/parser/ferris-struct.rs3
-rw-r--r--tests/ui/parser/ferris-struct.stderr8
6 files changed, 58 insertions, 2 deletions
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index ca4e556dcdb..eed729a1777 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -24,8 +24,9 @@ pub(crate) struct CrateNameInvalid<'a> {
 pub struct FerrisIdentifier {
     #[primary_span]
     pub spans: Vec<Span>,
-    #[suggestion(code = "ferris", applicability = "maybe-incorrect")]
+    #[suggestion(code = "{ferris_fix}", applicability = "maybe-incorrect")]
     pub first_span: Span,
+    pub ferris_fix: &'static str,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 2d3c7f834e9..553215ca0af 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -305,8 +305,41 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
         for (ident, mut spans) in identifiers.drain(..) {
             spans.sort();
             if ident == sym::ferris {
+                enum FerrisFix {
+                    SnakeCase,
+                    ScreamingSnakeCase,
+                    PascalCase,
+                }
+
+                impl FerrisFix {
+                    const fn as_str(self) -> &'static str {
+                        match self {
+                            FerrisFix::SnakeCase => "ferris",
+                            FerrisFix::ScreamingSnakeCase => "FERRIS",
+                            FerrisFix::PascalCase => "Ferris",
+                        }
+                    }
+                }
+
                 let first_span = spans[0];
-                sess.dcx().emit_err(errors::FerrisIdentifier { spans, first_span });
+                let prev_source = sess.psess.source_map().span_to_prev_source(first_span);
+                let ferris_fix = prev_source
+                    .map_or(FerrisFix::SnakeCase, |source| {
+                        let mut source_before_ferris = source.trim_end().split_whitespace().rev();
+                        match source_before_ferris.next() {
+                            Some("struct" | "trait" | "mod" | "union" | "type" | "enum") => {
+                                FerrisFix::PascalCase
+                            }
+                            Some("const" | "static") => FerrisFix::ScreamingSnakeCase,
+                            Some("mut") if source_before_ferris.next() == Some("static") => {
+                                FerrisFix::ScreamingSnakeCase
+                            }
+                            _ => FerrisFix::SnakeCase,
+                        }
+                    })
+                    .as_str();
+
+                sess.dcx().emit_err(errors::FerrisIdentifier { spans, first_span, ferris_fix });
             } else {
                 sess.dcx().emit_err(errors::EmojiIdentifier { spans, ident });
             }
diff --git a/tests/ui/parser/ferris-static-mut.rs b/tests/ui/parser/ferris-static-mut.rs
new file mode 100644
index 00000000000..67186982691
--- /dev/null
+++ b/tests/ui/parser/ferris-static-mut.rs
@@ -0,0 +1,3 @@
+static mut πŸ¦€: &str = "ferris!";//~ ERROR Ferris cannot be used as an identifier
+
+fn main() {}
diff --git a/tests/ui/parser/ferris-static-mut.stderr b/tests/ui/parser/ferris-static-mut.stderr
new file mode 100644
index 00000000000..6af85bbaf7d
--- /dev/null
+++ b/tests/ui/parser/ferris-static-mut.stderr
@@ -0,0 +1,8 @@
+error: Ferris cannot be used as an identifier
+  --> $DIR/ferris-static-mut.rs:1:12
+   |
+LL | static mut πŸ¦€: &str = "ferris!";
+   |            ^^ help: try using their name instead: `FERRIS`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/ferris-struct.rs b/tests/ui/parser/ferris-struct.rs
new file mode 100644
index 00000000000..581957fa775
--- /dev/null
+++ b/tests/ui/parser/ferris-struct.rs
@@ -0,0 +1,3 @@
+struct πŸ¦€ {}//~ ERROR Ferris cannot be used as an identifier
+
+fn main() {}
diff --git a/tests/ui/parser/ferris-struct.stderr b/tests/ui/parser/ferris-struct.stderr
new file mode 100644
index 00000000000..34fe28c6297
--- /dev/null
+++ b/tests/ui/parser/ferris-struct.stderr
@@ -0,0 +1,8 @@
+error: Ferris cannot be used as an identifier
+  --> $DIR/ferris-struct.rs:1:8
+   |
+LL | struct πŸ¦€ {}
+   |        ^^ help: try using their name instead: `Ferris`
+
+error: aborting due to 1 previous error
+