@@ -5,6 +5,7 @@ use crate::diagnostics::error::{span_err, DiagnosticDeriveError};
5
5
use crate :: diagnostics:: utils:: SetOnce ;
6
6
use proc_macro2:: TokenStream ;
7
7
use quote:: quote;
8
+ use syn:: spanned:: Spanned ;
8
9
use synstructure:: Structure ;
9
10
10
11
/// The central struct for constructing the `into_diagnostic` method from an annotated struct.
@@ -45,10 +46,19 @@ impl<'a> DiagnosticDerive<'a> {
45
46
. emit ( ) ;
46
47
return DiagnosticDeriveError :: ErrorHandled . to_compile_error ( ) ;
47
48
}
49
+ Some ( slug) if let Some ( Mismatch { slug_name, crate_name, slug_prefix } ) = Mismatch :: check ( slug) => {
50
+ span_err ( slug. span ( ) . unwrap ( ) , "diagnostic slug and crate name do not match" )
51
+ . note ( & format ! (
52
+ "slug is `{slug_name}` but the crate name is `{crate_name}`"
53
+ ) )
54
+ . help ( & format ! (
55
+ "expected a slug starting with `{slug_prefix}_...`"
56
+ ) )
57
+ . emit ( ) ;
58
+ return DiagnosticDeriveError :: ErrorHandled . to_compile_error ( ) ;
59
+ }
48
60
Some ( slug) => {
49
- let check = make_check ( slug) ;
50
61
quote ! {
51
- #check
52
62
let mut #diag = #handler. struct_diagnostic( rustc_errors:: fluent:: #slug) ;
53
63
}
54
64
}
@@ -130,11 +140,19 @@ impl<'a> LintDiagnosticDerive<'a> {
130
140
. emit ( ) ;
131
141
return DiagnosticDeriveError :: ErrorHandled . to_compile_error ( ) ;
132
142
}
143
+ Some ( slug) if let Some ( Mismatch { slug_name, crate_name, slug_prefix } ) = Mismatch :: check ( slug) => {
144
+ span_err ( slug. span ( ) . unwrap ( ) , "diagnostic slug and crate name do not match" )
145
+ . note ( & format ! (
146
+ "slug is `{slug_name}` but the crate name is `{crate_name}`"
147
+ ) )
148
+ . help ( & format ! (
149
+ "expected a slug starting with `{slug_prefix}_...`"
150
+ ) )
151
+ . emit ( ) ;
152
+ return DiagnosticDeriveError :: ErrorHandled . to_compile_error ( ) ;
153
+ }
133
154
Some ( slug) => {
134
- let check = make_check ( slug) ;
135
-
136
155
quote ! {
137
- #check
138
156
rustc_errors:: fluent:: #slug. into( )
139
157
}
140
158
}
@@ -161,53 +179,26 @@ impl<'a> LintDiagnosticDerive<'a> {
161
179
}
162
180
}
163
181
164
- /// Checks whether the slug starts with the crate name it's in.
165
- fn make_check ( slug : & syn:: Path ) -> TokenStream {
166
- quote ! {
167
- const _: ( ) = {
168
- const krate_str: & str = match option_env!( "CARGO_CRATE_NAME" ) {
169
- Some ( c) => c,
170
- None => "" ,
171
- } ;
172
- const krate: & [ u8 ] = krate_str. as_bytes( ) ;
173
-
174
- if krate. len( ) > 6
175
- && krate[ 0 ] == b'r'
176
- && krate[ 1 ] == b'u'
177
- && krate[ 2 ] == b's'
178
- && krate[ 3 ] == b't'
179
- && krate[ 4 ] == b'c'
180
- && krate[ 5 ] == b'_'
181
- {
182
- let slug = stringify!( #slug) . as_bytes( ) ;
183
-
184
- let mut pos = 0 ;
185
- loop {
186
- let b = slug[ pos] ;
187
- if krate. len( ) == pos + 6 {
188
- if b != b'_' {
189
- panic!( concat!(
190
- "slug \" " ,
191
- stringify!( #slug) ,
192
- "\" does not match the crate it is in"
193
- ) ) ;
194
- }
195
- break ;
196
- }
197
- let a = krate[ pos + 6 ] ;
198
-
199
- if a != b {
200
- panic!( concat!(
201
- "slug \" " ,
202
- stringify!( #slug) ,
203
- "\" does not match the crate it is in"
204
- ) ) ;
205
- }
206
- pos += 1 ;
207
- }
208
- } else {
209
- // Crate does not start with "rustc_"
210
- }
211
- } ;
182
+ struct Mismatch {
183
+ slug_name : String ,
184
+ crate_name : String ,
185
+ slug_prefix : String ,
186
+ }
187
+
188
+ impl Mismatch {
189
+ /// Checks whether the slug starts with the crate name it's in.
190
+ fn check ( slug : & syn:: Path ) -> Option < Mismatch > {
191
+ // If this is missing we're probably in a test, so bail.
192
+ let crate_name = std:: env:: var ( "CARGO_CRATE_NAME" ) . ok ( ) ?;
193
+
194
+ // If we're not in a "rustc_" crate, bail.
195
+ let Some ( ( "rustc" , slug_prefix) ) = crate_name. split_once ( "_" ) else { return None } ;
196
+
197
+ let slug_name = slug. segments . first ( ) ?. ident . to_string ( ) ;
198
+ if !slug_name. starts_with ( slug_prefix) {
199
+ Some ( Mismatch { slug_name, slug_prefix : slug_prefix. to_string ( ) , crate_name } )
200
+ } else {
201
+ None
202
+ }
212
203
}
213
204
}
0 commit comments