]>
Commit | Line | Data |
---|---|---|
1 | mod cast_abs_to_unsigned; | |
2 | mod cast_enum_constructor; | |
3 | mod cast_lossless; | |
4 | mod cast_possible_truncation; | |
5 | mod cast_possible_wrap; | |
6 | mod cast_precision_loss; | |
7 | mod cast_ptr_alignment; | |
8 | mod cast_ref_to_mut; | |
9 | mod cast_sign_loss; | |
10 | mod cast_slice_different_sizes; | |
11 | mod char_lit_as_u8; | |
12 | mod fn_to_numeric_cast; | |
13 | mod fn_to_numeric_cast_any; | |
14 | mod fn_to_numeric_cast_with_truncation; | |
15 | mod ptr_as_ptr; | |
16 | mod unnecessary_cast; | |
17 | mod utils; | |
18 | ||
19 | use clippy_utils::is_hir_ty_cfg_dependant; | |
20 | use rustc_hir::{Expr, ExprKind}; | |
21 | use rustc_lint::{LateContext, LateLintPass, LintContext}; | |
22 | use rustc_middle::lint::in_external_macro; | |
23 | use rustc_semver::RustcVersion; | |
24 | use rustc_session::{declare_tool_lint, impl_lint_pass}; | |
25 | ||
26 | declare_clippy_lint! { | |
27 | /// ### What it does | |
28 | /// Checks for casts from any numerical to a float type where | |
29 | /// the receiving type cannot store all values from the original type without | |
30 | /// rounding errors. This possible rounding is to be expected, so this lint is | |
31 | /// `Allow` by default. | |
32 | /// | |
33 | /// Basically, this warns on casting any integer with 32 or more bits to `f32` | |
34 | /// or any 64-bit integer to `f64`. | |
35 | /// | |
36 | /// ### Why is this bad? | |
37 | /// It's not bad at all. But in some applications it can be | |
38 | /// helpful to know where precision loss can take place. This lint can help find | |
39 | /// those places in the code. | |
40 | /// | |
41 | /// ### Example | |
42 | /// ```rust | |
43 | /// let x = u64::MAX; | |
44 | /// x as f64; | |
45 | /// ``` | |
46 | #[clippy::version = "pre 1.29.0"] | |
47 | pub CAST_PRECISION_LOSS, | |
48 | pedantic, | |
49 | "casts that cause loss of precision, e.g., `x as f32` where `x: u64`" | |
50 | } | |
51 | ||
52 | declare_clippy_lint! { | |
53 | /// ### What it does | |
54 | /// Checks for casts from a signed to an unsigned numerical | |
55 | /// type. In this case, negative values wrap around to large positive values, | |
56 | /// which can be quite surprising in practice. However, as the cast works as | |
57 | /// defined, this lint is `Allow` by default. | |
58 | /// | |
59 | /// ### Why is this bad? | |
60 | /// Possibly surprising results. You can activate this lint | |
61 | /// as a one-time check to see where numerical wrapping can arise. | |
62 | /// | |
63 | /// ### Example | |
64 | /// ```rust | |
65 | /// let y: i8 = -1; | |
66 | /// y as u128; // will return 18446744073709551615 | |
67 | /// ``` | |
68 | #[clippy::version = "pre 1.29.0"] | |
69 | pub CAST_SIGN_LOSS, | |
70 | pedantic, | |
71 | "casts from signed types to unsigned types, e.g., `x as u32` where `x: i32`" | |
72 | } | |
73 | ||
74 | declare_clippy_lint! { | |
75 | /// ### What it does | |
76 | /// Checks for casts between numerical types that may | |
77 | /// truncate large values. This is expected behavior, so the cast is `Allow` by | |
78 | /// default. | |
79 | /// | |
80 | /// ### Why is this bad? | |
81 | /// In some problem domains, it is good practice to avoid | |
82 | /// truncation. This lint can be activated to help assess where additional | |
83 | /// checks could be beneficial. | |
84 | /// | |
85 | /// ### Example | |
86 | /// ```rust | |
87 | /// fn as_u8(x: u64) -> u8 { | |
88 | /// x as u8 | |
89 | /// } | |
90 | /// ``` | |
91 | #[clippy::version = "pre 1.29.0"] | |
92 | pub CAST_POSSIBLE_TRUNCATION, | |
93 | pedantic, | |
94 | "casts that may cause truncation of the value, e.g., `x as u8` where `x: u32`, or `x as i32` where `x: f32`" | |
95 | } | |
96 | ||
97 | declare_clippy_lint! { | |
98 | /// ### What it does | |
99 | /// Checks for casts from an unsigned type to a signed type of | |
100 | /// the same size. Performing such a cast is a 'no-op' for the compiler, | |
101 | /// i.e., nothing is changed at the bit level, and the binary representation of | |
102 | /// the value is reinterpreted. This can cause wrapping if the value is too big | |
103 | /// for the target signed type. However, the cast works as defined, so this lint | |
104 | /// is `Allow` by default. | |
105 | /// | |
106 | /// ### Why is this bad? | |
107 | /// While such a cast is not bad in itself, the results can | |
108 | /// be surprising when this is not the intended behavior, as demonstrated by the | |
109 | /// example below. | |
110 | /// | |
111 | /// ### Example | |
112 | /// ```rust | |
113 | /// u32::MAX as i32; // will yield a value of `-1` | |
114 | /// ``` | |
115 | #[clippy::version = "pre 1.29.0"] | |
116 | pub CAST_POSSIBLE_WRAP, | |
117 | pedantic, | |
118 | "casts that may cause wrapping around the value, e.g., `x as i32` where `x: u32` and `x > i32::MAX`" | |
119 | } | |
120 | ||
121 | declare_clippy_lint! { | |
122 | /// ### What it does | |
123 | /// Checks for casts between numerical types that may | |
124 | /// be replaced by safe conversion functions. | |
125 | /// | |
126 | /// ### Why is this bad? | |
127 | /// Rust's `as` keyword will perform many kinds of | |
128 | /// conversions, including silently lossy conversions. Conversion functions such | |
129 | /// as `i32::from` will only perform lossless conversions. Using the conversion | |
130 | /// functions prevents conversions from turning into silent lossy conversions if | |
131 | /// the types of the input expressions ever change, and make it easier for | |
132 | /// people reading the code to know that the conversion is lossless. | |
133 | /// | |
134 | /// ### Example | |
135 | /// ```rust | |
136 | /// fn as_u64(x: u8) -> u64 { | |
137 | /// x as u64 | |
138 | /// } | |
139 | /// ``` | |
140 | /// | |
141 | /// Using `::from` would look like this: | |
142 | /// | |
143 | /// ```rust | |
144 | /// fn as_u64(x: u8) -> u64 { | |
145 | /// u64::from(x) | |
146 | /// } | |
147 | /// ``` | |
148 | #[clippy::version = "pre 1.29.0"] | |
149 | pub CAST_LOSSLESS, | |
150 | pedantic, | |
151 | "casts using `as` that are known to be lossless, e.g., `x as u64` where `x: u8`" | |
152 | } | |
153 | ||
154 | declare_clippy_lint! { | |
155 | /// ### What it does | |
156 | /// Checks for casts to the same type, casts of int literals to integer types | |
157 | /// and casts of float literals to float types. | |
158 | /// | |
159 | /// ### Why is this bad? | |
160 | /// It's just unnecessary. | |
161 | /// | |
162 | /// ### Example | |
163 | /// ```rust | |
164 | /// let _ = 2i32 as i32; | |
165 | /// let _ = 0.5 as f32; | |
166 | /// ``` | |
167 | /// | |
168 | /// Better: | |
169 | /// | |
170 | /// ```rust | |
171 | /// let _ = 2_i32; | |
172 | /// let _ = 0.5_f32; | |
173 | /// ``` | |
174 | #[clippy::version = "pre 1.29.0"] | |
175 | pub UNNECESSARY_CAST, | |
176 | complexity, | |
177 | "cast to the same type, e.g., `x as i32` where `x: i32`" | |
178 | } | |
179 | ||
180 | declare_clippy_lint! { | |
181 | /// ### What it does | |
182 | /// Checks for casts, using `as` or `pointer::cast`, | |
183 | /// from a less-strictly-aligned pointer to a more-strictly-aligned pointer | |
184 | /// | |
185 | /// ### Why is this bad? | |
186 | /// Dereferencing the resulting pointer may be undefined | |
187 | /// behavior. | |
188 | /// | |
189 | /// ### Known problems | |
190 | /// Using `std::ptr::read_unaligned` and `std::ptr::write_unaligned` or similar | |
191 | /// on the resulting pointer is fine. Is over-zealous: Casts with manual alignment checks or casts like | |
192 | /// u64-> u8 -> u16 can be fine. Miri is able to do a more in-depth analysis. | |
193 | /// | |
194 | /// ### Example | |
195 | /// ```rust | |
196 | /// let _ = (&1u8 as *const u8) as *const u16; | |
197 | /// let _ = (&mut 1u8 as *mut u8) as *mut u16; | |
198 | /// | |
199 | /// (&1u8 as *const u8).cast::<u16>(); | |
200 | /// (&mut 1u8 as *mut u8).cast::<u16>(); | |
201 | /// ``` | |
202 | #[clippy::version = "pre 1.29.0"] | |
203 | pub CAST_PTR_ALIGNMENT, | |
204 | pedantic, | |
205 | "cast from a pointer to a more-strictly-aligned pointer" | |
206 | } | |
207 | ||
208 | declare_clippy_lint! { | |
209 | /// ### What it does | |
210 | /// Checks for casts of function pointers to something other than usize | |
211 | /// | |
212 | /// ### Why is this bad? | |
213 | /// Casting a function pointer to anything other than usize/isize is not portable across | |
214 | /// architectures, because you end up losing bits if the target type is too small or end up with a | |
215 | /// bunch of extra bits that waste space and add more instructions to the final binary than | |
216 | /// strictly necessary for the problem | |
217 | /// | |
218 | /// Casting to isize also doesn't make sense since there are no signed addresses. | |
219 | /// | |
220 | /// ### Example | |
221 | /// ```rust | |
222 | /// fn fun() -> i32 { 1 } | |
223 | /// let _ = fun as i64; | |
224 | /// ``` | |
225 | /// | |
226 | /// Use instead: | |
227 | /// ```rust | |
228 | /// # fn fun() -> i32 { 1 } | |
229 | /// let _ = fun as usize; | |
230 | /// ``` | |
231 | #[clippy::version = "pre 1.29.0"] | |
232 | pub FN_TO_NUMERIC_CAST, | |
233 | style, | |
234 | "casting a function pointer to a numeric type other than usize" | |
235 | } | |
236 | ||
237 | declare_clippy_lint! { | |
238 | /// ### What it does | |
239 | /// Checks for casts of a function pointer to a numeric type not wide enough to | |
240 | /// store address. | |
241 | /// | |
242 | /// ### Why is this bad? | |
243 | /// Such a cast discards some bits of the function's address. If this is intended, it would be more | |
244 | /// clearly expressed by casting to usize first, then casting the usize to the intended type (with | |
245 | /// a comment) to perform the truncation. | |
246 | /// | |
247 | /// ### Example | |
248 | /// ```rust | |
249 | /// fn fn1() -> i16 { | |
250 | /// 1 | |
251 | /// }; | |
252 | /// let _ = fn1 as i32; | |
253 | /// ``` | |
254 | /// | |
255 | /// Use instead: | |
256 | /// ```rust | |
257 | /// // Cast to usize first, then comment with the reason for the truncation | |
258 | /// fn fn1() -> i16 { | |
259 | /// 1 | |
260 | /// }; | |
261 | /// let fn_ptr = fn1 as usize; | |
262 | /// let fn_ptr_truncated = fn_ptr as i32; | |
263 | /// ``` | |
264 | #[clippy::version = "pre 1.29.0"] | |
265 | pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION, | |
266 | style, | |
267 | "casting a function pointer to a numeric type not wide enough to store the address" | |
268 | } | |
269 | ||
270 | declare_clippy_lint! { | |
271 | /// ### What it does | |
272 | /// Checks for casts of a function pointer to any integer type. | |
273 | /// | |
274 | /// ### Why is this bad? | |
275 | /// Casting a function pointer to an integer can have surprising results and can occur | |
276 | /// accidentally if parentheses are omitted from a function call. If you aren't doing anything | |
277 | /// low-level with function pointers then you can opt-out of casting functions to integers in | |
278 | /// order to avoid mistakes. Alternatively, you can use this lint to audit all uses of function | |
279 | /// pointer casts in your code. | |
280 | /// | |
281 | /// ### Example | |
282 | /// ```rust | |
283 | /// // fn1 is cast as `usize` | |
284 | /// fn fn1() -> u16 { | |
285 | /// 1 | |
286 | /// }; | |
287 | /// let _ = fn1 as usize; | |
288 | /// ``` | |
289 | /// | |
290 | /// Use instead: | |
291 | /// ```rust | |
292 | /// // maybe you intended to call the function? | |
293 | /// fn fn2() -> u16 { | |
294 | /// 1 | |
295 | /// }; | |
296 | /// let _ = fn2() as usize; | |
297 | /// | |
298 | /// // or | |
299 | /// | |
300 | /// // maybe you intended to cast it to a function type? | |
301 | /// fn fn3() -> u16 { | |
302 | /// 1 | |
303 | /// } | |
304 | /// let _ = fn3 as fn() -> u16; | |
305 | /// ``` | |
306 | #[clippy::version = "1.58.0"] | |
307 | pub FN_TO_NUMERIC_CAST_ANY, | |
308 | restriction, | |
309 | "casting a function pointer to any integer type" | |
310 | } | |
311 | ||
312 | declare_clippy_lint! { | |
313 | /// ### What it does | |
314 | /// Checks for casts of `&T` to `&mut T` anywhere in the code. | |
315 | /// | |
316 | /// ### Why is this bad? | |
317 | /// It’s basically guaranteed to be undefined behavior. | |
318 | /// `UnsafeCell` is the only way to obtain aliasable data that is considered | |
319 | /// mutable. | |
320 | /// | |
321 | /// ### Example | |
322 | /// ```rust,ignore | |
323 | /// fn x(r: &i32) { | |
324 | /// unsafe { | |
325 | /// *(r as *const _ as *mut _) += 1; | |
326 | /// } | |
327 | /// } | |
328 | /// ``` | |
329 | /// | |
330 | /// Instead consider using interior mutability types. | |
331 | /// | |
332 | /// ```rust | |
333 | /// use std::cell::UnsafeCell; | |
334 | /// | |
335 | /// fn x(r: &UnsafeCell<i32>) { | |
336 | /// unsafe { | |
337 | /// *r.get() += 1; | |
338 | /// } | |
339 | /// } | |
340 | /// ``` | |
341 | #[clippy::version = "1.33.0"] | |
342 | pub CAST_REF_TO_MUT, | |
343 | correctness, | |
344 | "a cast of reference to a mutable pointer" | |
345 | } | |
346 | ||
347 | declare_clippy_lint! { | |
348 | /// ### What it does | |
349 | /// Checks for expressions where a character literal is cast | |
350 | /// to `u8` and suggests using a byte literal instead. | |
351 | /// | |
352 | /// ### Why is this bad? | |
353 | /// In general, casting values to smaller types is | |
354 | /// error-prone and should be avoided where possible. In the particular case of | |
355 | /// converting a character literal to u8, it is easy to avoid by just using a | |
356 | /// byte literal instead. As an added bonus, `b'a'` is even slightly shorter | |
357 | /// than `'a' as u8`. | |
358 | /// | |
359 | /// ### Example | |
360 | /// ```rust,ignore | |
361 | /// 'x' as u8 | |
362 | /// ``` | |
363 | /// | |
364 | /// A better version, using the byte literal: | |
365 | /// | |
366 | /// ```rust,ignore | |
367 | /// b'x' | |
368 | /// ``` | |
369 | #[clippy::version = "pre 1.29.0"] | |
370 | pub CHAR_LIT_AS_U8, | |
371 | complexity, | |
372 | "casting a character literal to `u8` truncates" | |
373 | } | |
374 | ||
375 | declare_clippy_lint! { | |
376 | /// ### What it does | |
377 | /// Checks for `as` casts between raw pointers without changing its mutability, | |
378 | /// namely `*const T` to `*const U` and `*mut T` to `*mut U`. | |
379 | /// | |
380 | /// ### Why is this bad? | |
381 | /// Though `as` casts between raw pointers is not terrible, `pointer::cast` is safer because | |
382 | /// it cannot accidentally change the pointer's mutability nor cast the pointer to other types like `usize`. | |
383 | /// | |
384 | /// ### Example | |
385 | /// ```rust | |
386 | /// let ptr: *const u32 = &42_u32; | |
387 | /// let mut_ptr: *mut u32 = &mut 42_u32; | |
388 | /// let _ = ptr as *const i32; | |
389 | /// let _ = mut_ptr as *mut i32; | |
390 | /// ``` | |
391 | /// Use instead: | |
392 | /// ```rust | |
393 | /// let ptr: *const u32 = &42_u32; | |
394 | /// let mut_ptr: *mut u32 = &mut 42_u32; | |
395 | /// let _ = ptr.cast::<i32>(); | |
396 | /// let _ = mut_ptr.cast::<i32>(); | |
397 | /// ``` | |
398 | #[clippy::version = "1.51.0"] | |
399 | pub PTR_AS_PTR, | |
400 | pedantic, | |
401 | "casting using `as` from and to raw pointers that doesn't change its mutability, where `pointer::cast` could take the place of `as`" | |
402 | } | |
403 | ||
404 | declare_clippy_lint! { | |
405 | /// ### What it does | |
406 | /// Checks for casts from an enum type to an integral type which will definitely truncate the | |
407 | /// value. | |
408 | /// | |
409 | /// ### Why is this bad? | |
410 | /// The resulting integral value will not match the value of the variant it came from. | |
411 | /// | |
412 | /// ### Example | |
413 | /// ```rust | |
414 | /// enum E { X = 256 }; | |
415 | /// let _ = E::X as u8; | |
416 | /// ``` | |
417 | #[clippy::version = "1.61.0"] | |
418 | pub CAST_ENUM_TRUNCATION, | |
419 | suspicious, | |
420 | "casts from an enum type to an integral type which will truncate the value" | |
421 | } | |
422 | ||
423 | declare_clippy_lint! { | |
424 | /// ### What it does | |
425 | /// Checks for `as` casts between raw pointers to slices with differently sized elements. | |
426 | /// | |
427 | /// ### Why is this bad? | |
428 | /// The produced raw pointer to a slice does not update its length metadata. The produced | |
429 | /// pointer will point to a different number of bytes than the original pointer because the | |
430 | /// length metadata of a raw slice pointer is in elements rather than bytes. | |
431 | /// Producing a slice reference from the raw pointer will either create a slice with | |
432 | /// less data (which can be surprising) or create a slice with more data and cause Undefined Behavior. | |
433 | /// | |
434 | /// ### Example | |
435 | /// // Missing data | |
436 | /// ```rust | |
437 | /// let a = [1_i32, 2, 3, 4]; | |
438 | /// let p = &a as *const [i32] as *const [u8]; | |
439 | /// unsafe { | |
440 | /// println!("{:?}", &*p); | |
441 | /// } | |
442 | /// ``` | |
443 | /// // Undefined Behavior (note: also potential alignment issues) | |
444 | /// ```rust | |
445 | /// let a = [1_u8, 2, 3, 4]; | |
446 | /// let p = &a as *const [u8] as *const [u32]; | |
447 | /// unsafe { | |
448 | /// println!("{:?}", &*p); | |
449 | /// } | |
450 | /// ``` | |
451 | /// Instead use `ptr::slice_from_raw_parts` to construct a slice from a data pointer and the correct length | |
452 | /// ```rust | |
453 | /// let a = [1_i32, 2, 3, 4]; | |
454 | /// let old_ptr = &a as *const [i32]; | |
455 | /// // The data pointer is cast to a pointer to the target `u8` not `[u8]` | |
456 | /// // The length comes from the known length of 4 i32s times the 4 bytes per i32 | |
457 | /// let new_ptr = core::ptr::slice_from_raw_parts(old_ptr as *const u8, 16); | |
458 | /// unsafe { | |
459 | /// println!("{:?}", &*new_ptr); | |
460 | /// } | |
461 | /// ``` | |
462 | #[clippy::version = "1.61.0"] | |
463 | pub CAST_SLICE_DIFFERENT_SIZES, | |
464 | correctness, | |
465 | "casting using `as` between raw pointers to slices of types with different sizes" | |
466 | } | |
467 | ||
468 | declare_clippy_lint! { | |
469 | /// ### What it does | |
470 | /// Checks for casts from an enum tuple constructor to an integer. | |
471 | /// | |
472 | /// ### Why is this bad? | |
473 | /// The cast is easily confused with casting a c-like enum value to an integer. | |
474 | /// | |
475 | /// ### Example | |
476 | /// ```rust | |
477 | /// enum E { X(i32) }; | |
478 | /// let _ = E::X as usize; | |
479 | /// ``` | |
480 | #[clippy::version = "1.61.0"] | |
481 | pub CAST_ENUM_CONSTRUCTOR, | |
482 | suspicious, | |
483 | "casts from an enum tuple constructor to an integer" | |
484 | } | |
485 | ||
486 | declare_clippy_lint! { | |
487 | /// ### What it does | |
488 | /// Checks for uses of the `abs()` method that cast the result to unsigned. | |
489 | /// | |
490 | /// ### Why is this bad? | |
491 | /// The `unsigned_abs()` method avoids panic when called on the MIN value. | |
492 | /// | |
493 | /// ### Example | |
494 | /// ```rust | |
495 | /// let x: i32 = -42; | |
496 | /// let y: u32 = x.abs() as u32; | |
497 | /// ``` | |
498 | /// Use instead: | |
499 | /// ```rust | |
500 | /// let x: i32 = -42; | |
501 | /// let y: u32 = x.unsigned_abs(); | |
502 | /// ``` | |
503 | #[clippy::version = "1.61.0"] | |
504 | pub CAST_ABS_TO_UNSIGNED, | |
505 | suspicious, | |
506 | "casting the result of `abs()` to an unsigned integer can panic" | |
507 | } | |
508 | ||
509 | pub struct Casts { | |
510 | msrv: Option<RustcVersion>, | |
511 | } | |
512 | ||
513 | impl Casts { | |
514 | #[must_use] | |
515 | pub fn new(msrv: Option<RustcVersion>) -> Self { | |
516 | Self { msrv } | |
517 | } | |
518 | } | |
519 | ||
520 | impl_lint_pass!(Casts => [ | |
521 | CAST_PRECISION_LOSS, | |
522 | CAST_SIGN_LOSS, | |
523 | CAST_POSSIBLE_TRUNCATION, | |
524 | CAST_POSSIBLE_WRAP, | |
525 | CAST_LOSSLESS, | |
526 | CAST_REF_TO_MUT, | |
527 | CAST_PTR_ALIGNMENT, | |
528 | CAST_SLICE_DIFFERENT_SIZES, | |
529 | UNNECESSARY_CAST, | |
530 | FN_TO_NUMERIC_CAST_ANY, | |
531 | FN_TO_NUMERIC_CAST, | |
532 | FN_TO_NUMERIC_CAST_WITH_TRUNCATION, | |
533 | CHAR_LIT_AS_U8, | |
534 | PTR_AS_PTR, | |
535 | CAST_ENUM_TRUNCATION, | |
536 | CAST_ENUM_CONSTRUCTOR, | |
537 | CAST_ABS_TO_UNSIGNED | |
538 | ]); | |
539 | ||
540 | impl<'tcx> LateLintPass<'tcx> for Casts { | |
541 | fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { | |
542 | if !in_external_macro(cx.sess(), expr.span) { | |
543 | ptr_as_ptr::check(cx, expr, self.msrv); | |
544 | } | |
545 | ||
546 | if expr.span.from_expansion() { | |
547 | return; | |
548 | } | |
549 | ||
550 | if let ExprKind::Cast(cast_expr, cast_to) = expr.kind { | |
551 | if is_hir_ty_cfg_dependant(cx, cast_to) { | |
552 | return; | |
553 | } | |
554 | let (cast_from, cast_to) = ( | |
555 | cx.typeck_results().expr_ty(cast_expr), | |
556 | cx.typeck_results().expr_ty(expr), | |
557 | ); | |
558 | ||
559 | if unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) { | |
560 | return; | |
561 | } | |
562 | ||
563 | fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to); | |
564 | fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to); | |
565 | fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to); | |
566 | ||
567 | if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) { | |
568 | cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to); | |
569 | if cast_from.is_numeric() { | |
570 | cast_possible_wrap::check(cx, expr, cast_from, cast_to); | |
571 | cast_precision_loss::check(cx, expr, cast_from, cast_to); | |
572 | cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to); | |
573 | cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv); | |
574 | } | |
575 | cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv); | |
576 | cast_enum_constructor::check(cx, expr, cast_expr, cast_from); | |
577 | } | |
578 | } | |
579 | ||
580 | cast_ref_to_mut::check(cx, expr); | |
581 | cast_ptr_alignment::check(cx, expr); | |
582 | char_lit_as_u8::check(cx, expr); | |
583 | ptr_as_ptr::check(cx, expr, self.msrv); | |
584 | cast_slice_different_sizes::check(cx, expr, self.msrv); | |
585 | } | |
586 | ||
587 | extract_msrv_attr!(LateContext); | |
588 | } |