]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use rustc_ast::ast::{Expr, ExprKind}; |
2 | use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; | |
3 | use rustc_middle::lint::in_external_macro; | |
4 | use rustc_session::{declare_lint_pass, declare_tool_lint}; | |
5 | ||
6 | use crate::utils::span_lint_and_help; | |
7 | ||
8 | declare_clippy_lint! { | |
9 | /// **What it does:** Checks for usage of `as` conversions. | |
10 | /// | |
11 | /// Note that this lint is specialized in linting *every single* use of `as` | |
12 | /// regardless of whether good alternatives exist or not. | |
13 | /// If you want more precise lints for `as`, please consider using these separate lints: | |
14 | /// `unnecessary_cast`, `cast_lossless/possible_truncation/possible_wrap/precision_loss/sign_loss`, | |
15 | /// `fn_to_numeric_cast(_with_truncation)`, `char_lit_as_u8`, `ref_to_mut` and `ptr_as_ptr`. | |
16 | /// There is a good explanation the reason why this lint should work in this way and how it is useful | |
17 | /// [in this issue](https://github.com/rust-lang/rust-clippy/issues/5122). | |
18 | /// | |
19 | /// **Why is this bad?** `as` conversions will perform many kinds of | |
20 | /// conversions, including silently lossy conversions and dangerous coercions. | |
21 | /// There are cases when it makes sense to use `as`, so the lint is | |
22 | /// Allow by default. | |
23 | /// | |
24 | /// **Known problems:** None. | |
25 | /// | |
26 | /// **Example:** | |
27 | /// ```rust,ignore | |
28 | /// let a: u32; | |
29 | /// ... | |
30 | /// f(a as u16); | |
31 | /// ``` | |
32 | /// | |
33 | /// Usually better represents the semantics you expect: | |
34 | /// ```rust,ignore | |
35 | /// f(a.try_into()?); | |
36 | /// ``` | |
37 | /// or | |
38 | /// ```rust,ignore | |
39 | /// f(a.try_into().expect("Unexpected u16 overflow in f")); | |
40 | /// ``` | |
41 | /// | |
42 | pub AS_CONVERSIONS, | |
43 | restriction, | |
44 | "using a potentially dangerous silent `as` conversion" | |
45 | } | |
46 | ||
47 | declare_lint_pass!(AsConversions => [AS_CONVERSIONS]); | |
48 | ||
49 | impl EarlyLintPass for AsConversions { | |
50 | fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { | |
51 | if in_external_macro(cx.sess(), expr.span) { | |
52 | return; | |
53 | } | |
54 | ||
55 | if let ExprKind::Cast(_, _) = expr.kind { | |
56 | span_lint_and_help( | |
57 | cx, | |
58 | AS_CONVERSIONS, | |
59 | expr.span, | |
60 | "using a potentially dangerous silent `as` conversion", | |
61 | None, | |
62 | "consider using a safe wrapper for this conversion", | |
63 | ); | |
64 | } | |
65 | } | |
66 | } |