Skip to content

Commit eba6c78

Browse files
committed
Show code suggestions in let_undescore lint messages.
This commit uses `span_suggestion_verbose` to add what specific code changes can be done as suggested by the lint--in this case, either binding the expression to an unused variable or using `std::mem::drop` to drop the value explicitly.
1 parent ae2ac3b commit eba6c78

File tree

4 files changed

+79
-21
lines changed

4 files changed

+79
-21
lines changed

compiler/rustc_lint/src/let_underscore.rs

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use crate::{LateContext, LateLintPass, LintContext};
2+
use rustc_errors::Applicability;
23
use rustc_hir as hir;
3-
use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
4+
use rustc_middle::{
5+
lint::LintDiagnosticBuilder,
6+
ty::{self, subst::GenericArgKind, Ty},
7+
};
48
use rustc_span::Symbol;
59

610
declare_lint! {
@@ -141,30 +145,60 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
141145
});
142146
let is_must_use_ty = is_must_use_ty(cx, cx.typeck_results().expr_ty(init));
143147
let is_must_use_func_call = is_must_use_func_call(cx, init);
148+
144149
if is_sync_lock {
145150
cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| {
146-
lint.build("non-binding let on a synchronization lock")
147-
.help("consider binding to an unused variable")
148-
.help("consider explicitly droping with `std::mem::drop`")
149-
.emit();
151+
build_and_emit_lint(
152+
lint,
153+
local,
154+
init.span,
155+
"non-binding let on a synchronization lock",
156+
)
150157
})
151158
} else if is_must_use_ty || is_must_use_func_call {
152159
cx.struct_span_lint(LET_UNDERSCORE_MUST_USE, local.span, |lint| {
153-
lint.build("non-binding let on a expression marked `must_use`")
154-
.help("consider binding to an unused variable")
155-
.help("consider explicitly droping with `std::mem::drop`")
156-
.emit();
160+
build_and_emit_lint(
161+
lint,
162+
local,
163+
init.span,
164+
"non-binding let on a expression marked `must_use`",
165+
);
157166
})
158167
} else if needs_drop {
159168
cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
160-
lint.build("non-binding let on a type that implements `Drop`")
161-
.help("consider binding to an unused variable")
162-
.help("consider explicitly droping with `std::mem::drop`")
163-
.emit();
169+
build_and_emit_lint(
170+
lint,
171+
local,
172+
init.span,
173+
"non-binding let on a type that implements `Drop`",
174+
);
164175
})
165176
}
166177
}
167178

179+
fn build_and_emit_lint(
180+
lint: LintDiagnosticBuilder<'_, ()>,
181+
local: &hir::Local<'_>,
182+
init_span: rustc_span::Span,
183+
msg: &str,
184+
) {
185+
lint.build(msg)
186+
.span_suggestion_verbose(
187+
local.pat.span,
188+
"consider binding to an unused variable",
189+
"_unused",
190+
Applicability::MachineApplicable,
191+
)
192+
.span_suggestion_verbose(
193+
init_span,
194+
"consider explicitly droping with `std::mem::drop`",
195+
"drop(...)",
196+
Applicability::HasPlaceholders,
197+
)
198+
.emit();
199+
}
200+
201+
// return true if `ty` is a type that is marked as `must_use`
168202
fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
169203
match ty.kind() {
170204
ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()),

src/test/ui/let_underscore/let_underscore_drop.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ LL | let _ = NontrivialDrop;
55
| ^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: requested on the command line with `-W let-underscore-drop`
8-
= help: consider binding to an unused variable
9-
= help: consider explicitly droping with `std::mem::drop`
8+
help: consider binding to an unused variable
9+
|
10+
LL | let _unused = NontrivialDrop;
11+
| ~~~~~~~
12+
help: consider explicitly droping with `std::mem::drop`
13+
|
14+
LL | let _ = drop(...);
15+
| ~~~~~~~~~
1016

1117
warning: 1 warning emitted
1218

src/test/ui/let_underscore/let_underscore_lock.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ LL | let _ = data.lock().unwrap();
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(let_underscore_lock)]` on by default
8-
= help: consider binding to an unused variable
9-
= help: consider explicitly droping with `std::mem::drop`
8+
help: consider binding to an unused variable
9+
|
10+
LL | let _unused = data.lock().unwrap();
11+
| ~~~~~~~
12+
help: consider explicitly droping with `std::mem::drop`
13+
|
14+
LL | let _ = drop(...);
15+
| ~~~~~~~~~
1016

1117
warning: 1 warning emitted
1218

src/test/ui/let_underscore/let_underscore_must_use.stderr

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,29 @@ LL | let _ = MustUseType;
55
| ^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: requested on the command line with `-W let-underscore-must-use`
8-
= help: consider binding to an unused variable
9-
= help: consider explicitly droping with `std::mem::drop`
8+
help: consider binding to an unused variable
9+
|
10+
LL | let _unused = MustUseType;
11+
| ~~~~~~~
12+
help: consider explicitly droping with `std::mem::drop`
13+
|
14+
LL | let _ = drop(...);
15+
| ~~~~~~~~~
1016

1117
warning: non-binding let on a expression marked `must_use`
1218
--> $DIR/let_underscore_must_use.rs:12:5
1319
|
1420
LL | let _ = must_use_function();
1521
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1622
|
17-
= help: consider binding to an unused variable
18-
= help: consider explicitly droping with `std::mem::drop`
23+
help: consider binding to an unused variable
24+
|
25+
LL | let _unused = must_use_function();
26+
| ~~~~~~~
27+
help: consider explicitly droping with `std::mem::drop`
28+
|
29+
LL | let _ = drop(...);
30+
| ~~~~~~~~~
1931

2032
warning: 2 warnings emitted
2133

0 commit comments

Comments
 (0)