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,56 @@ 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
+ let mut app = Applicability :: MachineApplicable ;
31
+ if let ExprKind :: Call ( func, [ ] ) = cast_expr. kind
32
+ && let ExprKind :: Path ( QPath :: Resolved ( None , path) ) = func. kind
33
+ && let Some ( defid) = path. res . opt_def_id ( )
34
+ && let Some ( prefix) = std_or_core ( cx)
35
+ && let sugg = format ! ( "{}" , Sugg :: hir_with_applicability( cx, cast_expr, "_" , & mut app) )
36
+ && let Some ( ( _, after_lt) ) = sugg. split_once ( "::<" )
37
+ {
38
+ if cx. tcx . is_diagnostic_item ( sym:: ptr_null, defid) {
39
+ span_lint_and_sugg (
40
+ cx,
41
+ PTR_CAST_CONSTNESS ,
42
+ expr. span ,
43
+ "`as` casting to make a const null pointer into a mutable null pointer" ,
44
+ "use `null_mut()` directly instead" ,
45
+ format ! ( "{prefix}::ptr::null_mut::<{after_lt}" ) ,
46
+ app,
47
+ ) ;
48
+ return ;
49
+ }
50
+ if cx. tcx . is_diagnostic_item ( sym:: ptr_null_mut, defid) {
51
+ span_lint_and_sugg (
52
+ cx,
53
+ PTR_CAST_CONSTNESS ,
54
+ expr. span ,
55
+ "`as` casting to make a mutable null pointer into an immutable null pointer" ,
56
+ "use `null()` directly instead" ,
57
+ format ! ( "{prefix}::ptr::null::<{after_lt}" ) ,
58
+ app,
59
+ ) ;
60
+ return ;
61
+ }
62
+ }
34
63
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
- ) ;
64
+ if msrv. meets ( msrvs:: POINTER_CAST_CONSTNESS ) {
65
+ let sugg = Sugg :: hir ( cx, cast_expr, "_" ) ;
66
+ let constness = match * to_mutbl {
67
+ Mutability :: Not => "const" ,
68
+ Mutability :: Mut => "mut" ,
69
+ } ;
70
+
71
+ span_lint_and_sugg (
72
+ cx,
73
+ PTR_CAST_CONSTNESS ,
74
+ expr. span ,
75
+ "`as` casting between raw pointers while changing only its constness" ,
76
+ format ! ( "try `pointer::cast_{constness}`, a safer alternative" ) ,
77
+ format ! ( "{}.cast_{constness}()" , sugg. maybe_par( ) ) ,
78
+ Applicability :: MachineApplicable ,
79
+ ) ;
80
+ }
44
81
}
45
82
}
0 commit comments