mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-12-11 22:02:55 +00:00
Auto merge of #10844 - Centri3:let_unit_value, r=Alexendoo
Don't lint `let_unit_value` when `()` is explicit since these are explicitly written (and not the result of a function call or anything else), they should be allowed, as they are both useful in some cases described in #9048 Fixes #9048 changelog: [`let_unit_value`]: Don't lint when `()` is explicit
This commit is contained in:
commit
394f63fe94
7 changed files with 71 additions and 127 deletions
|
@ -13,12 +13,31 @@ use rustc_middle::ty;
|
||||||
use super::LET_UNIT_VALUE;
|
use super::LET_UNIT_VALUE;
|
||||||
|
|
||||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
|
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
|
||||||
|
// skip `let () = { ... }`
|
||||||
|
if let PatKind::Tuple(fields, ..) = local.pat.kind
|
||||||
|
&& fields.is_empty()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(init) = local.init
|
if let Some(init) = local.init
|
||||||
&& !local.pat.span.from_expansion()
|
&& !local.pat.span.from_expansion()
|
||||||
&& !in_external_macro(cx.sess(), local.span)
|
&& !in_external_macro(cx.sess(), local.span)
|
||||||
&& !is_from_async_await(local.span)
|
&& !is_from_async_await(local.span)
|
||||||
&& cx.typeck_results().pat_ty(local.pat).is_unit()
|
&& cx.typeck_results().pat_ty(local.pat).is_unit()
|
||||||
{
|
{
|
||||||
|
// skip `let awa = ()`
|
||||||
|
if let ExprKind::Tup([]) = init.kind {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip `let _: () = { ... }`
|
||||||
|
if let Some(ty) = local.ty
|
||||||
|
&& let TyKind::Tup([]) = ty.kind
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer))
|
if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer))
|
||||||
|| matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
|
|| matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
|
||||||
&& expr_needs_inferred_result(cx, init)
|
&& expr_needs_inferred_result(cx, init)
|
||||||
|
@ -34,7 +53,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
|
||||||
|diag| {
|
|diag| {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
local.pat.span,
|
local.pat.span,
|
||||||
"use a wild (`_`) binding",
|
"use a wildcard binding",
|
||||||
"_",
|
"_",
|
||||||
Applicability::MaybeIncorrect, // snippet
|
Applicability::MaybeIncorrect, // snippet
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
#![warn(clippy::let_unit_value)]
|
|
||||||
|
|
||||||
fn f() {}
|
|
||||||
static FN: fn() = f;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
FN();
|
|
||||||
//~^ ERROR: this let-binding has unit value
|
|
||||||
//~| NOTE: `-D clippy::let-unit-value` implied by `-D warnings`
|
|
||||||
}
|
|
|
@ -5,6 +5,4 @@ static FN: fn() = f;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: () = FN();
|
let _: () = FN();
|
||||||
//~^ ERROR: this let-binding has unit value
|
|
||||||
//~| NOTE: `-D clippy::let-unit-value` implied by `-D warnings`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
error: this let-binding has unit value
|
|
||||||
--> $DIR/ice-8821.rs:7:5
|
|
||||||
|
|
|
||||||
LL | let _: () = FN();
|
|
||||||
| ^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `FN();`
|
|
||||||
|
|
|
||||||
= note: `-D clippy::let-unit-value` implied by `-D warnings`
|
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
|
@ -13,7 +13,14 @@ fn main() {
|
||||||
let _y = 1; // this is fine
|
let _y = 1; // this is fine
|
||||||
let _z = ((), 1); // this as well
|
let _z = ((), 1); // this as well
|
||||||
if true {
|
if true {
|
||||||
();
|
// do not lint this, since () is explicit
|
||||||
|
let _a = ();
|
||||||
|
let () = dummy();
|
||||||
|
let () = ();
|
||||||
|
() = dummy();
|
||||||
|
() = ();
|
||||||
|
let _a: () = ();
|
||||||
|
let _a: () = dummy();
|
||||||
}
|
}
|
||||||
|
|
||||||
consume_units_with_for_loop(); // should be fine as well
|
consume_units_with_for_loop(); // should be fine as well
|
||||||
|
@ -23,6 +30,8 @@ fn main() {
|
||||||
let_and_return!(()) // should be fine
|
let_and_return!(()) // should be fine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dummy() {}
|
||||||
|
|
||||||
// Related to issue #1964
|
// Related to issue #1964
|
||||||
fn consume_units_with_for_loop() {
|
fn consume_units_with_for_loop() {
|
||||||
// `for_let_unit` lint should not be triggered by consuming them using for loop.
|
// `for_let_unit` lint should not be triggered by consuming them using for loop.
|
||||||
|
@ -74,40 +83,29 @@ fn _returns_generic() {
|
||||||
x.then(|| T::default())
|
x.then(|| T::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
let _: () = f(); // Ok
|
let _: () = f();
|
||||||
let _: () = f(); // Lint.
|
let x: () = f();
|
||||||
|
|
||||||
let _: () = f2(0i32); // Ok
|
let _: () = f2(0i32);
|
||||||
let _: () = f2(0i32); // Lint.
|
let x: () = f2(0i32);
|
||||||
|
|
||||||
f3(()); // Lint
|
let _: () = f3(());
|
||||||
f3(()); // Lint
|
let x: () = f3(());
|
||||||
|
|
||||||
// Should lint:
|
fn f4<T>(mut x: Vec<T>) -> T {
|
||||||
// fn f4<T>(mut x: Vec<T>) -> T {
|
x.pop().unwrap()
|
||||||
// x.pop().unwrap()
|
}
|
||||||
// }
|
let _: () = f4(vec![()]);
|
||||||
// let _: () = f4(vec![()]);
|
let x: () = f4(vec![()]);
|
||||||
// let x: () = f4(vec![()]);
|
|
||||||
|
|
||||||
// Ok
|
|
||||||
let _: () = {
|
let _: () = {
|
||||||
let x = 5;
|
let x = 5;
|
||||||
f2(x)
|
f2(x)
|
||||||
};
|
};
|
||||||
|
|
||||||
let _: () = if true { f() } else { f2(0) }; // Ok
|
let _: () = if true { f() } else { f2(0) };
|
||||||
let _: () = if true { f() } else { f2(0) }; // Lint
|
let x: () = if true { f() } else { f2(0) };
|
||||||
|
|
||||||
// Ok
|
|
||||||
let _: () = match Some(0) {
|
|
||||||
None => f2(1),
|
|
||||||
Some(0) => f(),
|
|
||||||
Some(1) => f2(3),
|
|
||||||
Some(_) => f2('x'),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lint
|
|
||||||
match Some(0) {
|
match Some(0) {
|
||||||
None => f2(1),
|
None => f2(1),
|
||||||
Some(0) => f(),
|
Some(0) => f(),
|
||||||
|
@ -155,7 +153,7 @@ fn _returns_generic() {
|
||||||
{
|
{
|
||||||
let _: () = x;
|
let _: () = x;
|
||||||
let _: () = y;
|
let _: () = y;
|
||||||
z;
|
let _: () = z;
|
||||||
let _: () = x1;
|
let _: () = x1;
|
||||||
let _: () = x2;
|
let _: () = x2;
|
||||||
let _: () = opt;
|
let _: () = opt;
|
||||||
|
|
|
@ -13,7 +13,14 @@ fn main() {
|
||||||
let _y = 1; // this is fine
|
let _y = 1; // this is fine
|
||||||
let _z = ((), 1); // this as well
|
let _z = ((), 1); // this as well
|
||||||
if true {
|
if true {
|
||||||
|
// do not lint this, since () is explicit
|
||||||
let _a = ();
|
let _a = ();
|
||||||
|
let () = dummy();
|
||||||
|
let () = ();
|
||||||
|
() = dummy();
|
||||||
|
() = ();
|
||||||
|
let _a: () = ();
|
||||||
|
let _a: () = dummy();
|
||||||
}
|
}
|
||||||
|
|
||||||
consume_units_with_for_loop(); // should be fine as well
|
consume_units_with_for_loop(); // should be fine as well
|
||||||
|
@ -23,6 +30,8 @@ fn main() {
|
||||||
let_and_return!(()) // should be fine
|
let_and_return!(()) // should be fine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dummy() {}
|
||||||
|
|
||||||
// Related to issue #1964
|
// Related to issue #1964
|
||||||
fn consume_units_with_for_loop() {
|
fn consume_units_with_for_loop() {
|
||||||
// `for_let_unit` lint should not be triggered by consuming them using for loop.
|
// `for_let_unit` lint should not be triggered by consuming them using for loop.
|
||||||
|
@ -74,41 +83,30 @@ fn _returns_generic() {
|
||||||
x.then(|| T::default())
|
x.then(|| T::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
let _: () = f(); // Ok
|
let _: () = f();
|
||||||
let x: () = f(); // Lint.
|
let x: () = f();
|
||||||
|
|
||||||
let _: () = f2(0i32); // Ok
|
let _: () = f2(0i32);
|
||||||
let x: () = f2(0i32); // Lint.
|
let x: () = f2(0i32);
|
||||||
|
|
||||||
let _: () = f3(()); // Lint
|
let _: () = f3(());
|
||||||
let x: () = f3(()); // Lint
|
let x: () = f3(());
|
||||||
|
|
||||||
// Should lint:
|
fn f4<T>(mut x: Vec<T>) -> T {
|
||||||
// fn f4<T>(mut x: Vec<T>) -> T {
|
x.pop().unwrap()
|
||||||
// x.pop().unwrap()
|
}
|
||||||
// }
|
let _: () = f4(vec![()]);
|
||||||
// let _: () = f4(vec![()]);
|
let x: () = f4(vec![()]);
|
||||||
// let x: () = f4(vec![()]);
|
|
||||||
|
|
||||||
// Ok
|
|
||||||
let _: () = {
|
let _: () = {
|
||||||
let x = 5;
|
let x = 5;
|
||||||
f2(x)
|
f2(x)
|
||||||
};
|
};
|
||||||
|
|
||||||
let _: () = if true { f() } else { f2(0) }; // Ok
|
let _: () = if true { f() } else { f2(0) };
|
||||||
let x: () = if true { f() } else { f2(0) }; // Lint
|
let x: () = if true { f() } else { f2(0) };
|
||||||
|
|
||||||
// Ok
|
let x = match Some(0) {
|
||||||
let _: () = match Some(0) {
|
|
||||||
None => f2(1),
|
|
||||||
Some(0) => f(),
|
|
||||||
Some(1) => f2(3),
|
|
||||||
Some(_) => f2('x'),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lint
|
|
||||||
let _: () = match Some(0) {
|
|
||||||
None => f2(1),
|
None => f2(1),
|
||||||
Some(0) => f(),
|
Some(0) => f(),
|
||||||
Some(1) => f2(3),
|
Some(1) => f2(3),
|
||||||
|
|
|
@ -8,13 +8,7 @@ LL | let _x = println!("x");
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
|
= help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
|
||||||
|
|
||||||
error: this let-binding has unit value
|
error: this let-binding has unit value
|
||||||
--> $DIR/let_unit.rs:16:9
|
--> $DIR/let_unit.rs:60:5
|
||||||
|
|
|
||||||
LL | let _a = ();
|
|
||||||
| ^^^^^^^^^^^^ help: omit the `let` binding: `();`
|
|
||||||
|
|
||||||
error: this let-binding has unit value
|
|
||||||
--> $DIR/let_unit.rs:51:5
|
|
||||||
|
|
|
|
||||||
LL | / let _ = v
|
LL | / let _ = v
|
||||||
LL | | .into_iter()
|
LL | | .into_iter()
|
||||||
|
@ -37,45 +31,9 @@ LL + .unwrap();
|
||||||
|
|
|
|
||||||
|
|
||||||
error: this let-binding has unit value
|
error: this let-binding has unit value
|
||||||
--> $DIR/let_unit.rs:78:5
|
--> $DIR/let_unit.rs:109:5
|
||||||
|
|
|
|
||||||
LL | let x: () = f(); // Lint.
|
LL | / let x = match Some(0) {
|
||||||
| ^^^^-^^^^^^^^^^^
|
|
||||||
| |
|
|
||||||
| help: use a wild (`_`) binding: `_`
|
|
||||||
|
|
||||||
error: this let-binding has unit value
|
|
||||||
--> $DIR/let_unit.rs:81:5
|
|
||||||
|
|
|
||||||
LL | let x: () = f2(0i32); // Lint.
|
|
||||||
| ^^^^-^^^^^^^^^^^^^^^^
|
|
||||||
| |
|
|
||||||
| help: use a wild (`_`) binding: `_`
|
|
||||||
|
|
||||||
error: this let-binding has unit value
|
|
||||||
--> $DIR/let_unit.rs:83:5
|
|
||||||
|
|
|
||||||
LL | let _: () = f3(()); // Lint
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `f3(());`
|
|
||||||
|
|
||||||
error: this let-binding has unit value
|
|
||||||
--> $DIR/let_unit.rs:84:5
|
|
||||||
|
|
|
||||||
LL | let x: () = f3(()); // Lint
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `f3(());`
|
|
||||||
|
|
||||||
error: this let-binding has unit value
|
|
||||||
--> $DIR/let_unit.rs:100:5
|
|
||||||
|
|
|
||||||
LL | let x: () = if true { f() } else { f2(0) }; // Lint
|
|
||||||
| ^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
| |
|
|
||||||
| help: use a wild (`_`) binding: `_`
|
|
||||||
|
|
||||||
error: this let-binding has unit value
|
|
||||||
--> $DIR/let_unit.rs:111:5
|
|
||||||
|
|
|
||||||
LL | / let _: () = match Some(0) {
|
|
||||||
LL | | None => f2(1),
|
LL | | None => f2(1),
|
||||||
LL | | Some(0) => f(),
|
LL | | Some(0) => f(),
|
||||||
LL | | Some(1) => f2(3),
|
LL | | Some(1) => f2(3),
|
||||||
|
@ -93,11 +51,5 @@ LL + Some(_) => (),
|
||||||
LL + };
|
LL + };
|
||||||
|
|
|
|
||||||
|
|
||||||
error: this let-binding has unit value
|
error: aborting due to 3 previous errors
|
||||||
--> $DIR/let_unit.rs:158:13
|
|
||||||
|
|
|
||||||
LL | let _: () = z;
|
|
||||||
| ^^^^^^^^^^^^^^ help: omit the `let` binding: `z;`
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue