1
1
use clippy_config:: msrvs:: { self , Msrv } ;
2
2
use clippy_utils:: diagnostics:: span_lint_and_sugg;
3
+ use clippy_utils:: std_or_core;
3
4
use clippy_utils:: sugg:: Sugg ;
4
5
use rustc_errors:: Applicability ;
5
- use rustc_hir:: { Expr , Mutability } ;
6
+ use rustc_hir:: { Expr , ExprKind , Mutability , QPath } ;
6
7
use rustc_lint:: LateContext ;
7
8
use rustc_middle:: ty:: { self , Ty , TypeVisitableExt } ;
9
+ use rustc_span:: sym;
8
10
9
11
use super :: PTR_CAST_CONSTNESS ;
10
12
@@ -16,8 +18,7 @@ pub(super) fn check<'tcx>(
16
18
cast_to : Ty < ' tcx > ,
17
19
msrv : & Msrv ,
18
20
) {
19
- if msrv. meets ( msrvs:: POINTER_CAST_CONSTNESS )
20
- && let ty:: RawPtr ( from_ty, from_mutbl) = cast_from. kind ( )
21
+ if let ty:: RawPtr ( from_ty, from_mutbl) = cast_from. kind ( )
21
22
&& let ty:: RawPtr ( to_ty, to_mutbl) = cast_to. kind ( )
22
23
&& matches ! (
23
24
( from_mutbl, to_mutbl) ,
@@ -26,20 +27,47 @@ pub(super) fn check<'tcx>(
26
27
&& from_ty == to_ty
27
28
&& !from_ty. has_erased_regions ( )
28
29
{
29
- let sugg = Sugg :: hir ( cx, cast_expr, "_" ) ;
30
- let constness = match * to_mutbl {
31
- Mutability :: Not => "const" ,
32
- Mutability :: Mut => "mut" ,
33
- } ;
30
+ if let ExprKind :: Call ( func, [ ] ) = cast_expr. kind
31
+ && let ExprKind :: Path ( QPath :: Resolved ( None , path) ) = func. kind
32
+ && let Some ( defid) = path. res . opt_def_id ( )
33
+ && let Some ( prefix) = std_or_core ( cx)
34
+ && let mut app = Applicability :: MachineApplicable
35
+ && let sugg = format ! ( "{}" , Sugg :: hir_with_applicability( cx, cast_expr, "_" , & mut app) )
36
+ && let Some ( ( _, after_lt) ) = sugg. split_once ( "::<" )
37
+ && let Some ( ( source, target, target_func) ) = match cx. tcx . get_diagnostic_name ( defid) {
38
+ Some ( sym:: ptr_null) => Some ( ( "const" , "mutable" , "null_mut" ) ) ,
39
+ Some ( sym:: ptr_null_mut) => Some ( ( "mutable" , "const" , "null" ) ) ,
40
+ _ => None ,
41
+ }
42
+ {
43
+ span_lint_and_sugg (
44
+ cx,
45
+ PTR_CAST_CONSTNESS ,
46
+ expr. span ,
47
+ format ! ( "`as` casting to make a {source} null pointer into a {target} null pointer" ) ,
48
+ format ! ( "use `{target_func}()` directly instead" ) ,
49
+ format ! ( "{prefix}::ptr::{target_func}::<{after_lt}" ) ,
50
+ app,
51
+ ) ;
52
+ return ;
53
+ }
34
54
35
- span_lint_and_sugg (
36
- cx,
37
- PTR_CAST_CONSTNESS ,
38
- expr. span ,
39
- "`as` casting between raw pointers while changing only its constness" ,
40
- format ! ( "try `pointer::cast_{constness}`, a safer alternative" ) ,
41
- format ! ( "{}.cast_{constness}()" , sugg. maybe_par( ) ) ,
42
- Applicability :: MachineApplicable ,
43
- ) ;
55
+ if msrv. meets ( msrvs:: POINTER_CAST_CONSTNESS ) {
56
+ let sugg = Sugg :: hir ( cx, cast_expr, "_" ) ;
57
+ let constness = match * to_mutbl {
58
+ Mutability :: Not => "const" ,
59
+ Mutability :: Mut => "mut" ,
60
+ } ;
61
+
62
+ span_lint_and_sugg (
63
+ cx,
64
+ PTR_CAST_CONSTNESS ,
65
+ expr. span ,
66
+ "`as` casting between raw pointers while changing only its constness" ,
67
+ format ! ( "try `pointer::cast_{constness}`, a safer alternative" ) ,
68
+ format ! ( "{}.cast_{constness}()" , sugg. maybe_par( ) ) ,
69
+ Applicability :: MachineApplicable ,
70
+ ) ;
71
+ }
44
72
}
45
73
}
0 commit comments