Allow more complex expressions in let_unit_value
This commit is contained in:
parent
48bcc1d95f
commit
70f7c624e4
@ -1,5 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_with_macro_callsite;
|
use clippy_utils::source::snippet_with_macro_callsite;
|
||||||
|
use clippy_utils::visitors::for_each_value_source;
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind, PatKind, Stmt, StmtKind};
|
use rustc_hir::{Expr, ExprKind, PatKind, Stmt, StmtKind};
|
||||||
@ -11,11 +12,18 @@
|
|||||||
|
|
||||||
pub(super) fn check(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
|
pub(super) fn check(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
|
||||||
if let StmtKind::Local(local) = stmt.kind
|
if let StmtKind::Local(local) = stmt.kind
|
||||||
|
&& let Some(init) = local.init
|
||||||
&& !local.pat.span.from_expansion()
|
&& !local.pat.span.from_expansion()
|
||||||
&& !in_external_macro(cx.sess(), stmt.span)
|
&& !in_external_macro(cx.sess(), stmt.span)
|
||||||
&& cx.typeck_results().pat_ty(local.pat).is_unit()
|
&& cx.typeck_results().pat_ty(local.pat).is_unit()
|
||||||
{
|
{
|
||||||
if local.init.map_or(false, |e| needs_inferred_result_ty(cx, e)) {
|
let needs_inferred = for_each_value_source(init, &mut |e| if needs_inferred_result_ty(cx, e) {
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
} else {
|
||||||
|
ControlFlow::Break(())
|
||||||
|
}).is_continue();
|
||||||
|
|
||||||
|
if needs_inferred {
|
||||||
if !matches!(local.pat.kind, PatKind::Wild) {
|
if !matches!(local.pat.kind, PatKind::Wild) {
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::path_to_local_id;
|
use crate::path_to_local_id;
|
||||||
|
use core::ops::ControlFlow;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
|
use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
|
||||||
@ -402,3 +403,36 @@ fn visit_block(&mut self, b: &'tcx Block<'_>) {
|
|||||||
v.visit_expr(e);
|
v.visit_expr(e);
|
||||||
v.found_unsafe
|
v.found_unsafe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs the given function for each sub-expression producing the final value consumed by the parent
|
||||||
|
/// of the give expression.
|
||||||
|
///
|
||||||
|
/// e.g. for the following expression
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// if foo {
|
||||||
|
/// f(0)
|
||||||
|
/// } else {
|
||||||
|
/// 1 + 1
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// this will pass both `f(0)` and `1+1` to the given function.
|
||||||
|
pub fn for_each_value_source<'tcx, B>(
|
||||||
|
e: &'tcx Expr<'tcx>,
|
||||||
|
f: &mut impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>,
|
||||||
|
) -> ControlFlow<B> {
|
||||||
|
match e.kind {
|
||||||
|
ExprKind::Block(Block { expr: Some(e), .. }, _) => for_each_value_source(e, f),
|
||||||
|
ExprKind::Match(_, arms, _) => {
|
||||||
|
for arm in arms {
|
||||||
|
for_each_value_source(arm.body, f)?;
|
||||||
|
}
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
},
|
||||||
|
ExprKind::If(_, if_expr, Some(else_expr)) => {
|
||||||
|
for_each_value_source(if_expr, f)?;
|
||||||
|
for_each_value_source(else_expr, f)
|
||||||
|
},
|
||||||
|
ExprKind::DropTemps(e) => for_each_value_source(e, f),
|
||||||
|
_ => f(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -44,8 +44,8 @@ fn main() {
|
|||||||
let _ = core::ptr::read_unaligned(ptr as *const u16);
|
let _ = core::ptr::read_unaligned(ptr as *const u16);
|
||||||
let _ = core::intrinsics::unaligned_volatile_load(ptr as *const u16);
|
let _ = core::intrinsics::unaligned_volatile_load(ptr as *const u16);
|
||||||
let ptr = &mut data as *mut [u8; 2] as *mut u8;
|
let ptr = &mut data as *mut [u8; 2] as *mut u8;
|
||||||
let _ = (ptr as *mut u16).write_unaligned(0);
|
(ptr as *mut u16).write_unaligned(0);
|
||||||
let _ = core::ptr::write_unaligned(ptr as *mut u16, 0);
|
core::ptr::write_unaligned(ptr as *mut u16, 0);
|
||||||
let _ = core::intrinsics::unaligned_volatile_store(ptr as *mut u16, 0);
|
core::intrinsics::unaligned_volatile_store(ptr as *mut u16, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,4 +87,29 @@ fn _returns_generic() {
|
|||||||
|
|
||||||
f4(vec![()]); // Lint
|
f4(vec![()]); // Lint
|
||||||
f4(vec![()]); // Lint
|
f4(vec![()]); // Lint
|
||||||
|
|
||||||
|
// Ok
|
||||||
|
let _: () = {
|
||||||
|
let x = 5;
|
||||||
|
f2(x)
|
||||||
|
};
|
||||||
|
|
||||||
|
let _: () = if true { f() } else { f2(0) }; // Ok
|
||||||
|
let _: () = if true { f() } else { f2(0) }; // Lint
|
||||||
|
|
||||||
|
// Ok
|
||||||
|
let _: () = match Some(0) {
|
||||||
|
None => f2(1),
|
||||||
|
Some(0) => f(),
|
||||||
|
Some(1) => f2(3),
|
||||||
|
Some(_) => f2('x'),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lint
|
||||||
|
match Some(0) {
|
||||||
|
None => f2(1),
|
||||||
|
Some(0) => f(),
|
||||||
|
Some(1) => f2(3),
|
||||||
|
Some(_) => (),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -87,4 +87,29 @@ fn f4<T>(mut x: Vec<T>) -> T {
|
|||||||
|
|
||||||
let _: () = f4(vec![()]); // Lint
|
let _: () = f4(vec![()]); // Lint
|
||||||
let x: () = f4(vec![()]); // Lint
|
let x: () = f4(vec![()]); // Lint
|
||||||
|
|
||||||
|
// Ok
|
||||||
|
let _: () = {
|
||||||
|
let x = 5;
|
||||||
|
f2(x)
|
||||||
|
};
|
||||||
|
|
||||||
|
let _: () = if true { f() } else { f2(0) }; // Ok
|
||||||
|
let x: () = if true { f() } else { f2(0) }; // Lint
|
||||||
|
|
||||||
|
// Ok
|
||||||
|
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),
|
||||||
|
Some(0) => f(),
|
||||||
|
Some(1) => f2(3),
|
||||||
|
Some(_) => (),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -74,5 +74,34 @@ error: this let-binding has unit value
|
|||||||
LL | let x: () = f4(vec![()]); // Lint
|
LL | let x: () = f4(vec![()]); // Lint
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `f4(vec![()]);`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `f4(vec![()]);`
|
||||||
|
|
||||||
error: aborting due to 9 previous errors
|
error: this let-binding has unit value
|
||||||
|
--> $DIR/let_unit.rs:98: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:109:5
|
||||||
|
|
|
||||||
|
LL | / let _: () = match Some(0) {
|
||||||
|
LL | | None => f2(1),
|
||||||
|
LL | | Some(0) => f(),
|
||||||
|
LL | | Some(1) => f2(3),
|
||||||
|
LL | | Some(_) => (),
|
||||||
|
LL | | };
|
||||||
|
| |______^
|
||||||
|
|
|
||||||
|
help: omit the `let` binding
|
||||||
|
|
|
||||||
|
LL ~ match Some(0) {
|
||||||
|
LL + None => f2(1),
|
||||||
|
LL + Some(0) => f(),
|
||||||
|
LL + Some(1) => f2(3),
|
||||||
|
LL + Some(_) => (),
|
||||||
|
LL + };
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
#![warn(clippy::or_then_unwrap)]
|
#![warn(clippy::or_then_unwrap)]
|
||||||
#![allow(clippy::map_identity)]
|
#![allow(clippy::map_identity, clippy::let_unit_value)]
|
||||||
|
|
||||||
struct SomeStruct;
|
struct SomeStruct;
|
||||||
impl SomeStruct {
|
impl SomeStruct {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
#![warn(clippy::or_then_unwrap)]
|
#![warn(clippy::or_then_unwrap)]
|
||||||
#![allow(clippy::map_identity)]
|
#![allow(clippy::map_identity, clippy::let_unit_value)]
|
||||||
|
|
||||||
struct SomeStruct;
|
struct SomeStruct;
|
||||||
impl SomeStruct {
|
impl SomeStruct {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![allow(clippy::assertions_on_constants, clippy::eq_op)]
|
#![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::let_unit_value)]
|
||||||
#![feature(inline_const)]
|
#![feature(inline_const)]
|
||||||
#![warn(clippy::unimplemented, clippy::unreachable, clippy::todo, clippy::panic)]
|
#![warn(clippy::unimplemented, clippy::unreachable, clippy::todo, clippy::panic)]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user