Improve slug name error

This commit is contained in:
mejrs 2022-11-13 13:10:36 +01:00
parent d494502f64
commit e8e47e0873
4 changed files with 77 additions and 50 deletions

View File

@ -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();
struct Mismatch {
slug_name: String,
crate_name: String,
slug_prefix: String,
}
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();
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()?;
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 we're not in a "rustc_" crate, bail.
let Some(("rustc", slug_prefix)) = crate_name.split_once("_") else { return None };
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_"
}
};
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
}
}
}

View File

@ -1,4 +1,5 @@
#![feature(allow_internal_unstable)]
#![feature(if_let_guard)]
#![feature(never_type)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_span)]

View File

@ -0,0 +1,24 @@
// rustc-env:CARGO_CRATE_NAME=rustc_dummy
#![feature(rustc_private)]
#![crate_type = "lib"]
extern crate rustc_span;
use rustc_span::symbol::Ident;
use rustc_span::Span;
extern crate rustc_macros;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
extern crate rustc_middle;
use rustc_middle::ty::Ty;
extern crate rustc_errors;
use rustc_errors::{Applicability, MultiSpan};
extern crate rustc_session;
#[derive(Diagnostic)]
#[diag(compiletest_example, code = "E0123")]
//~^ ERROR diagnostic slug and crate name do not match
struct Hello {}

View File

@ -0,0 +1,11 @@
error: diagnostic slug and crate name do not match
--> $DIR/enforce_slug_naming.rs:22:8
|
LL | #[diag(compiletest_example, code = "E0123")]
| ^^^^^^^^^^^^^^^^^^^
|
= note: slug is `compiletest_example` but the crate name is `rustc_dummy`
= help: expected a slug starting with `dummy_...`
error: aborting due to previous error