11use clippy_config:: msrvs:: { self , Msrv } ;
22use clippy_utils:: diagnostics:: span_lint_and_sugg;
3+ use clippy_utils:: std_or_core;
34use clippy_utils:: sugg:: Sugg ;
45use rustc_errors:: Applicability ;
5- use rustc_hir:: { Expr , Mutability } ;
6+ use rustc_hir:: { Expr , ExprKind , Mutability , QPath } ;
67use rustc_lint:: LateContext ;
78use rustc_middle:: ty:: { self , Ty , TypeVisitableExt } ;
9+ use rustc_span:: sym;
810
911use super :: PTR_CAST_CONSTNESS ;
1012
@@ -16,8 +18,7 @@ pub(super) fn check<'tcx>(
1618 cast_to : Ty < ' tcx > ,
1719 msrv : & Msrv ,
1820) {
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 ( )
2122 && let ty:: RawPtr ( to_ty, to_mutbl) = cast_to. kind ( )
2223 && matches ! (
2324 ( from_mutbl, to_mutbl) ,
@@ -26,20 +27,47 @@ pub(super) fn check<'tcx>(
2627 && from_ty == to_ty
2728 && !from_ty. has_erased_regions ( )
2829 {
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+ }
3454
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+ }
4472 }
4573}
0 commit comments