about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/autorefs.rs153
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs20
-rw-r--r--library/alloc/src/vec/mod.rs2
-rw-r--r--tests/ui/lint/implicit_autorefs.fixed99
-rw-r--r--tests/ui/lint/implicit_autorefs.rs99
-rw-r--r--tests/ui/lint/implicit_autorefs.stderr219
8 files changed, 598 insertions, 1 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 60c183bd56b..a6499b07fe2 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -360,6 +360,10 @@ lint_impl_trait_overcaptures = `{$self_ty}` will capture more lifetimes than pos
 lint_impl_trait_redundant_captures = all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
     .suggestion = remove the `use<...>` syntax
 
+lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dereference of a raw pointer
+    .note = creating a reference requires the pointer target to be valid and imposes aliasing requirements
+    .suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit
+
 lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
     .label = not FFI-safe
     .note = the type is defined here
diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs
new file mode 100644
index 00000000000..5dd26854c95
--- /dev/null
+++ b/compiler/rustc_lint/src/autorefs.rs
@@ -0,0 +1,153 @@
+use rustc_ast::{BorrowKind, UnOp};
+use rustc_hir::{Expr, ExprKind, Mutability};
+use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDeref};
+use rustc_session::{declare_lint, declare_lint_pass};
+use rustc_span::sym;
+
+use crate::lints::{ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsSuggestion};
+use crate::{LateContext, LateLintPass, LintContext};
+
+declare_lint! {
+    /// The `dangerous_implicit_autorefs` lint checks for implicitly taken references
+    /// to dereferences of raw pointers.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] {
+    ///     &raw mut (*ptr)[..16]
+    ///     //             ^^^^^^ this calls `IndexMut::index_mut(&mut ..., ..16)`,
+    ///     //                    implicitly creating a reference
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// When working with raw pointers it's usually undesirable to create references,
+    /// since they inflict additional safety requirements. Unfortunately, it's possible
+    /// to take a reference to the dereference of a raw pointer implicitly, which inflicts
+    /// the usual reference requirements.
+    ///
+    /// If you are sure that you can soundly take a reference, then you can take it explicitly:
+    ///
+    /// ```rust
+    /// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] {
+    ///     &raw mut (&mut *ptr)[..16]
+    /// }
+    /// ```
+    ///
+    /// Otherwise try to find an alternative way to achive your goals using only raw pointers:
+    ///
+    /// ```rust
+    /// use std::slice;
+    ///
+    /// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] {
+    ///     slice::from_raw_parts_mut(ptr.cast(), 16)
+    /// }
+    /// ```
+    pub DANGEROUS_IMPLICIT_AUTOREFS,
+    Warn,
+    "implicit reference to a dereference of a raw pointer",
+    report_in_external_macro
+}
+
+declare_lint_pass!(ImplicitAutorefs => [DANGEROUS_IMPLICIT_AUTOREFS]);
+
+impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        // This logic has mostly been taken from
+        // <https://github.com/rust-lang/rust/pull/103735#issuecomment-1370420305>
+
+        // 5. Either of the following:
+        //   a. A deref followed by any non-deref place projection (that intermediate
+        //      deref will typically be auto-inserted).
+        //   b. A method call annotated with `#[rustc_no_implicit_refs]`.
+        //   c. A deref followed by a `&raw const` or `&raw mut`.
+        let mut is_coming_from_deref = false;
+        let inner = match expr.kind {
+            ExprKind::AddrOf(BorrowKind::Raw, _, inner) => match inner.kind {
+                ExprKind::Unary(UnOp::Deref, inner) => {
+                    is_coming_from_deref = true;
+                    inner
+                }
+                _ => return,
+            },
+            ExprKind::Index(base, _, _) => base,
+            ExprKind::MethodCall(_, inner, _, _)
+                if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+                    && cx.tcx.has_attr(def_id, sym::rustc_no_implicit_autorefs) =>
+            {
+                inner
+            }
+            ExprKind::Field(inner, _) => inner,
+            _ => return,
+        };
+
+        let typeck = cx.typeck_results();
+        let adjustments_table = typeck.adjustments();
+
+        if let Some(adjustments) = adjustments_table.get(inner.hir_id)
+            // 4. Any number of automatically inserted deref/derefmut calls.
+            && let adjustments = peel_derefs_adjustments(&**adjustments)
+            // 3. An automatically inserted reference (might come from a deref).
+            && let [adjustment] = adjustments
+            && let Some(borrow_mutbl) = has_implicit_borrow(adjustment)
+            && let ExprKind::Unary(UnOp::Deref, dereferenced) =
+                // 2. Any number of place projections.
+                peel_place_mappers(inner).kind
+            // 1. Deref of a raw pointer.
+            && typeck.expr_ty(dereferenced).is_raw_ptr()
+        {
+            cx.emit_span_lint(
+                DANGEROUS_IMPLICIT_AUTOREFS,
+                expr.span.source_callsite(),
+                ImplicitUnsafeAutorefsDiag {
+                    suggestion: ImplicitUnsafeAutorefsSuggestion {
+                        mutbl: borrow_mutbl.ref_prefix_str(),
+                        deref: if is_coming_from_deref { "*" } else { "" },
+                        start_span: inner.span.shrink_to_lo(),
+                        end_span: inner.span.shrink_to_hi(),
+                    },
+                },
+            )
+        }
+    }
+}
+
+/// Peels expressions from `expr` that can map a place.
+fn peel_place_mappers<'tcx>(mut expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
+    loop {
+        match expr.kind {
+            ExprKind::Index(base, _idx, _) => expr = &base,
+            ExprKind::Field(e, _) => expr = &e,
+            _ => break expr,
+        }
+    }
+}
+
+/// Peel derefs adjustments until the last last element.
+fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustment<'a>] {
+    while let [Adjustment { kind: Adjust::Deref(_), .. }, end @ ..] = adjs
+        && !end.is_empty()
+    {
+        adjs = end;
+    }
+    adjs
+}
+
+/// Test if some adjustment has some implicit borrow.
+///
+/// Returns `Some(mutability)` if the argument adjustment has implicit borrow in it.
+fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<Mutability> {
+    match kind {
+        &Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some(mutbl),
+        &Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some(mutbl.into()),
+        Adjust::NeverToAny
+        | Adjust::Pointer(..)
+        | Adjust::ReborrowPin(..)
+        | Adjust::Deref(None)
+        | Adjust::Borrow(AutoBorrow::RawPtr(..)) => None,
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 212368bea82..79c984cb634 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -36,6 +36,7 @@
 
 mod async_closures;
 mod async_fn_in_trait;
+mod autorefs;
 pub mod builtin;
 mod context;
 mod dangling;
@@ -83,6 +84,7 @@ mod utils;
 
 use async_closures::AsyncClosureUsage;
 use async_fn_in_trait::AsyncFnInTrait;
+use autorefs::*;
 use builtin::*;
 use dangling::*;
 use default_could_be_derived::DefaultCouldBeDerived;
@@ -200,6 +202,7 @@ late_lint_methods!(
             PathStatements: PathStatements,
             LetUnderscore: LetUnderscore,
             InvalidReferenceCasting: InvalidReferenceCasting,
+            ImplicitAutorefs: ImplicitAutorefs,
             // Depends on referenced function signatures in expressions
             UnusedResults: UnusedResults,
             UnitBindings: UnitBindings,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 8ab64fbd127..487184b836a 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -55,6 +55,26 @@ pub(crate) enum ShadowedIntoIterDiagSub {
     },
 }
 
+// autorefs.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_implicit_unsafe_autorefs)]
+#[note]
+pub(crate) struct ImplicitUnsafeAutorefsDiag {
+    #[subdiagnostic]
+    pub suggestion: ImplicitUnsafeAutorefsSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
+pub(crate) struct ImplicitUnsafeAutorefsSuggestion {
+    pub mutbl: &'static str,
+    pub deref: &'static str,
+    #[suggestion_part(code = "({mutbl}{deref}")]
+    pub start_span: Span,
+    #[suggestion_part(code = ")")]
+    pub end_span: Span,
+}
+
 // builtin.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_builtin_while_true)]
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 68e4add30e5..65a83cb98ba 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2588,7 +2588,7 @@ impl<T, A: Allocator> Vec<T, A> {
     #[inline]
     #[track_caller]
     unsafe fn append_elements(&mut self, other: *const [T]) {
-        let count = unsafe { (*other).len() };
+        let count = other.len();
         self.reserve(count);
         let len = self.len();
         unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) };
diff --git a/tests/ui/lint/implicit_autorefs.fixed b/tests/ui/lint/implicit_autorefs.fixed
new file mode 100644
index 00000000000..96a617b20c9
--- /dev/null
+++ b/tests/ui/lint/implicit_autorefs.fixed
@@ -0,0 +1,99 @@
+//@ check-pass
+//@ run-rustfix
+
+#![allow(dead_code)] // For the rustfix-ed code.
+
+use std::mem::ManuallyDrop;
+use std::ops::Deref;
+
+unsafe fn test_const(ptr: *const [u8]) {
+    let _ = (&(*ptr))[..16];
+    //~^ WARN implicit autoref
+}
+
+struct Test {
+    field: [u8],
+}
+
+unsafe fn test_field(ptr: *const Test) -> *const [u8] {
+    let l = (&(*ptr).field).len();
+    //~^ WARN implicit autoref
+
+    &raw const (&(*ptr).field)[..l - 1]
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_builtin_index(a: *mut [String]) {
+    _ = (&(*a)[0]).len();
+    //~^ WARN implicit autoref
+
+    _ = (&(&(*a))[..1][0]).len();
+    //~^ WARN implicit autoref
+    //~^^ WARN implicit autoref
+}
+
+unsafe fn test_overloaded_deref_const(ptr: *const ManuallyDrop<Test>) {
+    let _ = (&(*ptr)).field;
+    //~^ WARN implicit autoref
+    let _ = &raw const (&(*ptr)).field;
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_overloaded_deref_mut(ptr: *mut ManuallyDrop<Test>) {
+    let _ = (&(*ptr)).field;
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_double_overloaded_deref_const(ptr: *const ManuallyDrop<ManuallyDrop<Test>>) {
+    let _ = (&(*ptr)).field;
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_manually_overloaded_deref() {
+    struct W<T>(T);
+
+    impl<T> Deref for W<T> {
+        type Target = T;
+        fn deref(&self) -> &T { &self.0 }
+    }
+
+    let w: W<i32> = W(5);
+    let w = &raw const w;
+    let _p: *const i32 = &raw const *(&**w);
+    //~^ WARN implicit autoref
+}
+
+struct Test2 {
+    // Derefs to `[u8]`.
+    field: &'static [u8]
+}
+
+fn test_more_manual_deref(ptr: *const Test2) -> usize {
+    unsafe { (&(*ptr).field).len() }
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_no_attr(ptr: *mut ManuallyDrop<u8>) {
+    ptr.write(ManuallyDrop::new(1)); // Should not warn, as `ManuallyDrop::write` is not
+                                     // annotated with `#[rustc_no_implicit_auto_ref]`
+}
+
+unsafe fn test_vec_get(ptr: *mut Vec<u8>) {
+    let _ = (&(*ptr)).get(0);
+    //~^ WARN implicit autoref
+    let _ = (&(*ptr)).get_unchecked(0);
+    //~^ WARN implicit autoref
+    let _ = (&mut (*ptr)).get_mut(0);
+    //~^ WARN implicit autoref
+    let _ = (&mut (*ptr)).get_unchecked_mut(0);
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_string(ptr: *mut String) {
+    let _ = (&(*ptr)).len();
+    //~^ WARN implicit autoref
+    let _ = (&(*ptr)).is_empty();
+    //~^ WARN implicit autoref
+}
+
+fn main() {}
diff --git a/tests/ui/lint/implicit_autorefs.rs b/tests/ui/lint/implicit_autorefs.rs
new file mode 100644
index 00000000000..61dd0ac50ce
--- /dev/null
+++ b/tests/ui/lint/implicit_autorefs.rs
@@ -0,0 +1,99 @@
+//@ check-pass
+//@ run-rustfix
+
+#![allow(dead_code)] // For the rustfix-ed code.
+
+use std::mem::ManuallyDrop;
+use std::ops::Deref;
+
+unsafe fn test_const(ptr: *const [u8]) {
+    let _ = (*ptr)[..16];
+    //~^ WARN implicit autoref
+}
+
+struct Test {
+    field: [u8],
+}
+
+unsafe fn test_field(ptr: *const Test) -> *const [u8] {
+    let l = (*ptr).field.len();
+    //~^ WARN implicit autoref
+
+    &raw const (*ptr).field[..l - 1]
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_builtin_index(a: *mut [String]) {
+    _ = (*a)[0].len();
+    //~^ WARN implicit autoref
+
+    _ = (*a)[..1][0].len();
+    //~^ WARN implicit autoref
+    //~^^ WARN implicit autoref
+}
+
+unsafe fn test_overloaded_deref_const(ptr: *const ManuallyDrop<Test>) {
+    let _ = (*ptr).field;
+    //~^ WARN implicit autoref
+    let _ = &raw const (*ptr).field;
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_overloaded_deref_mut(ptr: *mut ManuallyDrop<Test>) {
+    let _ = (*ptr).field;
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_double_overloaded_deref_const(ptr: *const ManuallyDrop<ManuallyDrop<Test>>) {
+    let _ = (*ptr).field;
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_manually_overloaded_deref() {
+    struct W<T>(T);
+
+    impl<T> Deref for W<T> {
+        type Target = T;
+        fn deref(&self) -> &T { &self.0 }
+    }
+
+    let w: W<i32> = W(5);
+    let w = &raw const w;
+    let _p: *const i32 = &raw const **w;
+    //~^ WARN implicit autoref
+}
+
+struct Test2 {
+    // Derefs to `[u8]`.
+    field: &'static [u8]
+}
+
+fn test_more_manual_deref(ptr: *const Test2) -> usize {
+    unsafe { (*ptr).field.len() }
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_no_attr(ptr: *mut ManuallyDrop<u8>) {
+    ptr.write(ManuallyDrop::new(1)); // Should not warn, as `ManuallyDrop::write` is not
+                                     // annotated with `#[rustc_no_implicit_auto_ref]`
+}
+
+unsafe fn test_vec_get(ptr: *mut Vec<u8>) {
+    let _ = (*ptr).get(0);
+    //~^ WARN implicit autoref
+    let _ = (*ptr).get_unchecked(0);
+    //~^ WARN implicit autoref
+    let _ = (*ptr).get_mut(0);
+    //~^ WARN implicit autoref
+    let _ = (*ptr).get_unchecked_mut(0);
+    //~^ WARN implicit autoref
+}
+
+unsafe fn test_string(ptr: *mut String) {
+    let _ = (*ptr).len();
+    //~^ WARN implicit autoref
+    let _ = (*ptr).is_empty();
+    //~^ WARN implicit autoref
+}
+
+fn main() {}
diff --git a/tests/ui/lint/implicit_autorefs.stderr b/tests/ui/lint/implicit_autorefs.stderr
new file mode 100644
index 00000000000..6dd1ac65ada
--- /dev/null
+++ b/tests/ui/lint/implicit_autorefs.stderr
@@ -0,0 +1,219 @@
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:10:13
+   |
+LL |     let _ = (*ptr)[..16];
+   |             ^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+   = note: `#[warn(dangerous_implicit_autorefs)]` on by default
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&(*ptr))[..16];
+   |             ++      +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:19:13
+   |
+LL |     let l = (*ptr).field.len();
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let l = (&(*ptr).field).len();
+   |             ++            +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:22:16
+   |
+LL |     &raw const (*ptr).field[..l - 1]
+   |                ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     &raw const (&(*ptr).field)[..l - 1]
+   |                ++            +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:27:9
+   |
+LL |     _ = (*a)[0].len();
+   |         ^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     _ = (&(*a)[0]).len();
+   |         ++       +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:30:9
+   |
+LL |     _ = (*a)[..1][0].len();
+   |         ^^^^^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     _ = (&(*a)[..1][0]).len();
+   |         ++            +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:30:9
+   |
+LL |     _ = (*a)[..1][0].len();
+   |         ^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     _ = (&(*a))[..1][0].len();
+   |         ++    +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:36:13
+   |
+LL |     let _ = (*ptr).field;
+   |             ^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&(*ptr)).field;
+   |             ++      +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:38:24
+   |
+LL |     let _ = &raw const (*ptr).field;
+   |                        ^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = &raw const (&(*ptr)).field;
+   |                        ++      +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:43:13
+   |
+LL |     let _ = (*ptr).field;
+   |             ^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&(*ptr)).field;
+   |             ++      +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:48:13
+   |
+LL |     let _ = (*ptr).field;
+   |             ^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&(*ptr)).field;
+   |             ++      +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:62:26
+   |
+LL |     let _p: *const i32 = &raw const **w;
+   |                          ^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _p: *const i32 = &raw const *(&**w);
+   |                                      +++  +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:72:14
+   |
+LL |     unsafe { (*ptr).field.len() }
+   |              ^^^^^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     unsafe { (&(*ptr).field).len() }
+   |              ++            +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:82:13
+   |
+LL |     let _ = (*ptr).get(0);
+   |             ^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&(*ptr)).get(0);
+   |             ++      +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:84:13
+   |
+LL |     let _ = (*ptr).get_unchecked(0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&(*ptr)).get_unchecked(0);
+   |             ++      +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:86:13
+   |
+LL |     let _ = (*ptr).get_mut(0);
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&mut (*ptr)).get_mut(0);
+   |             +++++       +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:88:13
+   |
+LL |     let _ = (*ptr).get_unchecked_mut(0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&mut (*ptr)).get_unchecked_mut(0);
+   |             +++++       +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:93:13
+   |
+LL |     let _ = (*ptr).len();
+   |             ^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&(*ptr)).len();
+   |             ++      +
+
+warning: implicit autoref creates a reference to the dereference of a raw pointer
+  --> $DIR/implicit_autorefs.rs:95:13
+   |
+LL |     let _ = (*ptr).is_empty();
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
+help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
+   |
+LL |     let _ = (&(*ptr)).is_empty();
+   |             ++      +
+
+warning: 18 warnings emitted
+