]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/casts/cast_possible_truncation.rs
Last PR adjustments
[rust.git] / clippy_lints / src / casts / cast_possible_truncation.rs
index 88deb4565eb216cb801b49e659418ffd42b74131..7a6450ffaa5ec17be291ab61e854cf91b4274919 100644 (file)
@@ -1,13 +1,14 @@
 use clippy_utils::consts::{constant, Constant};
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::expr_or_init;
+use clippy_utils::source::snippet;
 use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
-use rustc_ast::ast;
-use rustc_attr::IntType;
+use rustc_errors::{Applicability, SuggestionStyle};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
+use rustc_target::abi::IntegerType;
 
 use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
 
@@ -119,12 +120,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
             };
             let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
 
-            let cast_from_ptr_size = def.repr().int.map_or(true, |ty| {
-                matches!(
-                    ty,
-                    IntType::SignedInt(ast::IntTy::Isize) | IntType::UnsignedInt(ast::UintTy::Usize)
-                )
-            });
+            let cast_from_ptr_size = def.repr().int.map_or(true, |ty| matches!(ty, IntegerType::Pointer(_),));
             let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) {
                 (false, false) if from_nbits > to_nbits => "",
                 (true, false) if from_nbits > to_nbits => "",
@@ -145,7 +141,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                 );
                 return;
             }
-            format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",)
+            format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}")
         },
 
         (ty::Float(_), true) => {
@@ -159,5 +155,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
         _ => return,
     };
 
-    span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg);
+    let snippet = snippet(cx, expr.span, "..");
+    let name_of_cast_from = snippet.split(" as").next().unwrap_or("..");
+    let suggestion = format!("{cast_to}::try_from({name_of_cast_from})");
+
+    span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
+        diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...");
+        diag.span_suggestion_with_style(
+            expr.span,
+            "... or use `try_from` and handle the error accordingly",
+            suggestion,
+            Applicability::Unspecified,
+            // always show the suggestion in a separate line
+            SuggestionStyle::ShowAlways,
+        );
+    });
 }