about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarcin Serwin <marcin.serwin0@protonmail.com>2024-01-02 22:54:17 +0100
committerblyxyas <blyxyas@gmail.com>2024-02-04 17:38:09 +0100
commita3baebcb3147773c9673e4ea166e3419201e8b9f (patch)
tree8414f8dc14561e6acf62d0a0aff67a5241828dbd
parentbc962c246a8f3efe4a1217b36c64a03652493327 (diff)
downloadrust-a3baebcb3147773c9673e4ea166e3419201e8b9f.tar.gz
rust-a3baebcb3147773c9673e4ea166e3419201e8b9f.zip
Add ref_as_ptr lint
Author:    Marcin Serwin <marcin.serwin0@protonmail.com>
-rw-r--r--CHANGELOG.md1
-rw-r--r--README.md2
-rw-r--r--book/src/README.md2
-rw-r--r--clippy_config/src/msrvs.rs1
-rw-r--r--clippy_lints/src/casts/mod.rs30
-rw-r--r--clippy_lints/src/casts/ref_as_ptr.rs55
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/only_used_in_recursion.rs5
-rw-r--r--tests/ui/borrow_as_ptr.fixed1
-rw-r--r--tests/ui/borrow_as_ptr.rs1
-rw-r--r--tests/ui/borrow_as_ptr.stderr4
-rw-r--r--tests/ui/borrow_as_ptr_no_std.fixed1
-rw-r--r--tests/ui/borrow_as_ptr_no_std.rs1
-rw-r--r--tests/ui/borrow_as_ptr_no_std.stderr4
-rw-r--r--tests/ui/ref_as_ptr.fixed110
-rw-r--r--tests/ui/ref_as_ptr.rs110
-rw-r--r--tests/ui/ref_as_ptr.stderr269
17 files changed, 588 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6c081ca94f..a03878c54c7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5522,6 +5522,7 @@ Released 2018-09-13
 [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing
 [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
 [`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations
+[`ref_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_as_ptr
 [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
 [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
diff --git a/README.md b/README.md
index 5d490645d89..0450b54121d 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 
 A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
 
-[There are over 650 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
 
 Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
 You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
diff --git a/book/src/README.md b/book/src/README.md
index 486ea3df704..e7972b0db19 100644
--- a/book/src/README.md
+++ b/book/src/README.md
@@ -6,7 +6,7 @@
 A collection of lints to catch common mistakes and improve your
 [Rust](https://github.com/rust-lang/rust) code.
 
-[There are over 650 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
 
 Lints are divided into categories, each with a default [lint
 level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how
diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index 3507e106fab..0032a66365c 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -16,6 +16,7 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
+    1,76,0 { PTR_FROM_REF }
     1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
     1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN }
     1,68,0 { PATH_MAIN_SEPARATOR_STR }
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index e05b8f66d86..14f2f4a7f59 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -18,6 +18,7 @@ mod fn_to_numeric_cast_any;
 mod fn_to_numeric_cast_with_truncation;
 mod ptr_as_ptr;
 mod ptr_cast_constness;
+mod ref_as_ptr;
 mod unnecessary_cast;
 mod utils;
 mod zero_ptr;
@@ -689,6 +690,30 @@ declare_clippy_lint! {
     "using `0 as *{const, mut} T`"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for casts of references to pointer using `as`
+    /// and suggests `std::ptr::from_ref` and `std::ptr::from_mut` instead.
+    ///
+    /// ### Why is this bad?
+    /// Using `as` casts may result in silently changing mutability or type.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let a_ref = &1;
+    /// let a_ptr = a_ref as *const _;
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// let a_ref = &1;
+    /// let a_ptr = std::ptr::from_ref(a_ref);
+    /// ```
+    #[clippy::version = "1.77.0"]
+    pub REF_AS_PTR,
+    pedantic,
+    "using `as` to cast a reference to pointer"
+}
+
 pub struct Casts {
     msrv: Msrv,
 }
@@ -724,6 +749,7 @@ impl_lint_pass!(Casts => [
     AS_PTR_CAST_MUT,
     CAST_NAN_TO_INT,
     ZERO_PTR,
+    REF_AS_PTR,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Casts {
@@ -771,7 +797,9 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
 
             as_underscore::check(cx, expr, cast_to_hir);
 
-            if self.msrv.meets(msrvs::BORROW_AS_PTR) {
+            if self.msrv.meets(msrvs::PTR_FROM_REF) {
+                ref_as_ptr::check(cx, expr, cast_expr, cast_to_hir);
+            } else if self.msrv.meets(msrvs::BORROW_AS_PTR) {
                 borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir);
             }
         }
diff --git a/clippy_lints/src/casts/ref_as_ptr.rs b/clippy_lints/src/casts/ref_as_ptr.rs
new file mode 100644
index 00000000000..d600d2aec1b
--- /dev/null
+++ b/clippy_lints/src/casts/ref_as_ptr.rs
@@ -0,0 +1,55 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_no_std_crate;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, Mutability, Ty, TyKind};
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self, TypeAndMut};
+
+use super::REF_AS_PTR;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to_hir_ty: &Ty<'_>) {
+    let (cast_from, cast_to) = (
+        cx.typeck_results().expr_ty(cast_expr),
+        cx.typeck_results().expr_ty(expr),
+    );
+
+    if matches!(cast_from.kind(), ty::Ref(..))
+        && let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind()
+    {
+        let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" };
+        let fn_name = match to_mutbl {
+            Mutability::Not => "from_ref",
+            Mutability::Mut => "from_mut",
+        };
+
+        let mut app = Applicability::MachineApplicable;
+        let turbofish = match &cast_to_hir_ty.kind {
+            TyKind::Infer => String::new(),
+            TyKind::Ptr(mut_ty) => {
+                if matches!(mut_ty.ty.kind, TyKind::Infer) {
+                    String::new()
+                } else {
+                    format!(
+                        "::<{}>",
+                        snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app)
+                    )
+                }
+            },
+            _ => return,
+        };
+
+        let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
+
+        span_lint_and_sugg(
+            cx,
+            REF_AS_PTR,
+            expr.span,
+            "reference as raw pointer",
+            "try",
+            format!("{core_or_std}::ptr::{fn_name}{turbofish}({cast_expr_sugg})"),
+            app,
+        );
+    }
+}
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index f6c9ffea9fc..ccb7b25066d 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -96,6 +96,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO,
     crate::casts::PTR_AS_PTR_INFO,
     crate::casts::PTR_CAST_CONSTNESS_INFO,
+    crate::casts::REF_AS_PTR_INFO,
     crate::casts::UNNECESSARY_CAST_INFO,
     crate::casts::ZERO_PTR_INFO,
     crate::checked_conversions::CHECKED_CONVERSIONS_INFO,
diff --git a/clippy_lints/src/only_used_in_recursion.rs b/clippy_lints/src/only_used_in_recursion.rs
index d621051ef16..ae14016f482 100644
--- a/clippy_lints/src/only_used_in_recursion.rs
+++ b/clippy_lints/src/only_used_in_recursion.rs
@@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
                 {
                     (
                         trait_item_id,
-                        FnKind::ImplTraitFn(cx.tcx.erase_regions(trait_ref.args) as *const _ as usize),
+                        FnKind::ImplTraitFn(std::ptr::from_ref(cx.tcx.erase_regions(trait_ref.args)) as usize),
                         usize::from(sig.decl.implicit_self.has_implicit_self()),
                     )
                 } else {
@@ -390,7 +390,6 @@ fn has_matching_args(kind: FnKind, args: GenericArgsRef<'_>) -> bool {
             GenericArgKind::Type(ty) => matches!(*ty.kind(), ty::Param(ty) if ty.index as usize == idx),
             GenericArgKind::Const(c) => matches!(c.kind(), ConstKind::Param(c) if c.index as usize == idx),
         }),
-        #[allow(trivial_casts)]
-        FnKind::ImplTraitFn(expected_args) => args as *const _ as usize == expected_args,
+        FnKind::ImplTraitFn(expected_args) => std::ptr::from_ref(args) as usize == expected_args,
     }
 }
diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed
index 6c0de96d65e..289a5ef38b8 100644
--- a/tests/ui/borrow_as_ptr.fixed
+++ b/tests/ui/borrow_as_ptr.fixed
@@ -5,6 +5,7 @@ fn a() -> i32 {
     0
 }
 
+#[clippy::msrv = "1.75"]
 fn main() {
     let val = 1;
     let _p = std::ptr::addr_of!(val);
diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs
index c37c5357c82..b5328cb22dc 100644
--- a/tests/ui/borrow_as_ptr.rs
+++ b/tests/ui/borrow_as_ptr.rs
@@ -5,6 +5,7 @@ fn a() -> i32 {
     0
 }
 
+#[clippy::msrv = "1.75"]
 fn main() {
     let val = 1;
     let _p = &val as *const i32;
diff --git a/tests/ui/borrow_as_ptr.stderr b/tests/ui/borrow_as_ptr.stderr
index 43a7a6bf5b5..b9861805905 100644
--- a/tests/ui/borrow_as_ptr.stderr
+++ b/tests/ui/borrow_as_ptr.stderr
@@ -1,5 +1,5 @@
 error: borrow as raw pointer
-  --> $DIR/borrow_as_ptr.rs:10:14
+  --> $DIR/borrow_as_ptr.rs:11:14
    |
 LL |     let _p = &val as *const i32;
    |              ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of!(val)`
@@ -8,7 +8,7 @@ LL |     let _p = &val as *const i32;
    = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]`
 
 error: borrow as raw pointer
-  --> $DIR/borrow_as_ptr.rs:17:18
+  --> $DIR/borrow_as_ptr.rs:18:18
    |
 LL |     let _p_mut = &mut val_mut as *mut i32;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)`
diff --git a/tests/ui/borrow_as_ptr_no_std.fixed b/tests/ui/borrow_as_ptr_no_std.fixed
index a361a36474d..f66554de300 100644
--- a/tests/ui/borrow_as_ptr_no_std.fixed
+++ b/tests/ui/borrow_as_ptr_no_std.fixed
@@ -2,6 +2,7 @@
 #![feature(lang_items, start, libc)]
 #![no_std]
 
+#[clippy::msrv = "1.75"]
 #[start]
 fn main(_argc: isize, _argv: *const *const u8) -> isize {
     let val = 1;
diff --git a/tests/ui/borrow_as_ptr_no_std.rs b/tests/ui/borrow_as_ptr_no_std.rs
index b3fe01442b7..1fc254aafa7 100644
--- a/tests/ui/borrow_as_ptr_no_std.rs
+++ b/tests/ui/borrow_as_ptr_no_std.rs
@@ -2,6 +2,7 @@
 #![feature(lang_items, start, libc)]
 #![no_std]
 
+#[clippy::msrv = "1.75"]
 #[start]
 fn main(_argc: isize, _argv: *const *const u8) -> isize {
     let val = 1;
diff --git a/tests/ui/borrow_as_ptr_no_std.stderr b/tests/ui/borrow_as_ptr_no_std.stderr
index 2f258bcf966..1ef0a948a32 100644
--- a/tests/ui/borrow_as_ptr_no_std.stderr
+++ b/tests/ui/borrow_as_ptr_no_std.stderr
@@ -1,5 +1,5 @@
 error: borrow as raw pointer
-  --> $DIR/borrow_as_ptr_no_std.rs:8:14
+  --> $DIR/borrow_as_ptr_no_std.rs:9:14
    |
 LL |     let _p = &val as *const i32;
    |              ^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of!(val)`
@@ -8,7 +8,7 @@ LL |     let _p = &val as *const i32;
    = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]`
 
 error: borrow as raw pointer
-  --> $DIR/borrow_as_ptr_no_std.rs:11:18
+  --> $DIR/borrow_as_ptr_no_std.rs:12:18
    |
 LL |     let _p_mut = &mut val_mut as *mut i32;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of_mut!(val_mut)`
diff --git a/tests/ui/ref_as_ptr.fixed b/tests/ui/ref_as_ptr.fixed
new file mode 100644
index 00000000000..7a946393f25
--- /dev/null
+++ b/tests/ui/ref_as_ptr.fixed
@@ -0,0 +1,110 @@
+#![warn(clippy::ref_as_ptr)]
+#![allow(clippy::unnecessary_mut_passed)]
+
+fn main() {
+    let _ = std::ptr::from_ref(&1u8);
+    let _ = std::ptr::from_ref::<u32>(&2u32);
+    let _ = std::ptr::from_ref::<f64>(&3.0f64);
+
+    let _ = std::ptr::from_ref(&4) as *const f32;
+    let _ = std::ptr::from_ref::<f32>(&5.0f32) as *const u32;
+
+    let _ = std::ptr::from_ref(&mut 6u8);
+    let _ = std::ptr::from_ref::<u32>(&mut 7u32);
+    let _ = std::ptr::from_ref::<f64>(&mut 8.0f64);
+
+    let _ = std::ptr::from_ref(&mut 9) as *const f32;
+    let _ = std::ptr::from_ref::<f32>(&mut 10.0f32) as *const u32;
+
+    let _ = std::ptr::from_mut(&mut 11u8);
+    let _ = std::ptr::from_mut::<u32>(&mut 12u32);
+    let _ = std::ptr::from_mut::<f64>(&mut 13.0f64);
+
+    let _ = std::ptr::from_mut(&mut 14) as *const f32;
+    let _ = std::ptr::from_mut::<f32>(&mut 15.0f32) as *const u32;
+
+    let _ = std::ptr::from_ref(&1u8);
+    let _ = std::ptr::from_ref::<u32>(&2u32);
+    let _ = std::ptr::from_ref::<f64>(&3.0f64);
+
+    let _ = std::ptr::from_ref(&4) as *const f32;
+    let _ = std::ptr::from_ref::<f32>(&5.0f32) as *const u32;
+
+    let val = 1;
+    let _ = std::ptr::from_ref(&val);
+    let _ = std::ptr::from_ref::<i32>(&val);
+
+    let _ = std::ptr::from_ref(&val) as *const f32;
+    let _ = std::ptr::from_ref::<i32>(&val) as *const f64;
+
+    let mut val: u8 = 2;
+    let _ = std::ptr::from_mut::<u8>(&mut val);
+    let _ = std::ptr::from_mut(&mut val);
+
+    let _ = std::ptr::from_ref::<u8>(&mut val);
+    let _ = std::ptr::from_ref(&mut val);
+
+    let _ = std::ptr::from_ref::<u8>(&mut val) as *const f64;
+    let _: *const Option<u8> = std::ptr::from_ref(&mut val) as *const _;
+
+    let _ = std::ptr::from_ref::<[usize; 7]>(&std::array::from_fn(|i| i * i));
+    let _ = std::ptr::from_ref::<[usize; 8]>(&mut std::array::from_fn(|i| i * i));
+    let _ = std::ptr::from_mut::<[usize; 9]>(&mut std::array::from_fn(|i| i * i));
+}
+
+#[clippy::msrv = "1.75"]
+fn _msrv_1_75() {
+    let val = &42_i32;
+    let mut_val = &mut 42_i32;
+
+    // `std::ptr::from_{ref, mut}` was stabilized in 1.76. Do not lint this
+    let _ = val as *const i32;
+    let _ = mut_val as *mut i32;
+}
+
+#[clippy::msrv = "1.76"]
+fn _msrv_1_76() {
+    let val = &42_i32;
+    let mut_val = &mut 42_i32;
+
+    let _ = std::ptr::from_ref::<i32>(val);
+    let _ = std::ptr::from_mut::<i32>(mut_val);
+}
+
+fn foo(val: &[u8]) {
+    let _ = std::ptr::from_ref(val);
+    let _ = std::ptr::from_ref::<[u8]>(val);
+}
+
+fn bar(val: &mut str) {
+    let _ = std::ptr::from_mut(val);
+    let _ = std::ptr::from_mut::<str>(val);
+}
+
+struct X<'a>(&'a i32);
+
+impl<'a> X<'a> {
+    fn foo(&self) -> *const i64 {
+        std::ptr::from_ref(self.0) as *const _
+    }
+
+    fn bar(&mut self) -> *const i64 {
+        std::ptr::from_ref(self.0) as *const _
+    }
+}
+
+struct Y<'a>(&'a mut i32);
+
+impl<'a> Y<'a> {
+    fn foo(&self) -> *const i64 {
+        std::ptr::from_ref(self.0) as *const _
+    }
+
+    fn bar(&mut self) -> *const i64 {
+        std::ptr::from_ref(self.0) as *const _
+    }
+
+    fn baz(&mut self) -> *const i64 {
+        std::ptr::from_mut(self.0) as *mut _
+    }
+}
diff --git a/tests/ui/ref_as_ptr.rs b/tests/ui/ref_as_ptr.rs
new file mode 100644
index 00000000000..6f745505b46
--- /dev/null
+++ b/tests/ui/ref_as_ptr.rs
@@ -0,0 +1,110 @@
+#![warn(clippy::ref_as_ptr)]
+#![allow(clippy::unnecessary_mut_passed)]
+
+fn main() {
+    let _ = &1u8 as *const _;
+    let _ = &2u32 as *const u32;
+    let _ = &3.0f64 as *const f64;
+
+    let _ = &4 as *const _ as *const f32;
+    let _ = &5.0f32 as *const f32 as *const u32;
+
+    let _ = &mut 6u8 as *const _;
+    let _ = &mut 7u32 as *const u32;
+    let _ = &mut 8.0f64 as *const f64;
+
+    let _ = &mut 9 as *const _ as *const f32;
+    let _ = &mut 10.0f32 as *const f32 as *const u32;
+
+    let _ = &mut 11u8 as *mut _;
+    let _ = &mut 12u32 as *mut u32;
+    let _ = &mut 13.0f64 as *mut f64;
+
+    let _ = &mut 14 as *mut _ as *const f32;
+    let _ = &mut 15.0f32 as *mut f32 as *const u32;
+
+    let _ = &1u8 as *const _;
+    let _ = &2u32 as *const u32;
+    let _ = &3.0f64 as *const f64;
+
+    let _ = &4 as *const _ as *const f32;
+    let _ = &5.0f32 as *const f32 as *const u32;
+
+    let val = 1;
+    let _ = &val as *const _;
+    let _ = &val as *const i32;
+
+    let _ = &val as *const _ as *const f32;
+    let _ = &val as *const i32 as *const f64;
+
+    let mut val: u8 = 2;
+    let _ = &mut val as *mut u8;
+    let _ = &mut val as *mut _;
+
+    let _ = &mut val as *const u8;
+    let _ = &mut val as *const _;
+
+    let _ = &mut val as *const u8 as *const f64;
+    let _: *const Option<u8> = &mut val as *const _ as *const _;
+
+    let _ = &std::array::from_fn(|i| i * i) as *const [usize; 7];
+    let _ = &mut std::array::from_fn(|i| i * i) as *const [usize; 8];
+    let _ = &mut std::array::from_fn(|i| i * i) as *mut [usize; 9];
+}
+
+#[clippy::msrv = "1.75"]
+fn _msrv_1_75() {
+    let val = &42_i32;
+    let mut_val = &mut 42_i32;
+
+    // `std::ptr::from_{ref, mut}` was stabilized in 1.76. Do not lint this
+    let _ = val as *const i32;
+    let _ = mut_val as *mut i32;
+}
+
+#[clippy::msrv = "1.76"]
+fn _msrv_1_76() {
+    let val = &42_i32;
+    let mut_val = &mut 42_i32;
+
+    let _ = val as *const i32;
+    let _ = mut_val as *mut i32;
+}
+
+fn foo(val: &[u8]) {
+    let _ = val as *const _;
+    let _ = val as *const [u8];
+}
+
+fn bar(val: &mut str) {
+    let _ = val as *mut _;
+    let _ = val as *mut str;
+}
+
+struct X<'a>(&'a i32);
+
+impl<'a> X<'a> {
+    fn foo(&self) -> *const i64 {
+        self.0 as *const _ as *const _
+    }
+
+    fn bar(&mut self) -> *const i64 {
+        self.0 as *const _ as *const _
+    }
+}
+
+struct Y<'a>(&'a mut i32);
+
+impl<'a> Y<'a> {
+    fn foo(&self) -> *const i64 {
+        self.0 as *const _ as *const _
+    }
+
+    fn bar(&mut self) -> *const i64 {
+        self.0 as *const _ as *const _
+    }
+
+    fn baz(&mut self) -> *const i64 {
+        self.0 as *mut _ as *mut _
+    }
+}
diff --git a/tests/ui/ref_as_ptr.stderr b/tests/ui/ref_as_ptr.stderr
new file mode 100644
index 00000000000..371d42df528
--- /dev/null
+++ b/tests/ui/ref_as_ptr.stderr
@@ -0,0 +1,269 @@
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:5:13
+   |
+LL |     let _ = &1u8 as *const _;
+   |             ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&1u8)`
+   |
+   = note: `-D clippy::ref-as-ptr` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::ref_as_ptr)]`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:6:13
+   |
+LL |     let _ = &2u32 as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u32>(&2u32)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:7:13
+   |
+LL |     let _ = &3.0f64 as *const f64;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f64>(&3.0f64)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:9:13
+   |
+LL |     let _ = &4 as *const _ as *const f32;
+   |             ^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&4)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:10:13
+   |
+LL |     let _ = &5.0f32 as *const f32 as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f32>(&5.0f32)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:12:13
+   |
+LL |     let _ = &mut 6u8 as *const _;
+   |             ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut 6u8)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:13:13
+   |
+LL |     let _ = &mut 7u32 as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u32>(&mut 7u32)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:14:13
+   |
+LL |     let _ = &mut 8.0f64 as *const f64;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f64>(&mut 8.0f64)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:16:13
+   |
+LL |     let _ = &mut 9 as *const _ as *const f32;
+   |             ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut 9)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:17:13
+   |
+LL |     let _ = &mut 10.0f32 as *const f32 as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f32>(&mut 10.0f32)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:19:13
+   |
+LL |     let _ = &mut 11u8 as *mut _;
+   |             ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut 11u8)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:20:13
+   |
+LL |     let _ = &mut 12u32 as *mut u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<u32>(&mut 12u32)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:21:13
+   |
+LL |     let _ = &mut 13.0f64 as *mut f64;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<f64>(&mut 13.0f64)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:23:13
+   |
+LL |     let _ = &mut 14 as *mut _ as *const f32;
+   |             ^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut 14)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:24:13
+   |
+LL |     let _ = &mut 15.0f32 as *mut f32 as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<f32>(&mut 15.0f32)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:26:13
+   |
+LL |     let _ = &1u8 as *const _;
+   |             ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&1u8)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:27:13
+   |
+LL |     let _ = &2u32 as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u32>(&2u32)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:28:13
+   |
+LL |     let _ = &3.0f64 as *const f64;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f64>(&3.0f64)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:30:13
+   |
+LL |     let _ = &4 as *const _ as *const f32;
+   |             ^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&4)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:31:13
+   |
+LL |     let _ = &5.0f32 as *const f32 as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f32>(&5.0f32)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:34:13
+   |
+LL |     let _ = &val as *const _;
+   |             ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:35:13
+   |
+LL |     let _ = &val as *const i32;
+   |             ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<i32>(&val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:37:13
+   |
+LL |     let _ = &val as *const _ as *const f32;
+   |             ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:38:13
+   |
+LL |     let _ = &val as *const i32 as *const f64;
+   |             ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<i32>(&val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:41:13
+   |
+LL |     let _ = &mut val as *mut u8;
+   |             ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<u8>(&mut val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:42:13
+   |
+LL |     let _ = &mut val as *mut _;
+   |             ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:44:13
+   |
+LL |     let _ = &mut val as *const u8;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u8>(&mut val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:45:13
+   |
+LL |     let _ = &mut val as *const _;
+   |             ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:47:13
+   |
+LL |     let _ = &mut val as *const u8 as *const f64;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u8>(&mut val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:48:32
+   |
+LL |     let _: *const Option<u8> = &mut val as *const _ as *const _;
+   |                                ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:50:13
+   |
+LL |     let _ = &std::array::from_fn(|i| i * i) as *const [usize; 7];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[usize; 7]>(&std::array::from_fn(|i| i * i))`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:51:13
+   |
+LL |     let _ = &mut std::array::from_fn(|i| i * i) as *const [usize; 8];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[usize; 8]>(&mut std::array::from_fn(|i| i * i))`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:52:13
+   |
+LL |     let _ = &mut std::array::from_fn(|i| i * i) as *mut [usize; 9];
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<[usize; 9]>(&mut std::array::from_fn(|i| i * i))`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:70:13
+   |
+LL |     let _ = val as *const i32;
+   |             ^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<i32>(val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:71:13
+   |
+LL |     let _ = mut_val as *mut i32;
+   |             ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<i32>(mut_val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:75:13
+   |
+LL |     let _ = val as *const _;
+   |             ^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:76:13
+   |
+LL |     let _ = val as *const [u8];
+   |             ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[u8]>(val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:80:13
+   |
+LL |     let _ = val as *mut _;
+   |             ^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:81:13
+   |
+LL |     let _ = val as *mut str;
+   |             ^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<str>(val)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:88:9
+   |
+LL |         self.0 as *const _ as *const _
+   |         ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:92:9
+   |
+LL |         self.0 as *const _ as *const _
+   |         ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:100:9
+   |
+LL |         self.0 as *const _ as *const _
+   |         ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:104:9
+   |
+LL |         self.0 as *const _ as *const _
+   |         ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)`
+
+error: reference as raw pointer
+  --> $DIR/ref_as_ptr.rs:108:9
+   |
+LL |         self.0 as *mut _ as *mut _
+   |         ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(self.0)`
+
+error: aborting due to 44 previous errors
+