1- use clippy_utils:: diagnostics:: span_lint_and_sugg;
1+ use clippy_utils:: diagnostics:: { span_lint_and_sugg, span_lint_and_then } ;
22use clippy_utils:: msrvs:: Msrv ;
33use clippy_utils:: source:: { snippet_with_applicability, snippet_with_context} ;
44use 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} ;
66use rustc_errors:: Applicability ;
77use rustc_hir:: { BorrowKind , Expr , ExprKind , Mutability , Ty , TyKind } ;
88use rustc_lint:: LateContext ;
9+ use rustc_middle:: ty:: adjustment:: { Adjust , AutoBorrow } ;
910use rustc_span:: BytePos ;
1011
1112use super :: BORROW_AS_PTR ;
@@ -29,10 +30,6 @@ pub(super) fn check<'tcx>(
2930 }
3031
3132 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- } ;
3633 // Make sure that the span to be replaced doesn't include parentheses, that could break the
3734 // suggestion.
3835 let span = if has_enclosing_paren ( snippet_with_applicability ( cx, expr. span , "" , & mut app) ) {
@@ -42,7 +39,7 @@ pub(super) fn check<'tcx>(
4239 } else {
4340 expr. span
4441 } ;
45- ( format ! ( "&raw {operator_kind } {snip}" ) , span)
42+ ( format ! ( "&raw {} {snip}" , mutability . ptr_str ( ) ) , span)
4643 } else {
4744 let Some ( std_or_core) = std_or_core ( cx) else {
4845 return false ;
@@ -59,3 +56,25 @@ pub(super) fn check<'tcx>(
5956 }
6057 false
6158}
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