11use clippy_utils:: diagnostics:: span_lint_and_sugg;
22use clippy_utils:: numeric_literal:: NumericLiteral ;
33use clippy_utils:: res:: MaybeResPath as _;
4- use clippy_utils:: source:: { SpanRangeExt , snippet_opt} ;
4+ use clippy_utils:: source:: { SpanRangeExt , snippet, snippet_with_applicability} ;
5+ use clippy_utils:: sugg:: has_enclosing_paren;
56use clippy_utils:: visitors:: { Visitable , for_each_expr_without_closures} ;
67use clippy_utils:: { get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, sym} ;
78use rustc_ast:: { LitFloatType , LitIntType , LitKind } ;
@@ -24,7 +25,8 @@ pub(super) fn check<'tcx>(
2425 cast_from : Ty < ' tcx > ,
2526 cast_to : Ty < ' tcx > ,
2627) -> bool {
27- let cast_str = snippet_opt ( cx, cast_expr. span ) . unwrap_or_default ( ) ;
28+ let mut app = Applicability :: MachineApplicable ;
29+ let cast_str = snippet_with_applicability ( cx, cast_expr. span , "_" , & mut app) ;
2830
2931 if let ty:: RawPtr ( ..) = cast_from. kind ( )
3032 // check both mutability and type are the same
@@ -47,16 +49,23 @@ pub(super) fn check<'tcx>(
4749 _ => { } ,
4850 }
4951
50- span_lint_and_sugg (
52+ // Preserve parentheses around `expr` in case of cascaded casts
53+ let surrounding =
54+ if matches ! ( cast_expr. kind, ExprKind :: Cast ( ..) ) && has_enclosing_paren ( snippet ( cx, expr. span , "" ) ) {
55+ MaybeParenOrBlock :: Paren
56+ } else {
57+ MaybeParenOrBlock :: Nothing
58+ } ;
59+
60+ emit_lint (
5161 cx,
52- UNNECESSARY_CAST ,
53- expr. span ,
62+ expr,
5463 format ! (
5564 "casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"
5665 ) ,
57- "try" ,
58- cast_str . clone ( ) ,
59- Applicability :: MaybeIncorrect ,
66+ & cast_str ,
67+ surrounding ,
68+ app . max ( Applicability :: MaybeIncorrect ) ,
6069 ) ;
6170 }
6271
@@ -143,12 +152,6 @@ pub(super) fn check<'tcx>(
143152 }
144153
145154 if cast_from. kind ( ) == cast_to. kind ( ) && !expr. span . in_external_macro ( cx. sess ( ) . source_map ( ) ) {
146- enum MaybeParenOrBlock {
147- Paren ,
148- Block ,
149- Nothing ,
150- }
151-
152155 fn is_borrow_expr ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
153156 matches ! ( expr. kind, ExprKind :: AddrOf ( ..) )
154157 || cx
@@ -188,18 +191,13 @@ pub(super) fn check<'tcx>(
188191 _ => MaybeParenOrBlock :: Nothing ,
189192 } ;
190193
191- span_lint_and_sugg (
194+ emit_lint (
192195 cx,
193- UNNECESSARY_CAST ,
194- expr. span ,
196+ expr,
195197 format ! ( "casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)" ) ,
196- "try" ,
197- match surrounding {
198- MaybeParenOrBlock :: Paren => format ! ( "({cast_str})" ) ,
199- MaybeParenOrBlock :: Block => format ! ( "{{ {cast_str} }}" ) ,
200- MaybeParenOrBlock :: Nothing => cast_str,
201- } ,
202- Applicability :: MachineApplicable ,
198+ & cast_str,
199+ surrounding,
200+ app,
203201 ) ;
204202 return true ;
205203 }
@@ -312,3 +310,33 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
312310 } )
313311 . is_some ( )
314312}
313+
314+ #[ derive( Clone , Copy ) ]
315+ enum MaybeParenOrBlock {
316+ Paren ,
317+ Block ,
318+ Nothing ,
319+ }
320+
321+ fn emit_lint (
322+ cx : & LateContext < ' _ > ,
323+ expr : & Expr < ' _ > ,
324+ msg : String ,
325+ sugg : & str ,
326+ surrounding : MaybeParenOrBlock ,
327+ applicability : Applicability ,
328+ ) {
329+ span_lint_and_sugg (
330+ cx,
331+ UNNECESSARY_CAST ,
332+ expr. span ,
333+ msg,
334+ "try" ,
335+ match surrounding {
336+ MaybeParenOrBlock :: Paren => format ! ( "({sugg})" ) ,
337+ MaybeParenOrBlock :: Block => format ! ( "{{ {sugg} }}" ) ,
338+ MaybeParenOrBlock :: Nothing => sugg. to_string ( ) ,
339+ } ,
340+ applicability,
341+ ) ;
342+ }
0 commit comments