@@ -5,6 +5,7 @@ mod cast_precision_loss;
55mod cast_ptr_alignment;
66mod cast_ref_to_mut;
77mod cast_sign_loss;
8+ mod char_lit_as_u8;
89mod fn_to_numeric_cast;
910mod fn_to_numeric_cast_with_truncation;
1011mod unnecessary_cast;
@@ -13,19 +14,16 @@ mod utils;
1314use std:: borrow:: Cow ;
1415
1516use if_chain:: if_chain;
16- use rustc_ast:: LitKind ;
1717use rustc_errors:: Applicability ;
1818use rustc_hir:: { Expr , ExprKind , Mutability , TyKind } ;
1919use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
2020use rustc_middle:: lint:: in_external_macro;
21- use rustc_middle:: ty:: { self , TypeAndMut , UintTy } ;
21+ use rustc_middle:: ty:: { self , TypeAndMut } ;
2222use rustc_semver:: RustcVersion ;
2323use rustc_session:: { declare_lint_pass, declare_tool_lint, impl_lint_pass} ;
2424
2525use crate :: utils:: sugg:: Sugg ;
26- use crate :: utils:: {
27- is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint_and_sugg, span_lint_and_then,
28- } ;
26+ use crate :: utils:: { is_hir_ty_cfg_dependant, meets_msrv, span_lint_and_sugg} ;
2927
3028declare_clippy_lint ! {
3129 /// **What it does:** Checks for casts from any numerical to a float type where
@@ -290,17 +288,45 @@ declare_clippy_lint! {
290288 "a cast of reference to a mutable pointer"
291289}
292290
291+ declare_clippy_lint ! {
292+ /// **What it does:** Checks for expressions where a character literal is cast
293+ /// to `u8` and suggests using a byte literal instead.
294+ ///
295+ /// **Why is this bad?** In general, casting values to smaller types is
296+ /// error-prone and should be avoided where possible. In the particular case of
297+ /// converting a character literal to u8, it is easy to avoid by just using a
298+ /// byte literal instead. As an added bonus, `b'a'` is even slightly shorter
299+ /// than `'a' as u8`.
300+ ///
301+ /// **Known problems:** None.
302+ ///
303+ /// **Example:**
304+ /// ```rust,ignore
305+ /// 'x' as u8
306+ /// ```
307+ ///
308+ /// A better version, using the byte literal:
309+ ///
310+ /// ```rust,ignore
311+ /// b'x'
312+ /// ```
313+ pub CHAR_LIT_AS_U8 ,
314+ complexity,
315+ "casting a character literal to `u8` truncates"
316+ }
317+
293318declare_lint_pass ! ( Casts => [
294319 CAST_PRECISION_LOSS ,
295320 CAST_SIGN_LOSS ,
296321 CAST_POSSIBLE_TRUNCATION ,
297322 CAST_POSSIBLE_WRAP ,
298323 CAST_LOSSLESS ,
299324 CAST_REF_TO_MUT ,
300- UNNECESSARY_CAST ,
301325 CAST_PTR_ALIGNMENT ,
326+ UNNECESSARY_CAST ,
302327 FN_TO_NUMERIC_CAST ,
303328 FN_TO_NUMERIC_CAST_WITH_TRUNCATION ,
329+ CHAR_LIT_AS_U8 ,
304330] ) ;
305331
306332impl < ' tcx > LateLintPass < ' tcx > for Casts {
@@ -335,74 +361,12 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
335361 }
336362
337363 cast_ptr_alignment:: check ( cx, expr) ;
364+ char_lit_as_u8:: check ( cx, expr) ;
338365 }
339366}
340367
341368const PTR_AS_PTR_MSRV : RustcVersion = RustcVersion :: new ( 1 , 38 , 0 ) ;
342369
343- declare_clippy_lint ! {
344- /// **What it does:** Checks for expressions where a character literal is cast
345- /// to `u8` and suggests using a byte literal instead.
346- ///
347- /// **Why is this bad?** In general, casting values to smaller types is
348- /// error-prone and should be avoided where possible. In the particular case of
349- /// converting a character literal to u8, it is easy to avoid by just using a
350- /// byte literal instead. As an added bonus, `b'a'` is even slightly shorter
351- /// than `'a' as u8`.
352- ///
353- /// **Known problems:** None.
354- ///
355- /// **Example:**
356- /// ```rust,ignore
357- /// 'x' as u8
358- /// ```
359- ///
360- /// A better version, using the byte literal:
361- ///
362- /// ```rust,ignore
363- /// b'x'
364- /// ```
365- pub CHAR_LIT_AS_U8 ,
366- complexity,
367- "casting a character literal to `u8` truncates"
368- }
369-
370- declare_lint_pass ! ( CharLitAsU8 => [ CHAR_LIT_AS_U8 ] ) ;
371-
372- impl < ' tcx > LateLintPass < ' tcx > for CharLitAsU8 {
373- fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
374- if_chain ! {
375- if !expr. span. from_expansion( ) ;
376- if let ExprKind :: Cast ( e, _) = & expr. kind;
377- if let ExprKind :: Lit ( l) = & e. kind;
378- if let LitKind :: Char ( c) = l. node;
379- if ty:: Uint ( UintTy :: U8 ) == * cx. typeck_results( ) . expr_ty( expr) . kind( ) ;
380- then {
381- let mut applicability = Applicability :: MachineApplicable ;
382- let snippet = snippet_with_applicability( cx, e. span, "'x'" , & mut applicability) ;
383-
384- span_lint_and_then(
385- cx,
386- CHAR_LIT_AS_U8 ,
387- expr. span,
388- "casting a character literal to `u8` truncates" ,
389- |diag| {
390- diag. note( "`char` is four bytes wide, but `u8` is a single byte" ) ;
391-
392- if c. is_ascii( ) {
393- diag. span_suggestion(
394- expr. span,
395- "use a byte literal instead" ,
396- format!( "b{}" , snippet) ,
397- applicability,
398- ) ;
399- }
400- } ) ;
401- }
402- }
403- }
404- }
405-
406370declare_clippy_lint ! {
407371 /// **What it does:**
408372 /// Checks for `as` casts between raw pointers without changing its mutability,
0 commit comments