Skip to content

Commit b5b5b54

Browse files
committed
Remove let_underscore_must_use
The `let_underscore_must_use` lint was really only added because clippy included it, but it doesn't actually seem very useful.
1 parent 11663b1 commit b5b5b54

File tree

4 files changed

+3
-155
lines changed

4 files changed

+3
-155
lines changed

compiler/rustc_lint/src/let_underscore.rs

Lines changed: 2 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
use crate::{LateContext, LateLintPass, LintContext};
22
use rustc_errors::Applicability;
33
use rustc_hir as hir;
4-
use rustc_middle::{
5-
lint::LintDiagnosticBuilder,
6-
ty::{self, Ty},
7-
};
4+
use rustc_middle::{lint::LintDiagnosticBuilder, ty};
85
use rustc_span::Symbol;
96

107
declare_lint! {
@@ -87,32 +84,7 @@ declare_lint! {
8784
"non-binding let on a synchronization lock"
8885
}
8986

90-
declare_lint! {
91-
/// The `let_underscore_must_use` lint checks for statements which don't bind
92-
/// a `must_use` expression to anything, causing the lock to be released
93-
/// immediately instead of at end of scope, which is typically incorrect.
94-
///
95-
/// ### Example
96-
/// ```rust
97-
/// #[must_use]
98-
/// struct SomeStruct;
99-
///
100-
/// fn main() {
101-
/// // SomeStuct is dropped immediately instead of at end of scope.
102-
/// let _ = SomeStruct;
103-
/// }
104-
/// ```
105-
/// ### Explanation
106-
///
107-
/// Statements which assign an expression to an underscore causes the
108-
/// expression to immediately drop. Usually, it's better to explicitly handle
109-
/// the `must_use` expression.
110-
pub LET_UNDERSCORE_MUST_USE,
111-
Allow,
112-
"non-binding let on a expression marked `must_use`"
113-
}
114-
115-
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_MUST_USE]);
87+
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK]);
11688

11789
const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [
11890
rustc_span::sym::MutexGuard,
@@ -138,8 +110,6 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
138110
.any(|guard_symbol| cx.tcx.is_diagnostic_item(*guard_symbol, adt.did())),
139111
_ => false,
140112
};
141-
let is_must_use_ty = is_must_use_ty(cx, cx.typeck_results().expr_ty(init));
142-
let is_must_use_func_call = is_must_use_func_call(cx, init);
143113

144114
if is_sync_lock {
145115
cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| {
@@ -150,15 +120,6 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
150120
"non-binding let on a synchronization lock",
151121
)
152122
})
153-
} else if is_must_use_ty || is_must_use_func_call {
154-
cx.struct_span_lint(LET_UNDERSCORE_MUST_USE, local.span, |lint| {
155-
build_and_emit_lint(
156-
lint,
157-
local,
158-
init.span,
159-
"non-binding let on a expression marked `must_use`",
160-
);
161-
})
162123
} else {
163124
cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
164125
build_and_emit_lint(
@@ -194,65 +155,3 @@ fn build_and_emit_lint(
194155
)
195156
.emit();
196157
}
197-
198-
// return true if `ty` is a type that is marked as `must_use`
199-
fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
200-
match ty.kind() {
201-
ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()),
202-
ty::Foreign(ref did) => has_must_use_attr(cx, *did),
203-
ty::Slice(ty)
204-
| ty::Array(ty, _)
205-
| ty::RawPtr(ty::TypeAndMut { ty, .. })
206-
| ty::Ref(_, ty, _) => {
207-
// for the Array case we don't need to care for the len == 0 case
208-
// because we don't want to lint functions returning empty arrays
209-
is_must_use_ty(cx, *ty)
210-
}
211-
ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
212-
ty::Opaque(ref def_id, _) => {
213-
for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
214-
if let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
215-
if has_must_use_attr(cx, trait_predicate.trait_ref.def_id) {
216-
return true;
217-
}
218-
}
219-
}
220-
false
221-
}
222-
ty::Dynamic(binder, _) => {
223-
for predicate in binder.iter() {
224-
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
225-
if has_must_use_attr(cx, trait_ref.def_id) {
226-
return true;
227-
}
228-
}
229-
}
230-
false
231-
}
232-
_ => false,
233-
}
234-
}
235-
236-
// check if expr is calling method or function with #[must_use] attribute
237-
fn is_must_use_func_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
238-
let did = match expr.kind {
239-
hir::ExprKind::Call(path, _) if let hir::ExprKind::Path(ref qpath) = path.kind => {
240-
if let hir::def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id) {
241-
Some(did)
242-
} else {
243-
None
244-
}
245-
},
246-
hir::ExprKind::MethodCall(..) => {
247-
cx.typeck_results().type_dependent_def_id(expr.hir_id)
248-
}
249-
_ => None,
250-
};
251-
252-
did.map_or(false, |did| has_must_use_attr(cx, did))
253-
}
254-
255-
// returns true if DefId contains a `#[must_use]` attribute
256-
fn has_must_use_attr(cx: &LateContext<'_>, did: hir::def_id::DefId) -> bool {
257-
cx.tcx.has_attr(did, rustc_span::sym::must_use)
258-
}

compiler/rustc_lint/src/lib.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -317,12 +317,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
317317
REDUNDANT_SEMICOLONS
318318
);
319319

320-
add_lint_group!(
321-
"let_underscore",
322-
LET_UNDERSCORE_DROP,
323-
LET_UNDERSCORE_LOCK,
324-
LET_UNDERSCORE_MUST_USE
325-
);
320+
add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK);
326321

327322
add_lint_group!(
328323
"rust_2018_idioms",

src/test/ui/lint/let_underscore/let_underscore_must_use.rs

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/test/ui/lint/let_underscore/let_underscore_must_use.stderr

Lines changed: 0 additions & 33 deletions
This file was deleted.

0 commit comments

Comments
 (0)