Skip to content

Commit 9b3abe7

Browse files
committed
Use more subdiagnostics and reword the overloaded deref note
1 parent ac1df15 commit 9b3abe7

File tree

4 files changed

+49
-42
lines changed

4 files changed

+49
-42
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dere
364364
.note = creating a reference requires the pointer target to be valid and imposes aliasing requirements
365365
.raw_ptr = this raw pointer has type `{$raw_ptr_ty}`
366366
.autoref = autoref is being applied to this expression, resulting in: `{$autoref_ty}`
367-
.through_overloaded_deref = reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
367+
.overloaded_deref = references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
368368
.method_def = method calls to `{$method_name}` require a reference
369369
.suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit
370370

compiler/rustc_lint/src/autorefs.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ use rustc_ast::{BorrowKind, UnOp};
22
use rustc_hir::{Expr, ExprKind, Mutability};
33
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDeref};
44
use rustc_session::{declare_lint, declare_lint_pass};
5-
use rustc_span::{kw, sym};
5+
use rustc_span::sym;
66

7-
use crate::lints::{ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsSuggestion};
7+
use crate::lints::{
8+
ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsMethodNote, ImplicitUnsafeAutorefsOrigin,
9+
ImplicitUnsafeAutorefsSuggestion,
10+
};
811
use crate::{LateContext, LateLintPass, LintContext};
912

1013
declare_lint! {
@@ -98,8 +101,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
98101
peel_place_mappers(inner).kind
99102
// 1. Deref of a raw pointer.
100103
&& typeck.expr_ty(dereferenced).is_raw_ptr()
101-
// PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
102104
&& let method_did = match expr.kind {
105+
// PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
103106
ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
104107
_ => None,
105108
}
@@ -111,11 +114,18 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
111114
ImplicitUnsafeAutorefsDiag {
112115
raw_ptr_span: dereferenced.span,
113116
raw_ptr_ty: typeck.expr_ty(dereferenced),
114-
autoref_span: inner.span,
115-
autoref_ty: typeck.expr_ty_adjusted(inner),
116-
method_def_span: method_did.map(|did| cx.tcx.def_span(did)),
117-
method_name: method_did.map(|did| cx.tcx.item_name(did)).unwrap_or(kw::Empty),
118-
through_overloaded_deref,
117+
origin: if through_overloaded_deref {
118+
ImplicitUnsafeAutorefsOrigin::OverloadedDeref
119+
} else {
120+
ImplicitUnsafeAutorefsOrigin::Autoref {
121+
autoref_span: inner.span,
122+
autoref_ty: typeck.expr_ty_adjusted(inner),
123+
}
124+
},
125+
method: method_did.map(|did| ImplicitUnsafeAutorefsMethodNote {
126+
def_span: cx.tcx.def_span(did),
127+
method_name: cx.tcx.item_name(did),
128+
}),
119129
suggestion: ImplicitUnsafeAutorefsSuggestion {
120130
mutbl: borrow_mutbl.ref_prefix_str(),
121131
deref: if is_coming_from_deref { "*" } else { "" },
@@ -151,7 +161,8 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen
151161

152162
/// Test if some adjustment has some implicit borrow.
153163
///
154-
/// Returns `Some(mutability)` if the argument adjustment has implicit borrow in it.
164+
/// Returns `Some((mutability, was_an_overloaded_deref))` if the argument adjustment is
165+
/// an implicit borrow (or has an implicit borrow via an overloaded deref).
155166
fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Mutability, bool)> {
156167
match kind {
157168
&Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some((mutbl, true)),

compiler/rustc_lint/src/lints.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,34 @@ pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> {
6363
#[label(lint_raw_ptr)]
6464
pub raw_ptr_span: Span,
6565
pub raw_ptr_ty: Ty<'a>,
66-
#[note(lint_autoref)]
67-
pub autoref_span: Span,
68-
pub autoref_ty: Ty<'a>,
69-
#[note(lint_method_def)]
70-
pub method_def_span: Option<Span>,
71-
pub method_name: Symbol,
72-
#[note(lint_through_overloaded_deref)]
73-
pub through_overloaded_deref: bool,
66+
#[subdiagnostic]
67+
pub origin: ImplicitUnsafeAutorefsOrigin<'a>,
68+
#[subdiagnostic]
69+
pub method: Option<ImplicitUnsafeAutorefsMethodNote>,
7470
#[subdiagnostic]
7571
pub suggestion: ImplicitUnsafeAutorefsSuggestion,
7672
}
7773

74+
#[derive(Subdiagnostic)]
75+
pub(crate) enum ImplicitUnsafeAutorefsOrigin<'a> {
76+
#[note(lint_autoref)]
77+
Autoref {
78+
#[primary_span]
79+
autoref_span: Span,
80+
autoref_ty: Ty<'a>,
81+
},
82+
#[note(lint_overloaded_deref)]
83+
OverloadedDeref,
84+
}
85+
86+
#[derive(Subdiagnostic)]
87+
#[note(lint_method_def)]
88+
pub(crate) struct ImplicitUnsafeAutorefsMethodNote {
89+
#[primary_span]
90+
pub def_span: Span,
91+
pub method_name: Symbol,
92+
}
93+
7894
#[derive(Subdiagnostic)]
7995
#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
8096
pub(crate) struct ImplicitUnsafeAutorefsSuggestion {

tests/ui/lint/implicit_autorefs.stderr

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,7 @@ LL | let _ = (*ptr).field;
128128
| this raw pointer has type `*const ManuallyDrop<Test>`
129129
|
130130
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
131-
note: autoref is being applied to this expression, resulting in: `Test`
132-
--> $DIR/implicit_autorefs.rs:36:13
133-
|
134-
LL | let _ = (*ptr).field;
135-
| ^^^^^^
136-
= note: reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
131+
= note: references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
137132
help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
138133
|
139134
LL | let _ = (&(*ptr)).field;
@@ -148,12 +143,7 @@ LL | let _ = &raw const (*ptr).field;
148143
| this raw pointer has type `*const ManuallyDrop<Test>`
149144
|
150145
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
151-
note: autoref is being applied to this expression, resulting in: `Test`
152-
--> $DIR/implicit_autorefs.rs:38:24
153-
|
154-
LL | let _ = &raw const (*ptr).field;
155-
| ^^^^^^
156-
= note: reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
146+
= note: references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
157147
help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
158148
|
159149
LL | let _ = &raw const (&(*ptr)).field;
@@ -168,12 +158,7 @@ LL | let _ = (*ptr).field;
168158
| this raw pointer has type `*mut ManuallyDrop<Test>`
169159
|
170160
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
171-
note: autoref is being applied to this expression, resulting in: `Test`
172-
--> $DIR/implicit_autorefs.rs:43:13
173-
|
174-
LL | let _ = (*ptr).field;
175-
| ^^^^^^
176-
= note: reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
161+
= note: references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
177162
help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
178163
|
179164
LL | let _ = (&(*ptr)).field;
@@ -188,12 +173,7 @@ LL | let _ = (*ptr).field;
188173
| this raw pointer has type `*const ManuallyDrop<ManuallyDrop<Test>>`
189174
|
190175
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
191-
note: autoref is being applied to this expression, resulting in: `Test`
192-
--> $DIR/implicit_autorefs.rs:48:13
193-
|
194-
LL | let _ = (*ptr).field;
195-
| ^^^^^^
196-
= note: reference(s) created through call(s) to overloaded `Deref(Mut)::deref(_mut)` implementation
176+
= note: references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
197177
help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
198178
|
199179
LL | let _ = (&(*ptr)).field;

0 commit comments

Comments
 (0)