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.
This commit is contained in:
parent
ae2ac3b4c5
commit
eba6c789dc
@ -1,6 +1,10 @@
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
|
||||
use rustc_middle::{
|
||||
lint::LintDiagnosticBuilder,
|
||||
ty::{self, subst::GenericArgKind, Ty},
|
||||
};
|
||||
use rustc_span::Symbol;
|
||||
|
||||
declare_lint! {
|
||||
@ -141,30 +145,60 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
|
||||
});
|
||||
let is_must_use_ty = is_must_use_ty(cx, cx.typeck_results().expr_ty(init));
|
||||
let is_must_use_func_call = is_must_use_func_call(cx, init);
|
||||
|
||||
if is_sync_lock {
|
||||
cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| {
|
||||
lint.build("non-binding let on a synchronization lock")
|
||||
.help("consider binding to an unused variable")
|
||||
.help("consider explicitly droping with `std::mem::drop`")
|
||||
.emit();
|
||||
build_and_emit_lint(
|
||||
lint,
|
||||
local,
|
||||
init.span,
|
||||
"non-binding let on a synchronization lock",
|
||||
)
|
||||
})
|
||||
} else if is_must_use_ty || is_must_use_func_call {
|
||||
cx.struct_span_lint(LET_UNDERSCORE_MUST_USE, local.span, |lint| {
|
||||
lint.build("non-binding let on a expression marked `must_use`")
|
||||
.help("consider binding to an unused variable")
|
||||
.help("consider explicitly droping with `std::mem::drop`")
|
||||
.emit();
|
||||
build_and_emit_lint(
|
||||
lint,
|
||||
local,
|
||||
init.span,
|
||||
"non-binding let on a expression marked `must_use`",
|
||||
);
|
||||
})
|
||||
} else if needs_drop {
|
||||
cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
|
||||
lint.build("non-binding let on a type that implements `Drop`")
|
||||
.help("consider binding to an unused variable")
|
||||
.help("consider explicitly droping with `std::mem::drop`")
|
||||
.emit();
|
||||
build_and_emit_lint(
|
||||
lint,
|
||||
local,
|
||||
init.span,
|
||||
"non-binding let on a type that implements `Drop`",
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn build_and_emit_lint(
|
||||
lint: LintDiagnosticBuilder<'_, ()>,
|
||||
local: &hir::Local<'_>,
|
||||
init_span: rustc_span::Span,
|
||||
msg: &str,
|
||||
) {
|
||||
lint.build(msg)
|
||||
.span_suggestion_verbose(
|
||||
local.pat.span,
|
||||
"consider binding to an unused variable",
|
||||
"_unused",
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.span_suggestion_verbose(
|
||||
init_span,
|
||||
"consider explicitly droping with `std::mem::drop`",
|
||||
"drop(...)",
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
// return true if `ty` is a type that is marked as `must_use`
|
||||
fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
match ty.kind() {
|
||||
ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()),
|
||||
|
@ -5,8 +5,14 @@ LL | let _ = NontrivialDrop;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: requested on the command line with `-W let-underscore-drop`
|
||||
= help: consider binding to an unused variable
|
||||
= help: consider explicitly droping with `std::mem::drop`
|
||||
help: consider binding to an unused variable
|
||||
|
|
||||
LL | let _unused = NontrivialDrop;
|
||||
| ~~~~~~~
|
||||
help: consider explicitly droping with `std::mem::drop`
|
||||
|
|
||||
LL | let _ = drop(...);
|
||||
| ~~~~~~~~~
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
@ -5,8 +5,14 @@ LL | let _ = data.lock().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(let_underscore_lock)]` on by default
|
||||
= help: consider binding to an unused variable
|
||||
= help: consider explicitly droping with `std::mem::drop`
|
||||
help: consider binding to an unused variable
|
||||
|
|
||||
LL | let _unused = data.lock().unwrap();
|
||||
| ~~~~~~~
|
||||
help: consider explicitly droping with `std::mem::drop`
|
||||
|
|
||||
LL | let _ = drop(...);
|
||||
| ~~~~~~~~~
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
@ -5,8 +5,14 @@ LL | let _ = MustUseType;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: requested on the command line with `-W let-underscore-must-use`
|
||||
= help: consider binding to an unused variable
|
||||
= help: consider explicitly droping with `std::mem::drop`
|
||||
help: consider binding to an unused variable
|
||||
|
|
||||
LL | let _unused = MustUseType;
|
||||
| ~~~~~~~
|
||||
help: consider explicitly droping with `std::mem::drop`
|
||||
|
|
||||
LL | let _ = drop(...);
|
||||
| ~~~~~~~~~
|
||||
|
||||
warning: non-binding let on a expression marked `must_use`
|
||||
--> $DIR/let_underscore_must_use.rs:12:5
|
||||
@ -14,8 +20,14 @@ warning: non-binding let on a expression marked `must_use`
|
||||
LL | let _ = must_use_function();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider binding to an unused variable
|
||||
= help: consider explicitly droping with `std::mem::drop`
|
||||
help: consider binding to an unused variable
|
||||
|
|
||||
LL | let _unused = must_use_function();
|
||||
| ~~~~~~~
|
||||
help: consider explicitly droping with `std::mem::drop`
|
||||
|
|
||||
LL | let _ = drop(...);
|
||||
| ~~~~~~~~~
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user