summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs32
1 files changed, 28 insertions, 4 deletions
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index a63764849..823970e35 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -1,11 +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_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_span::Span;
use rustc_target::abi::IntegerType;
use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
@@ -74,7 +77,14 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
}
}
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+pub(super) fn check(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ cast_expr: &Expr<'_>,
+ cast_from: Ty<'_>,
+ cast_to: Ty<'_>,
+ cast_to_span: Span,
+) {
let msg = match (cast_from.kind(), cast_to.is_integral()) {
(ty::Int(_) | ty::Uint(_), true) => {
let from_nbits = apply_reductions(
@@ -139,7 +149,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) => {
@@ -153,5 +163,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
_ => return,
};
- span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg);
+ let name_of_cast_from = snippet(cx, cast_expr.span, "..");
+ let cast_to_snip = snippet(cx, cast_to_span, "..");
+ let suggestion = format!("{cast_to_snip}::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_possible_truncation)]` ...");
+ 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,
+ );
+ });
}