|
1 | 1 | use rustc_middle::mir::visit::Visitor; |
2 | 2 | use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind}; |
3 | | -use rustc_middle::ty::{Ty, TyCtxt, UintTy}; |
| 3 | +use rustc_middle::ty::{TyCtxt, UintTy}; |
4 | 4 | use rustc_session::lint::builtin::REDUNDANT_TRANSMUTATION; |
5 | 5 | use rustc_span::source_map::Spanned; |
6 | 6 | use rustc_span::{Span, sym}; |
7 | 7 | use rustc_type_ir::TyKind::*; |
8 | 8 |
|
9 | | -use crate::errors; |
| 9 | +use crate::errors::RedundantTransmute as Error; |
10 | 10 |
|
11 | 11 | /// Check for transmutes that overlap with stdlib methods. |
12 | 12 | /// For example, transmuting `[u8; 4]` to `u32`. |
@@ -36,64 +36,48 @@ impl<'a, 'tcx> RedundantTransmutesChecker<'a, 'tcx> { |
36 | 36 | function: &Operand<'tcx>, |
37 | 37 | arg: String, |
38 | 38 | span: Span, |
39 | | - ) -> Option<errors::RedundantTransmute> { |
| 39 | + ) -> Option<Error> { |
40 | 40 | let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder(); |
41 | 41 | let [input] = fn_sig.inputs() else { return None }; |
42 | 42 |
|
43 | | - // Checks if `x` is `[u8; _]` |
44 | | - let is_u8s = |x: Ty<'tcx>| matches!(x.kind(), Array(t, _) if *t.kind() == Uint(UintTy::U8)); |
45 | | - // dont check the length; transmute does that for us. |
46 | | - if is_u8s(*input) && matches!(fn_sig.output().kind(), Uint(..) | Float(_) | Int(_)) { |
47 | | - // FIXME: get the whole expression out? |
48 | | - return Some(errors::RedundantTransmute { |
| 43 | + let err = |sugg| Error { span, sugg, help: None }; |
| 44 | + |
| 45 | + Some(match (input.kind(), fn_sig.output().kind()) { |
| 46 | + // dont check the length; transmute does that for us. |
| 47 | + (Array(t, _), Uint(_) | Float(_) | Int(_)) if *t.kind() == Uint(UintTy::U8) => Error { |
49 | 48 | sugg: format!("{}::from_ne_bytes({arg})", fn_sig.output()), |
50 | 49 | help: Some( |
51 | 50 | "there's also `from_le_bytes` and `from_ne_bytes` if you expect a particular byte order", |
52 | 51 | ), |
53 | 52 | span, |
54 | | - }); |
55 | | - } |
56 | | - if is_u8s(fn_sig.output()) && matches!(input.kind(), Uint(..) | Float(_) | Int(_)) { |
57 | | - return Some(errors::RedundantTransmute { |
| 53 | + }, |
| 54 | + (Uint(_) | Float(_) | Int(_), Array(t, _)) if *t.kind() == Uint(UintTy::U8) => Error { |
58 | 55 | sugg: format!("{input}::to_ne_bytes({arg})"), |
59 | 56 | help: Some( |
60 | 57 | "there's also `to_le_bytes` and `to_ne_bytes` if you expect a particular byte order", |
61 | 58 | ), |
62 | 59 | span, |
63 | | - }); |
64 | | - } |
65 | | - match input.kind() { |
| 60 | + }, |
66 | 61 | // char → u32 |
67 | | - Char => matches!(fn_sig.output().kind(), Uint(UintTy::U32)) |
68 | | - .then(|| errors::RedundantTransmute::new(format!("({arg}) as u32"), span)), |
| 62 | + (Char, Uint(UintTy::U32)) => err(format!("({arg}) as u32")), |
69 | 63 | // u32 → char |
70 | | - Uint(UintTy::U32) if *fn_sig.output().kind() == Char => { |
71 | | - Some(errors::RedundantTransmute { |
72 | | - sugg: format!("char::from_u32_unchecked({arg})"), |
73 | | - help: Some("consider `char::from_u32(…).unwrap()`"), |
74 | | - span, |
75 | | - }) |
76 | | - } |
| 64 | + (Uint(UintTy::U32), Char) => Error { |
| 65 | + sugg: format!("char::from_u32_unchecked({arg})"), |
| 66 | + help: Some("consider `char::from_u32(…).unwrap()`"), |
| 67 | + span, |
| 68 | + }, |
77 | 69 | // uNN → iNN |
78 | | - Uint(ty) if matches!(fn_sig.output().kind(), Int(..)) => { |
79 | | - Some(errors::RedundantTransmute::new( |
80 | | - format!("{}::cast_signed({arg})", ty.name_str()), |
81 | | - span, |
82 | | - )) |
83 | | - } |
| 70 | + (Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())), |
84 | 71 | // iNN → uNN |
85 | | - Int(ty) if matches!(fn_sig.output().kind(), Uint(..)) => { |
86 | | - Some(errors::RedundantTransmute::new( |
87 | | - format!("{}::cast_unsigned({arg})", ty.name_str()), |
88 | | - span, |
89 | | - )) |
90 | | - } |
| 72 | + (Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())), |
| 73 | + // fNN → uNN |
| 74 | + (Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())), |
| 75 | + // uNN → fNN |
| 76 | + (Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())), |
91 | 77 | // bool → { uNN, iNN } |
92 | | - Bool if matches!(fn_sig.output().kind(), Int(..) | Uint(..)) => Some( |
93 | | - errors::RedundantTransmute::new(format!("({arg}) as {}", fn_sig.output()), span), |
94 | | - ), |
95 | | - _ => None, |
96 | | - } |
| 78 | + (Bool, Int(..) | Uint(..)) => err(format!("({arg}) as {}", fn_sig.output())), |
| 79 | + _ => return None, |
| 80 | + }) |
97 | 81 | } |
98 | 82 | } |
99 | 83 |
|
|
0 commit comments