Skip to content

Commit d23a82e

Browse files
Rollup merge of rust-lang#140768 - Urgau:improv_autorefs-lint, r=fmease
Improve `dangerous_implicit_aurorefs` diagnostic output This PR *greatly* improves the `dangerous_implicit_aurorefs` lint diagnostic output. Kind of related to rust-lang#140721. r? ``@jieyouxu`` (maybe)
2 parents 53fa4d7 + 9b3abe7 commit d23a82e

File tree

6 files changed

+262
-33
lines changed

6 files changed

+262
-33
lines changed

compiler/rustc_lint/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,10 @@ lint_impl_trait_redundant_captures = all possible in-scope parameters are alread
362362
363363
lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dereference of a raw pointer
364364
.note = creating a reference requires the pointer target to be valid and imposes aliasing requirements
365+
.raw_ptr = this raw pointer has type `{$raw_ptr_ty}`
366+
.autoref = autoref is being applied to this expression, resulting in: `{$autoref_ty}`
367+
.overloaded_deref = references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations
368+
.method_def = method calls to `{$method_name}` require a reference
365369
.suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit
366370
367371
lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe

compiler/rustc_lint/src/autorefs.rs

+29-13
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDer
44
use rustc_session::{declare_lint, declare_lint_pass};
55
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! {
@@ -92,25 +95,37 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitAutorefs {
9295
&& let adjustments = peel_derefs_adjustments(&**adjustments)
9396
// 3. An automatically inserted reference (might come from a deref).
9497
&& let [adjustment] = adjustments
95-
&& let Some(borrow_mutbl) = has_implicit_borrow(adjustment)
98+
&& let Some((borrow_mutbl, through_overloaded_deref)) = has_implicit_borrow(adjustment)
9699
&& let ExprKind::Unary(UnOp::Deref, dereferenced) =
97100
// 2. Any number of place projections.
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]`
102-
&& match expr.kind {
103-
ExprKind::MethodCall(..) => matches!(
104-
cx.typeck_results().type_dependent_def_id(expr.hir_id),
105-
Some(def_id) if cx.tcx.has_attr(def_id, sym::rustc_no_implicit_autorefs)
106-
),
107-
_ => true,
104+
&& let method_did = match expr.kind {
105+
// PERF: 5. b. A method call annotated with `#[rustc_no_implicit_refs]`
106+
ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
107+
_ => None,
108108
}
109+
&& method_did.map(|did| cx.tcx.has_attr(did, sym::rustc_no_implicit_autorefs)).unwrap_or(true)
109110
{
110111
cx.emit_span_lint(
111112
DANGEROUS_IMPLICIT_AUTOREFS,
112113
expr.span.source_callsite(),
113114
ImplicitUnsafeAutorefsDiag {
115+
raw_ptr_span: dereferenced.span,
116+
raw_ptr_ty: typeck.expr_ty(dereferenced),
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+
}),
114129
suggestion: ImplicitUnsafeAutorefsSuggestion {
115130
mutbl: borrow_mutbl.ref_prefix_str(),
116131
deref: if is_coming_from_deref { "*" } else { "" },
@@ -146,11 +161,12 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen
146161

147162
/// Test if some adjustment has some implicit borrow.
148163
///
149-
/// Returns `Some(mutability)` if the argument adjustment has implicit borrow in it.
150-
fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<Mutability> {
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).
166+
fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Mutability, bool)> {
151167
match kind {
152-
&Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some(mutbl),
153-
&Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some(mutbl.into()),
168+
&Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some((mutbl, true)),
169+
&Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some((mutbl.into(), false)),
154170
Adjust::NeverToAny
155171
| Adjust::Pointer(..)
156172
| Adjust::ReborrowPin(..)

compiler/rustc_lint/src/lints.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,38 @@ pub(crate) enum ShadowedIntoIterDiagSub {
5959
#[derive(LintDiagnostic)]
6060
#[diag(lint_implicit_unsafe_autorefs)]
6161
#[note]
62-
pub(crate) struct ImplicitUnsafeAutorefsDiag {
62+
pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> {
63+
#[label(lint_raw_ptr)]
64+
pub raw_ptr_span: Span,
65+
pub raw_ptr_ty: Ty<'a>,
66+
#[subdiagnostic]
67+
pub origin: ImplicitUnsafeAutorefsOrigin<'a>,
68+
#[subdiagnostic]
69+
pub method: Option<ImplicitUnsafeAutorefsMethodNote>,
6370
#[subdiagnostic]
6471
pub suggestion: ImplicitUnsafeAutorefsSuggestion,
6572
}
6673

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+
6794
#[derive(Subdiagnostic)]
6895
#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
6996
pub(crate) struct ImplicitUnsafeAutorefsSuggestion {

tests/ui/lint/implicit_autorefs.fixed

+6
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,10 @@ unsafe fn test_string(ptr: *mut String) {
9696
//~^ WARN implicit autoref
9797
}
9898

99+
unsafe fn slice_ptr_len_because_of_msrv<T>(slice: *const [T]) {
100+
let _ = (&(&(*slice))[..]).len();
101+
//~^ WARN implicit autoref
102+
//~^^ WARN implicit autoref
103+
}
104+
99105
fn main() {}

tests/ui/lint/implicit_autorefs.rs

+6
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,10 @@ unsafe fn test_string(ptr: *mut String) {
9696
//~^ WARN implicit autoref
9797
}
9898

99+
unsafe fn slice_ptr_len_because_of_msrv<T>(slice: *const [T]) {
100+
let _ = (*slice)[..].len();
101+
//~^ WARN implicit autoref
102+
//~^^ WARN implicit autoref
103+
}
104+
99105
fn main() {}

0 commit comments

Comments
 (0)