@@ -2,15 +2,18 @@ use std::convert::Infallible;
22use std:: ops:: ControlFlow ;
33
44use clippy_utils:: consts:: { ConstEvalCtxt , Constant } ;
5- use clippy_utils:: diagnostics:: span_lint;
5+ use clippy_utils:: diagnostics:: span_lint_and_then;
6+ use clippy_utils:: msrvs:: { self , Msrv } ;
7+ use clippy_utils:: sugg:: Sugg ;
68use clippy_utils:: visitors:: { Descend , for_each_expr_without_closures} ;
79use clippy_utils:: { method_chain_args, sext, sym} ;
10+ use rustc_errors:: Applicability ;
811use rustc_hir:: { BinOpKind , Expr , ExprKind } ;
912use rustc_lint:: LateContext ;
1013use rustc_middle:: ty:: { self , Ty } ;
1114use rustc_span:: Symbol ;
1215
13- use super :: CAST_SIGN_LOSS ;
16+ use super :: { CAST_SIGN_LOSS , utils } ;
1417
1518/// A list of methods that can never return a negative value.
1619/// Includes methods that panic rather than returning a negative value.
@@ -42,13 +45,33 @@ pub(super) fn check<'cx>(
4245 cast_op : & Expr < ' _ > ,
4346 cast_from : Ty < ' cx > ,
4447 cast_to : Ty < ' _ > ,
48+ msrv : Msrv ,
4549) {
4650 if should_lint ( cx, cast_op, cast_from, cast_to) {
47- span_lint (
51+ span_lint_and_then (
4852 cx,
4953 CAST_SIGN_LOSS ,
5054 expr. span ,
5155 format ! ( "casting `{cast_from}` to `{cast_to}` may lose the sign of the value" ) ,
56+ |diag| {
57+ if msrv. meets ( cx, msrvs:: INTEGER_SIGN_CAST )
58+ && let Some ( cast) = utils:: is_signedness_cast ( cast_from, cast_to)
59+ {
60+ let method = match cast {
61+ utils:: CastTo :: Signed => "cast_signed()" ,
62+ utils:: CastTo :: Unsigned => "cast_unsigned()" ,
63+ } ;
64+ let mut app = Applicability :: MaybeIncorrect ;
65+ let sugg = Sugg :: hir_with_context ( cx, cast_op, expr. span . ctxt ( ) , ".." , & mut app) ;
66+
67+ diag. span_suggestion (
68+ expr. span ,
69+ format ! ( "if this is intentional, consider using `{method}` instead" ) ,
70+ format ! ( "{}.{method}" , sugg. maybe_paren( ) ) ,
71+ app,
72+ ) ;
73+ }
74+ } ,
5275 ) ;
5376 }
5477}
0 commit comments