@@ -26,6 +26,24 @@ declare_clippy_lint! {
26
26
"long integer literal without underscores"
27
27
}
28
28
29
+ /// **What it does:** Warns for mistyped suffix in literals
30
+ ///
31
+ /// **Why is this bad?** This is most probably a typo
32
+ ///
33
+ /// **Known problems:** Recommends unsigned suffix even if it's a negative number. Should only
34
+ /// recommend the signed suffix on those cases.
35
+ ///
36
+ /// **Example:**
37
+ ///
38
+ /// ```rust
39
+ /// 2_32
40
+ /// ```
41
+ declare_clippy_lint ! {
42
+ pub MISTYPED_LITERAL_SUFFIXES ,
43
+ correctness,
44
+ "mistyped literal suffix"
45
+ }
46
+
29
47
/// **What it does:** Warns if an integral or floating-point constant is
30
48
/// grouped inconsistently with underscores.
31
49
///
@@ -136,8 +154,11 @@ impl<'a> DigitInfo<'a> {
136
154
} ;
137
155
138
156
let mut last_d = '\0' ;
157
+ let len = sans_prefix. len ( ) ;
139
158
for ( d_idx, d) in sans_prefix. char_indices ( ) {
140
- if !float && ( d == 'i' || d == 'u' ) || float && ( d == 'f' || d == 'e' || d == 'E' ) {
159
+ if !float && ( d == 'i' || d == 'u' ) ||
160
+ float && ( d == 'f' || d == 'e' || d == 'E' ) ||
161
+ ( !float && d == '_' && ( d_idx == len -3 || d_idx == len - 2 ) ) {
141
162
let suffix_start = if last_d == '_' { d_idx - 1 } else { d_idx } ;
142
163
let ( digits, suffix) = sans_prefix. split_at ( suffix_start) ;
143
164
return Self {
@@ -211,11 +232,18 @@ impl<'a> DigitInfo<'a> {
211
232
if self . radix == Radix :: Hexadecimal && nb_digits_to_fill != 0 {
212
233
hint = format ! ( "{:0>4}{}" , & hint[ ..nb_digits_to_fill] , & hint[ nb_digits_to_fill..] ) ;
213
234
}
235
+ let suffix_hint = match self . suffix {
236
+ Some ( suffix) if suffix == "_32" || suffix == "_64" => {
237
+ format ! ( "_i{}` or `{}_u{}" , & suffix[ 1 ..] , hint, & suffix[ 1 ..] )
238
+ } ,
239
+ Some ( suffix) => suffix. to_string ( ) ,
240
+ None => String :: new ( )
241
+ } ;
214
242
format ! (
215
243
"{}{}{}" ,
216
244
self . prefix. unwrap_or( "" ) ,
217
245
hint,
218
- self . suffix . unwrap_or ( "" )
246
+ suffix_hint
219
247
)
220
248
}
221
249
}
@@ -226,11 +254,22 @@ enum WarningType {
226
254
InconsistentDigitGrouping ,
227
255
LargeDigitGroups ,
228
256
DecimalRepresentation ,
257
+ MistypedLiteralSuffix
229
258
}
230
259
231
260
impl WarningType {
232
261
crate fn display ( & self , grouping_hint : & str , cx : & EarlyContext < ' _ > , span : syntax_pos:: Span ) {
233
262
match self {
263
+ WarningType :: MistypedLiteralSuffix => {
264
+ span_lint_and_sugg (
265
+ cx,
266
+ MISTYPED_LITERAL_SUFFIXES ,
267
+ span,
268
+ "mistyped literal suffix" ,
269
+ "did you mean to write" ,
270
+ grouping_hint. to_string ( )
271
+ )
272
+ } ,
234
273
WarningType :: UnreadableLiteral => span_lint_and_sugg (
235
274
cx,
236
275
UNREADABLE_LITERAL ,
@@ -303,7 +342,7 @@ impl LiteralDigitGrouping {
303
342
if char :: to_digit( firstch, 10 ) . is_some( ) ;
304
343
then {
305
344
let digit_info = DigitInfo :: new( & src, false ) ;
306
- let _ = Self :: do_lint( digit_info. digits) . map_err( |warning_type| {
345
+ let _ = Self :: do_lint( digit_info. digits, digit_info . suffix ) . map_err( |warning_type| {
307
346
warning_type. display( & digit_info. grouping_hint( ) , cx, lit. span)
308
347
} ) ;
309
348
}
@@ -325,12 +364,12 @@ impl LiteralDigitGrouping {
325
364
326
365
// Lint integral and fractional parts separately, and then check consistency of digit
327
366
// groups if both pass.
328
- let _ = Self :: do_lint( parts[ 0 ] )
367
+ let _ = Self :: do_lint( parts[ 0 ] , None )
329
368
. map( |integral_group_size| {
330
369
if parts. len( ) > 1 {
331
370
// Lint the fractional part of literal just like integral part, but reversed.
332
371
let fractional_part = & parts[ 1 ] . chars( ) . rev( ) . collect:: <String >( ) ;
333
- let _ = Self :: do_lint( fractional_part)
372
+ let _ = Self :: do_lint( fractional_part, None )
334
373
. map( |fractional_group_size| {
335
374
let consistent = Self :: parts_consistent( integral_group_size,
336
375
fractional_group_size,
@@ -373,7 +412,12 @@ impl LiteralDigitGrouping {
373
412
374
413
/// Performs lint on `digits` (no decimal point) and returns the group
375
414
/// size on success or `WarningType` when emitting a warning.
376
- fn do_lint ( digits : & str ) -> Result < usize , WarningType > {
415
+ fn do_lint ( digits : & str , suffix : Option < & str > ) -> Result < usize , WarningType > {
416
+ if let Some ( suffix) = suffix {
417
+ if [ "_8" , "_32" , "_64" ] . contains ( & suffix) {
418
+ return Err ( WarningType :: MistypedLiteralSuffix ) ;
419
+ }
420
+ }
377
421
// Grab underscore indices with respect to the units digit.
378
422
let underscore_positions: Vec < usize > = digits
379
423
. chars ( )
0 commit comments