Skip to content

Commit d297ee4

Browse files
committed
Add unnecessary_refs lint
1 parent cdd8af2 commit d297ee4

File tree

6 files changed

+77
-0
lines changed

6 files changed

+77
-0
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3917,6 +3917,7 @@ dependencies = [
39173917
"rustc_feature",
39183918
"rustc_fluent_macro",
39193919
"rustc_hir",
3920+
"rustc_hir_pretty",
39203921
"rustc_index",
39213922
"rustc_infer",
39223923
"rustc_macros",

compiler/rustc_lint/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ rustc_errors = { path = "../rustc_errors" }
1414
rustc_feature = { path = "../rustc_feature" }
1515
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
1616
rustc_hir = { path = "../rustc_hir" }
17+
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
1718
rustc_index = { path = "../rustc_index" }
1819
rustc_infer = { path = "../rustc_infer" }
1920
rustc_macros = { path = "../rustc_macros" }

compiler/rustc_lint/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,9 @@ lint_unnameable_test_items = cannot test inner items
894894
lint_unnecessary_qualification = unnecessary qualification
895895
.suggestion = remove the unnecessary path segments
896896
897+
lint_unnecessary_refs_lint = creating unecessary reference is discouraged
898+
.suggestion = consider using `&raw const` for a safer and more explicit raw pointer
899+
897900
lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
898901
.note_duplicated_fn = the address of the same function can vary between different codegen units
899902
.note_deduplicated_fn = furthermore, different functions could have the same address after being merged together

compiler/rustc_lint/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ mod static_mut_refs;
7878
mod traits;
7979
mod types;
8080
mod unit_bindings;
81+
mod unnecessary_refs;
8182
mod unqualified_local_imports;
8283
mod unused;
8384

@@ -119,6 +120,7 @@ use static_mut_refs::*;
119120
use traits::*;
120121
use types::*;
121122
use unit_bindings::*;
123+
use unnecessary_refs::*;
122124
use unqualified_local_imports::*;
123125
use unused::*;
124126

@@ -244,6 +246,7 @@ late_lint_methods!(
244246
IfLetRescope: IfLetRescope::default(),
245247
StaticMutRefs: StaticMutRefs,
246248
UnqualifiedLocalImports: UnqualifiedLocalImports,
249+
UnecessaryRefs: UnecessaryRefs,
247250
]
248251
]
249252
);

compiler/rustc_lint/src/lints.rs

+8
Original file line numberDiff line numberDiff line change
@@ -3163,3 +3163,11 @@ pub(crate) struct ReservedMultihash {
31633163
#[suggestion(code = " ", applicability = "machine-applicable")]
31643164
pub suggestion: Span,
31653165
}
3166+
3167+
#[derive(LintDiagnostic)]
3168+
#[diag(lint_unnecessary_refs_lint)]
3169+
pub(crate) struct UnnecessaryRefs {
3170+
#[suggestion(code = "{replace}", applicability = "machine-applicable")]
3171+
pub span: Span,
3172+
pub replace: String,
3173+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use rustc_ast::{BorrowKind, UnOp};
2+
use rustc_hir::{Expr, ExprKind, TyKind};
3+
use rustc_session::{declare_lint, declare_lint_pass};
4+
5+
use crate::lints::UnnecessaryRefs;
6+
use crate::{LateContext, LateLintPass, LintContext};
7+
8+
declare_lint! {
9+
/// The `unnecessary_refs` lint checks for unnecessary references.
10+
///
11+
/// ### Example
12+
///
13+
/// ```rust
14+
/// fn via_ref(x: *const (i32, i32)) -> *const i32 {
15+
/// unsafe { &(*x).0 as *const i32 }
16+
/// }
17+
///
18+
/// fn main() {
19+
/// let x = 0;
20+
/// let _r = via_ref(&x);
21+
/// }
22+
/// ```
23+
///
24+
/// {{produces}}
25+
///
26+
/// ### Explanation
27+
///
28+
/// Creating unnecessary references is almost always a mistake.
29+
pub UNNECESSARY_REFS,
30+
Warn,
31+
"creating unecessary reference is discouraged"
32+
}
33+
34+
declare_lint_pass!(UnecessaryRefs => [UNNECESSARY_REFS]);
35+
36+
impl<'tcx> LateLintPass<'tcx> for UnecessaryRefs {
37+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
38+
if let ExprKind::Cast(exp, ty) = expr.kind
39+
&& let ExprKind::AddrOf(bk, _, exp) = exp.kind
40+
&& matches!(bk, BorrowKind::Ref)
41+
&& let ExprKind::Field(exp, field) = exp.kind
42+
&& let ExprKind::Unary(uo, exp) = exp.kind
43+
&& matches!(uo, UnOp::Deref)
44+
&& let TyKind::Ptr(_) = ty.kind
45+
&& let ExprKind::Path(qpath) = exp.kind
46+
{
47+
cx.emit_span_lint(
48+
UNNECESSARY_REFS,
49+
expr.span,
50+
UnnecessaryRefs {
51+
span: expr.span,
52+
replace: format!(
53+
"&raw const (*{}).{}",
54+
rustc_hir_pretty::qpath_to_string(&cx.tcx, &qpath),
55+
field
56+
),
57+
},
58+
);
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)