about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/autorefs.rs29
-rw-r--r--compiler/rustc_lint/src/lints.rs32
-rw-r--r--tests/ui/lint/implicit_autorefs.stderr28
4 files changed, 49 insertions, 42 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index baa017f3084..08180bf8f8b 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -364,7 +364,7 @@ lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dere
     .note = creating a reference requires the pointer target to be valid and imposes aliasing requirements
     .raw_ptr = this raw pointer has type `{$raw_ptr_ty}`
     .autoref = autoref is being applied to this expression, resulting in: `{$autoref_ty}`
-    .through_overloaded_deref = reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
+    .overloaded_deref = references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
     .method_def = method calls to `{$method_name}` require a reference
     .suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit
 
diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs
index 9bb23526362..5de2cbf9939 100644
--- a/compiler/rustc_lint/src/autorefs.rs
+++ b/compiler/rustc_lint/src/autorefs.rs
@@ -2,9 +2,12 @@ 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::{kw, sym};
+use rustc_span::sym;
 
-use crate::lints::{ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsSuggestion};
+use crate::lints::{
+    ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsMethodNote, ImplicitUnsafeAutorefsOrigin,
+    ImplicitUnsafeAutorefsSuggestion,
+};
 use crate::{LateContext, LateLintPass, LintContext};
 
 declare_lint! {
@@ -98,8 +101,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
                 peel_place_mappers(inner).kind
             // 1. Deref of a raw pointer.
             && typeck.expr_ty(dereferenced).is_raw_ptr()
-            // PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
             && let method_did = match expr.kind {
+                // PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
                 ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
                 _ => None,
             }
@@ -111,11 +114,18 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
                 ImplicitUnsafeAutorefsDiag {
                     raw_ptr_span: dereferenced.span,
                     raw_ptr_ty: typeck.expr_ty(dereferenced),
-                    autoref_span: inner.span,
-                    autoref_ty: typeck.expr_ty_adjusted(inner),
-                    method_def_span: method_did.map(|did| cx.tcx.def_span(did)),
-                    method_name: method_did.map(|did| cx.tcx.item_name(did)).unwrap_or(kw::Empty),
-                    through_overloaded_deref,
+                    origin: if through_overloaded_deref {
+                        ImplicitUnsafeAutorefsOrigin::OverloadedDeref
+                    } else {
+                        ImplicitUnsafeAutorefsOrigin::Autoref {
+                            autoref_span: inner.span,
+                            autoref_ty: typeck.expr_ty_adjusted(inner),
+                        }
+                    },
+                    method: method_did.map(|did| ImplicitUnsafeAutorefsMethodNote {
+                        def_span: cx.tcx.def_span(did),
+                        method_name: cx.tcx.item_name(did),
+                    }),
                     suggestion: ImplicitUnsafeAutorefsSuggestion {
                         mutbl: borrow_mutbl.ref_prefix_str(),
                         deref: if is_coming_from_deref { "*" } else { "" },
@@ -151,7 +161,8 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen
 
 /// Test if some adjustment has some implicit borrow.
 ///
-/// Returns `Some(mutability)` if the argument adjustment has implicit borrow in it.
+/// Returns `Some((mutability, was_an_overloaded_deref))` if the argument adjustment is
+/// an implicit borrow (or has an implicit borrow via an overloaded deref).
 fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Mutability, bool)> {
     match kind {
         &Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some((mutbl, true)),
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 978bb6d08d5..7268a7f704f 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -63,19 +63,35 @@ pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> {
     #[label(lint_raw_ptr)]
     pub raw_ptr_span: Span,
     pub raw_ptr_ty: Ty<'a>,
-    #[note(lint_autoref)]
-    pub autoref_span: Span,
-    pub autoref_ty: Ty<'a>,
-    #[note(lint_method_def)]
-    pub method_def_span: Option<Span>,
-    pub method_name: Symbol,
-    #[note(lint_through_overloaded_deref)]
-    pub through_overloaded_deref: bool,
+    #[subdiagnostic]
+    pub origin: ImplicitUnsafeAutorefsOrigin<'a>,
+    #[subdiagnostic]
+    pub method: Option<ImplicitUnsafeAutorefsMethodNote>,
     #[subdiagnostic]
     pub suggestion: ImplicitUnsafeAutorefsSuggestion,
 }
 
 #[derive(Subdiagnostic)]
+pub(crate) enum ImplicitUnsafeAutorefsOrigin<'a> {
+    #[note(lint_autoref)]
+    Autoref {
+        #[primary_span]
+        autoref_span: Span,
+        autoref_ty: Ty<'a>,
+    },
+    #[note(lint_overloaded_deref)]
+    OverloadedDeref,
+}
+
+#[derive(Subdiagnostic)]
+#[note(lint_method_def)]
+pub(crate) struct ImplicitUnsafeAutorefsMethodNote {
+    #[primary_span]
+    pub def_span: Span,
+    pub method_name: Symbol,
+}
+
+#[derive(Subdiagnostic)]
 #[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
 pub(crate) struct ImplicitUnsafeAutorefsSuggestion {
     pub mutbl: &'static str,
diff --git a/tests/ui/lint/implicit_autorefs.stderr b/tests/ui/lint/implicit_autorefs.stderr
index 29279a268eb..80ba8ae2fd2 100644
--- a/tests/ui/lint/implicit_autorefs.stderr
+++ b/tests/ui/lint/implicit_autorefs.stderr
@@ -128,12 +128,7 @@ LL |     let _ = (*ptr).field;
    |               this raw pointer has type `*const ManuallyDrop<Test>`
    |
    = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
-note: autoref is being applied to this expression, resulting in: `Test`
-  --> $DIR/implicit_autorefs.rs:36:13
-   |
-LL |     let _ = (*ptr).field;
-   |             ^^^^^^
-   = note: reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
+   = note: references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
 help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
    |
 LL |     let _ = (&(*ptr)).field;
@@ -148,12 +143,7 @@ LL |     let _ = &raw const (*ptr).field;
    |                          this raw pointer has type `*const ManuallyDrop<Test>`
    |
    = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
-note: autoref is being applied to this expression, resulting in: `Test`
-  --> $DIR/implicit_autorefs.rs:38:24
-   |
-LL |     let _ = &raw const (*ptr).field;
-   |                        ^^^^^^
-   = note: reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
+   = note: references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
 help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
    |
 LL |     let _ = &raw const (&(*ptr)).field;
@@ -168,12 +158,7 @@ LL |     let _ = (*ptr).field;
    |               this raw pointer has type `*mut ManuallyDrop<Test>`
    |
    = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
-note: autoref is being applied to this expression, resulting in: `Test`
-  --> $DIR/implicit_autorefs.rs:43:13
-   |
-LL |     let _ = (*ptr).field;
-   |             ^^^^^^
-   = note: reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
+   = note: references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
 help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
    |
 LL |     let _ = (&(*ptr)).field;
@@ -188,12 +173,7 @@ LL |     let _ = (*ptr).field;
    |               this raw pointer has type `*const ManuallyDrop<ManuallyDrop<Test>>`
    |
    = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
-note: autoref is being applied to this expression, resulting in: `Test`
-  --> $DIR/implicit_autorefs.rs:48:13
-   |
-LL |     let _ = (*ptr).field;
-   |             ^^^^^^
-   = note: reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
+   = note: references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
 help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
    |
 LL |     let _ = (&(*ptr)).field;