@@ -2,11 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
2
2
use clippy_utils:: numeric_literal:: NumericLiteral ;
3
3
use clippy_utils:: source:: snippet_opt;
4
4
use clippy_utils:: visitors:: { for_each_expr, Visitable } ;
5
- use clippy_utils:: { get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local} ;
5
+ use clippy_utils:: { get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local, SpanlessEq } ;
6
6
use rustc_ast:: { LitFloatType , LitIntType , LitKind } ;
7
7
use rustc_errors:: Applicability ;
8
8
use rustc_hir:: def:: { DefKind , Res } ;
9
- use rustc_hir:: { Expr , ExprKind , Lit , Node , Path , QPath , TyKind , UnOp } ;
9
+ use rustc_hir:: { self as hir , Expr , ExprKind , Lit , Node , Path , QPath , TyKind , UnOp } ;
10
10
use rustc_lint:: { LateContext , LintContext } ;
11
11
use rustc_middle:: lint:: in_external_macro;
12
12
use rustc_middle:: ty:: { self , FloatTy , InferTy , Ty } ;
@@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(
27
27
if let ty:: RawPtr ( ..) = cast_from. kind ( )
28
28
// check both mutability and type are the same
29
29
&& cast_from. kind ( ) == cast_to. kind ( )
30
- && let ExprKind :: Cast ( _ , cast_to_hir) = expr. kind
30
+ && let ExprKind :: Cast ( cast_from_expr , cast_to_hir) = expr. kind
31
31
// Ignore casts to e.g. type aliases and infer types
32
32
// - p as pointer_alias
33
33
// - p as _
@@ -41,6 +41,25 @@ pub(super) fn check<'tcx>(
41
41
if is_ty_alias ( & qpath) || is_hir_ty_cfg_dependant ( cx, to_pointee. ty ) {
42
42
return false ;
43
43
}
44
+
45
+ if let Some ( cast_from_hir_ty) = get_expr_hir_ty ( cx, cast_from_expr)
46
+ && let TyKind :: Ptr ( from_pointee) = cast_from_hir_ty. kind
47
+ && let TyKind :: Path ( QPath :: Resolved (
48
+ _,
49
+ Path {
50
+ segments : from_ty_seg, ..
51
+ } ,
52
+ ) ) = from_pointee. ty . kind
53
+ && let QPath :: Resolved (
54
+ _,
55
+ Path {
56
+ segments : to_ty_seg, ..
57
+ } ,
58
+ ) = qpath
59
+ && !SpanlessEq :: new ( cx) . eq_path_segments ( from_ty_seg, to_ty_seg)
60
+ {
61
+ return false ;
62
+ }
44
63
} ,
45
64
// Ignore `p as *const _`
46
65
TyKind :: Infer => return false ,
@@ -300,3 +319,30 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
300
319
fn snippet_eq_ty ( snippet : & str , ty : Ty < ' _ > ) -> bool {
301
320
snippet. trim ( ) == ty. to_string ( ) || snippet. trim ( ) . contains ( & format ! ( "::{ty}" ) )
302
321
}
322
+
323
+ fn get_expr_hir_ty < ' hir > ( cx : & LateContext < ' hir > , expr : & Expr < ' hir > ) -> Option < & ' hir hir:: Ty < ' hir > > {
324
+ match expr. kind {
325
+ ExprKind :: AddrOf ( _, _, inner) => get_expr_hir_ty ( cx, inner) ,
326
+ ExprKind :: Block ( hir:: Block { expr : Some ( inner) , .. } , _) => get_expr_hir_ty ( cx, inner) ,
327
+ ExprKind :: Cast ( _, ty) => Some ( ty) ,
328
+ ExprKind :: Call ( _caller, _) => {
329
+ // TODO: handle function call
330
+ // println!("calling: {caller:#?}");
331
+ None
332
+ } ,
333
+ ExprKind :: MethodCall ( _path, ..) => {
334
+ // TODO: handle method call
335
+ // println!("calling: {path:#?}");
336
+ None
337
+ } ,
338
+ ExprKind :: Path ( _) if let Some ( local_id) = path_to_local ( expr) => match cx. tcx . parent_hir_node ( local_id) {
339
+ Node :: Param ( param) => {
340
+ let parent_of_param = cx. tcx . parent_hir_node ( param. hir_id ) ;
341
+ let fn_decl = parent_of_param. fn_decl ( ) ?;
342
+ fn_decl. inputs . iter ( ) . find ( |ty| ty. span == param. ty_span )
343
+ } ,
344
+ _ => None ,
345
+ } ,
346
+ _ => None ,
347
+ }
348
+ }
0 commit comments