about summary refs log tree commit diff
path: root/compiler/rustc_macros/src
diff options
context:
space:
mode:
authormejrs <>2022-11-13 13:10:36 +0100
committermejrs <>2022-11-21 15:24:51 +0100
commite8e47e08731599e95724680ffbc574455bfeb233 (patch)
tree92d025ba37a0f72c41eaee291ccb9100ca6e0140 /compiler/rustc_macros/src
parentd494502f64ea1b3a3164a13ce20cd1eba89c8141 (diff)
downloadrust-e8e47e08731599e95724680ffbc574455bfeb233.tar.gz
rust-e8e47e08731599e95724680ffbc574455bfeb233.zip
Improve slug name error
Diffstat (limited to 'compiler/rustc_macros/src')
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic.rs97
-rw-r--r--compiler/rustc_macros/src/lib.rs1
2 files changed, 45 insertions, 53 deletions
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index c3772475769..be9821c00f5 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -5,6 +5,7 @@ use crate::diagnostics::error::{span_err, DiagnosticDeriveError};
 use crate::diagnostics::utils::SetOnce;
 use proc_macro2::TokenStream;
 use quote::quote;
+use syn::spanned::Spanned;
 use synstructure::Structure;
 
 /// The central struct for constructing the `into_diagnostic` method from an annotated struct.
@@ -45,10 +46,19 @@ impl<'a> DiagnosticDerive<'a> {
                         .emit();
                     return DiagnosticDeriveError::ErrorHandled.to_compile_error();
                 }
+                Some(slug) if let Some( Mismatch { slug_name, crate_name, slug_prefix }) = Mismatch::check(slug) => {
+                    span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
+                        .note(&format!(
+                            "slug is `{slug_name}` but the crate name is `{crate_name}`"
+                        ))
+                        .help(&format!(
+                            "expected a slug starting with `{slug_prefix}_...`"
+                        ))
+                        .emit();
+                    return DiagnosticDeriveError::ErrorHandled.to_compile_error();
+                }
                 Some(slug) => {
-                    let check = make_check(slug);
                     quote! {
-                        #check
                         let mut #diag = #handler.struct_diagnostic(rustc_errors::fluent::#slug);
                     }
                 }
@@ -130,11 +140,19 @@ impl<'a> LintDiagnosticDerive<'a> {
                         .emit();
                     return DiagnosticDeriveError::ErrorHandled.to_compile_error();
                 }
+                Some(slug) if let Some( Mismatch { slug_name, crate_name, slug_prefix }) = Mismatch::check(slug) => {
+                    span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
+                        .note(&format!(
+                            "slug is `{slug_name}` but the crate name is `{crate_name}`"
+                        ))
+                        .help(&format!(
+                            "expected a slug starting with `{slug_prefix}_...`"
+                        ))
+                        .emit();
+                    return DiagnosticDeriveError::ErrorHandled.to_compile_error();
+                }
                 Some(slug) => {
-                    let check = make_check(slug);
-
                     quote! {
-                        #check
                         rustc_errors::fluent::#slug.into()
                     }
                 }
@@ -161,53 +179,26 @@ impl<'a> LintDiagnosticDerive<'a> {
     }
 }
 
-/// Checks whether the slug starts with the crate name it's in.
-fn make_check(slug: &syn::Path) -> TokenStream {
-    quote! {
-        const _: () = {
-            const krate_str: &str = match option_env!("CARGO_CRATE_NAME") {
-                Some(c) => c,
-                None => "",
-            };
-            const krate: &[u8] = krate_str.as_bytes();
-
-            if krate.len() > 6
-                && krate[0] == b'r'
-                && krate[1] == b'u'
-                && krate[2] == b's'
-                && krate[3] == b't'
-                && krate[4] == b'c'
-                && krate[5] == b'_'
-            {
-                let slug = stringify!(#slug).as_bytes();
-
-                let mut pos = 0;
-                loop {
-                    let b = slug[pos];
-                    if krate.len() == pos + 6 {
-                        if b != b'_' {
-                            panic!(concat!(
-                                "slug \"",
-                                stringify!(#slug),
-                                "\" does not match the crate it is in"
-                            ));
-                        }
-                        break;
-                    }
-                    let a = krate[pos + 6];
-
-                    if a != b {
-                        panic!(concat!(
-                            "slug \"",
-                            stringify!(#slug),
-                            "\" does not match the crate it is in"
-                        ));
-                    }
-                    pos += 1;
-                }
-            } else {
-                // Crate does not start with "rustc_"
-            }
-        };
+struct Mismatch {
+    slug_name: String,
+    crate_name: String,
+    slug_prefix: String,
+}
+
+impl Mismatch {
+    /// Checks whether the slug starts with the crate name it's in.
+    fn check(slug: &syn::Path) -> Option<Mismatch> {
+        // If this is missing we're probably in a test, so bail.
+        let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
+
+        // If we're not in a "rustc_" crate, bail.
+        let Some(("rustc", slug_prefix)) = crate_name.split_once("_") else { return None };
+
+        let slug_name = slug.segments.first()?.ident.to_string();
+        if !slug_name.starts_with(slug_prefix) {
+            Some(Mismatch { slug_name, slug_prefix: slug_prefix.to_string(), crate_name })
+        } else {
+            None
+        }
     }
 }
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 36bda3e0f6b..a2a01b66690 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -1,4 +1,5 @@
 #![feature(allow_internal_unstable)]
+#![feature(if_let_guard)]
 #![feature(never_type)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_span)]