1
- use clippy_utils:: diagnostics:: span_lint_and_sugg;
1
+ use clippy_utils:: diagnostics:: { span_lint_and_sugg, span_lint_and_then } ;
2
2
use clippy_utils:: msrvs:: Msrv ;
3
3
use clippy_utils:: source:: { snippet_with_applicability, snippet_with_context} ;
4
4
use clippy_utils:: sugg:: has_enclosing_paren;
5
- use clippy_utils:: { is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core} ;
5
+ use clippy_utils:: { get_parent_expr , is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core} ;
6
6
use rustc_errors:: Applicability ;
7
7
use rustc_hir:: { BorrowKind , Expr , ExprKind , Mutability , Ty , TyKind } ;
8
8
use rustc_lint:: LateContext ;
9
+ use rustc_middle:: ty:: adjustment:: { Adjust , AutoBorrow } ;
9
10
use rustc_span:: BytePos ;
10
11
11
12
use super :: BORROW_AS_PTR ;
@@ -29,10 +30,6 @@ pub(super) fn check<'tcx>(
29
30
}
30
31
31
32
let ( suggestion, span) = if msrv. meets ( cx, msrvs:: RAW_REF_OP ) {
32
- let operator_kind = match mutability {
33
- Mutability :: Not => "const" ,
34
- Mutability :: Mut => "mut" ,
35
- } ;
36
33
// Make sure that the span to be replaced doesn't include parentheses, that could break the
37
34
// suggestion.
38
35
let span = if has_enclosing_paren ( snippet_with_applicability ( cx, expr. span , "" , & mut app) ) {
@@ -42,7 +39,7 @@ pub(super) fn check<'tcx>(
42
39
} else {
43
40
expr. span
44
41
} ;
45
- ( format ! ( "&raw {operator_kind } {snip}" ) , span)
42
+ ( format ! ( "&raw {} {snip}" , mutability . ptr_str ( ) ) , span)
46
43
} else {
47
44
let Some ( std_or_core) = std_or_core ( cx) else {
48
45
return false ;
@@ -59,3 +56,25 @@ pub(super) fn check<'tcx>(
59
56
}
60
57
false
61
58
}
59
+
60
+ /// Check for an implicit cast from reference to raw pointer outside an explicit `as`.
61
+ pub ( super ) fn check_implicit_cast ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
62
+ if !expr. span . from_expansion ( )
63
+ && let ExprKind :: AddrOf ( BorrowKind :: Ref , _, pointee) = expr. kind
64
+ && !matches ! ( get_parent_expr( cx, expr) . map( |e| e. kind) , Some ( ExprKind :: Cast ( ..) ) )
65
+ && let [ deref, borrow] = cx. typeck_results ( ) . expr_adjustments ( expr)
66
+ && matches ! ( deref. kind, Adjust :: Deref ( ..) )
67
+ && let Adjust :: Borrow ( AutoBorrow :: RawPtr ( mutability) ) = borrow. kind
68
+ // Do not suggest taking a raw pointer to a temporary value
69
+ && !is_expr_temporary_value ( cx, pointee)
70
+ {
71
+ span_lint_and_then ( cx, BORROW_AS_PTR , expr. span , "implicit borrow as raw pointer" , |diag| {
72
+ diag. span_suggestion_verbose (
73
+ expr. span . until ( pointee. span ) ,
74
+ "use a raw pointer instead" ,
75
+ format ! ( "&raw {} " , mutability. ptr_str( ) ) ,
76
+ Applicability :: MachineApplicable ,
77
+ ) ;
78
+ } ) ;
79
+ }
80
+ }
0 commit comments