Add needless_late_init lint

This commit is contained in:
Alex Macleod 2021-11-18 13:54:49 +00:00
parent 81f37a8150
commit 3957244120
18 changed files with 838 additions and 27 deletions

View file

@ -3033,6 +3033,7 @@ Released 2018-09-13
[`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue
[`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main
[`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each
[`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init
[`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref
[`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value

View file

@ -206,6 +206,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(needless_bool::BOOL_COMPARISON),
LintId::of(needless_bool::NEEDLESS_BOOL),
LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
LintId::of(needless_late_init::NEEDLESS_LATE_INIT),
LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF),
LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
LintId::of(needless_update::NEEDLESS_UPDATE),

View file

@ -362,6 +362,7 @@ store.register_lints(&[
needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
needless_continue::NEEDLESS_CONTINUE,
needless_for_each::NEEDLESS_FOR_EACH,
needless_late_init::NEEDLESS_LATE_INIT,
needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF,
needless_pass_by_value::NEEDLESS_PASS_BY_VALUE,
needless_question_mark::NEEDLESS_QUESTION_MARK,

View file

@ -82,6 +82,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
LintId::of(misc_early::REDUNDANT_PATTERN),
LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK),
LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
LintId::of(needless_late_init::NEEDLESS_LATE_INIT),
LintId::of(neg_multiply::NEG_MULTIPLY),
LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),

View file

@ -299,6 +299,7 @@ mod needless_bool;
mod needless_borrowed_ref;
mod needless_continue;
mod needless_for_each;
mod needless_late_init;
mod needless_option_as_deref;
mod needless_pass_by_value;
mod needless_question_mark;
@ -851,6 +852,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(move || Box::new(format_args::FormatArgs));
store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray));
store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes));
store.register_late_pass(|| Box::new(needless_late_init::NeedlessLateInit));
// add lints here, do not remove this comment, it's used in `new_lint`
}

View file

@ -0,0 +1,345 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::path_to_local;
use clippy_utils::source::snippet_opt;
use clippy_utils::visitors::{expr_visitor, is_local_used};
use rustc_errors::Applicability;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, LocalSource, MatchSource, Node, Pat, PatKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
/// Checks for late initializations that can be replaced by a let statement
/// with an initializer.
///
/// ### Why is this bad?
/// Assigning in the let statement is less repetitive.
///
/// ### Example
/// ```rust
/// let a;
/// a = 1;
///
/// let b;
/// match 3 {
/// 0 => b = "zero",
/// 1 => b = "one",
/// _ => b = "many",
/// }
///
/// let c;
/// if true {
/// c = 1;
/// } else {
/// c = -1;
/// }
/// ```
/// Use instead:
/// ```rust
/// let a = 1;
///
/// let b = match 3 {
/// 0 => "zero",
/// 1 => "one",
/// _ => "many",
/// };
///
/// let c = if true {
/// 1
/// } else {
/// -1
/// };
/// ```
#[clippy::version = "1.58.0"]
pub NEEDLESS_LATE_INIT,
style,
"late initializations that can be replaced by a let statement with an initializer"
}
declare_lint_pass!(NeedlessLateInit => [NEEDLESS_LATE_INIT]);
fn contains_assign_expr<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> bool {
let mut seen = false;
expr_visitor(cx, |expr| {
if let ExprKind::Assign(..) = expr.kind {
seen = true;
}
!seen
})
.visit_stmt(stmt);
seen
}
#[derive(Debug)]
struct LocalAssign {
lhs_id: HirId,
lhs_span: Span,
rhs_span: Span,
span: Span,
}
impl LocalAssign {
fn from_expr(expr: &Expr<'_>, span: Span) -> Option<Self> {
if let ExprKind::Assign(lhs, rhs, _) = expr.kind {
if lhs.span.from_expansion() {
return None;
}
Some(Self {
lhs_id: path_to_local(lhs)?,
lhs_span: lhs.span,
rhs_span: rhs.span.source_callsite(),
span,
})
} else {
None
}
}
fn new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, binding_id: HirId) -> Option<LocalAssign> {
let assign = match expr.kind {
ExprKind::Block(Block { expr: Some(expr), .. }, _) => Self::from_expr(expr, expr.span),
ExprKind::Block(block, _) => {
if_chain! {
if let Some((last, other_stmts)) = block.stmts.split_last();
if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = last.kind;
let assign = Self::from_expr(expr, last.span)?;
// avoid visiting if not needed
if assign.lhs_id == binding_id;
if other_stmts.iter().all(|stmt| !contains_assign_expr(cx, stmt));
then {
Some(assign)
} else {
None
}
}
},
ExprKind::Assign(..) => Self::from_expr(expr, expr.span),
_ => None,
}?;
if assign.lhs_id == binding_id {
Some(assign)
} else {
None
}
}
}
fn assignment_suggestions<'tcx>(
cx: &LateContext<'tcx>,
binding_id: HirId,
exprs: impl IntoIterator<Item = &'tcx Expr<'tcx>>,
) -> Option<(Applicability, Vec<(Span, String)>)> {
let mut assignments = Vec::new();
for expr in exprs {
let ty = cx.typeck_results().expr_ty(expr);
if ty.is_never() {
continue;
}
if !ty.is_unit() {
return None;
}
let assign = LocalAssign::new(cx, expr, binding_id)?;
assignments.push(assign);
}
let suggestions = assignments
.into_iter()
.map(|assignment| Some((assignment.span, snippet_opt(cx, assignment.rhs_span)?)))
.collect::<Option<Vec<(Span, String)>>>()?;
let applicability = if suggestions.len() > 1 {
// multiple suggestions don't work with rustfix in multipart_suggest
// https://github.com/rust-lang/rustfix/issues/141
Applicability::Unspecified
} else {
Applicability::MachineApplicable
};
Some((applicability, suggestions))
}
struct Usage<'tcx> {
stmt: &'tcx Stmt<'tcx>,
expr: &'tcx Expr<'tcx>,
needs_semi: bool,
}
fn first_usage<'tcx>(
cx: &LateContext<'tcx>,
binding_id: HirId,
local_stmt_id: HirId,
block: &'tcx Block<'tcx>,
) -> Option<Usage<'tcx>> {
block
.stmts
.iter()
.skip_while(|stmt| stmt.hir_id != local_stmt_id)
.skip(1)
.find(|&stmt| is_local_used(cx, stmt, binding_id))
.and_then(|stmt| match stmt.kind {
StmtKind::Expr(expr) => Some(Usage {
stmt,
expr,
needs_semi: true,
}),
StmtKind::Semi(expr) => Some(Usage {
stmt,
expr,
needs_semi: false,
}),
_ => None,
})
}
fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &Local<'_>) -> Option<String> {
let span = local.span.with_hi(match local.ty {
// let <pat>: <ty>;
// ~~~~~~~~~~~~~~~
Some(ty) => ty.span.hi(),
// let <pat>;
// ~~~~~~~~~
None => local.pat.span.hi(),
});
snippet_opt(cx, span)
}
fn check<'tcx>(
cx: &LateContext<'tcx>,
local: &'tcx Local<'tcx>,
local_stmt: &'tcx Stmt<'tcx>,
block: &'tcx Block<'tcx>,
binding_id: HirId,
) -> Option<()> {
let usage = first_usage(cx, binding_id, local_stmt.hir_id, block)?;
let binding_name = cx.tcx.hir().opt_name(binding_id)?;
let let_snippet = local_snippet_without_semicolon(cx, local)?;
match usage.expr.kind {
ExprKind::Assign(..) => {
let assign = LocalAssign::new(cx, usage.expr, binding_id)?;
span_lint_and_then(
cx,
NEEDLESS_LATE_INIT,
local_stmt.span,
"unneeded late initalization",
|diag| {
diag.tool_only_span_suggestion(
local_stmt.span,
"remove the local",
String::new(),
Applicability::MachineApplicable,
);
diag.span_suggestion(
assign.lhs_span,
&format!("declare `{}` here", binding_name),
let_snippet,
Applicability::MachineApplicable,
);
},
);
},
ExprKind::If(_, then_expr, Some(else_expr)) => {
let (applicability, suggestions) = assignment_suggestions(cx, binding_id, [then_expr, else_expr])?;
span_lint_and_then(
cx,
NEEDLESS_LATE_INIT,
local_stmt.span,
"unneeded late initalization",
|diag| {
diag.tool_only_span_suggestion(local_stmt.span, "remove the local", String::new(), applicability);
diag.span_suggestion_verbose(
usage.stmt.span.shrink_to_lo(),
&format!("declare `{}` here", binding_name),
format!("{} = ", let_snippet),
applicability,
);
diag.multipart_suggestion("remove the assignments from the branches", suggestions, applicability);
if usage.needs_semi {
diag.span_suggestion(
usage.stmt.span.shrink_to_hi(),
"add a semicolon after the if expression",
";".to_string(),
applicability,
);
}
},
);
},
ExprKind::Match(_, arms, MatchSource::Normal) => {
let (applicability, suggestions) = assignment_suggestions(cx, binding_id, arms.iter().map(|arm| arm.body))?;
span_lint_and_then(
cx,
NEEDLESS_LATE_INIT,
local_stmt.span,
"unneeded late initalization",
|diag| {
diag.tool_only_span_suggestion(local_stmt.span, "remove the local", String::new(), applicability);
diag.span_suggestion_verbose(
usage.stmt.span.shrink_to_lo(),
&format!("declare `{}` here", binding_name),
format!("{} = ", let_snippet),
applicability,
);
diag.multipart_suggestion("remove the assignments from the match arms", suggestions, applicability);
if usage.needs_semi {
diag.span_suggestion(
usage.stmt.span.shrink_to_hi(),
"add a semicolon after the match expression",
";".to_string(),
applicability,
);
}
},
);
},
_ => {},
};
Some(())
}
impl LateLintPass<'tcx> for NeedlessLateInit {
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
let mut parents = cx.tcx.hir().parent_iter(local.hir_id);
if_chain! {
if let Local {
init: None,
pat: &Pat {
kind: PatKind::Binding(_, binding_id, _, None),
..
},
source: LocalSource::Normal,
..
} = local;
if let Some((_, Node::Stmt(local_stmt))) = parents.next();
if let Some((_, Node::Block(block))) = parents.next();
then {
check(cx, local, local_stmt, block, binding_id);
}
}
}
}

View file

@ -164,12 +164,13 @@ fn check_unnecessary_operation(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
if !&reduced.iter().any(|e| e.span.from_expansion());
then {
if let ExprKind::Index(..) = &expr.kind {
let snippet;
if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) {
snippet = format!("assert!({}.len() > {});", &arr, &func);
let snippet = if let (Some(arr), Some(func)) =
(snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span))
{
format!("assert!({}.len() > {});", &arr, &func)
} else {
return;
}
};
span_lint_hir_and_then(
cx,
UNNECESSARY_OPERATION,

View file

@ -1,3 +1,23 @@
error: unneeded late initalization
--> $DIR/let_if_seq.rs:48:5
|
LL | let foo;
| ^^^^^^^^
|
= note: `-D clippy::needless-late-init` implied by `-D warnings`
help: declare `foo` here
|
LL | let foo = if f() {
| +++++++++
help: remove the assignments from the branches
|
LL | 0
|
help: add a semicolon after the if expression
|
LL | };
| +
error: `if _ { .. } else { .. }` is an expression
--> $DIR/let_if_seq.rs:65:5
|
@ -46,5 +66,26 @@ LL | | }
|
= note: you might not need `mut` at all
error: aborting due to 4 previous errors
error: unneeded late initalization
--> $DIR/let_if_seq.rs:78:5
|
LL | let quz;
| ^^^^^^^^
|
help: declare `quz` here
|
LL | let quz = if f() {
| +++++++++
help: remove the assignments from the branches
|
LL ~ 42
LL | } else {
LL ~ 0
|
help: add a semicolon after the if expression
|
LL | };
| +
error: aborting due to 6 previous errors

View file

@ -19,8 +19,7 @@ impl NotOrd {
}
fn main() {
let x;
x = 2usize;
let x = 2usize;
min(1, max(3, x));
min(max(3, x), 1);
max(min(x, 1), 3);
@ -35,9 +34,7 @@ fn main() {
let y = 2isize;
min(max(y, -1), 3);
let s;
s = "Hello";
let s = "Hello";
min("Apple", max("Zoo", s));
max(min(s, "Apple"), "Zoo");

View file

@ -1,5 +1,5 @@
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:24:5
--> $DIR/min_max.rs:23:5
|
LL | min(1, max(3, x));
| ^^^^^^^^^^^^^^^^^
@ -7,73 +7,73 @@ LL | min(1, max(3, x));
= note: `-D clippy::min-max` implied by `-D warnings`
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:25:5
--> $DIR/min_max.rs:24:5
|
LL | min(max(3, x), 1);
| ^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:26:5
--> $DIR/min_max.rs:25:5
|
LL | max(min(x, 1), 3);
| ^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:27:5
--> $DIR/min_max.rs:26:5
|
LL | max(3, min(x, 1));
| ^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:29:5
--> $DIR/min_max.rs:28:5
|
LL | my_max(3, my_min(x, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:41:5
--> $DIR/min_max.rs:38:5
|
LL | min("Apple", max("Zoo", s));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:42:5
--> $DIR/min_max.rs:39:5
|
LL | max(min(s, "Apple"), "Zoo");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:47:5
--> $DIR/min_max.rs:44:5
|
LL | x.min(1).max(3);
| ^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:48:5
--> $DIR/min_max.rs:45:5
|
LL | x.max(3).min(1);
| ^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:49:5
--> $DIR/min_max.rs:46:5
|
LL | f.max(3f32).min(1f32);
| ^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:55:5
--> $DIR/min_max.rs:52:5
|
LL | max(x.min(1), 3);
| ^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:58:5
--> $DIR/min_max.rs:55:5
|
LL | s.max("Zoo").min("Apple");
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
--> $DIR/min_max.rs:59:5
--> $DIR/min_max.rs:56:5
|
LL | s.min("Apple").max("Zoo");
| ^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,133 @@
#![allow(unused)]
fn main() {
let a;
let n = 1;
match n {
1 => a = "one",
_ => {
a = "two";
},
}
let b;
if n == 3 {
b = "four";
} else {
b = "five"
}
let c;
if let Some(n) = Some(5) {
c = n;
} else {
c = -50;
}
let d;
if true {
let temp = 5;
d = temp;
} else {
d = 15;
}
let e;
if true {
e = format!("{} {}", a, b);
} else {
e = format!("{}", c);
}
println!("{}", a);
}
fn does_not_lint() {
let z;
if false {
z = 1;
}
let x;
let y;
if true {
x = 1;
} else {
y = 1;
}
let mut x;
if true {
x = 5;
x = 10 / x;
} else {
x = 2;
}
let x;
let _ = match 1 {
1 => x = 10,
_ => x = 20,
};
// using tuples would be possible, but not always preferable
let x;
let y;
if true {
x = 1;
y = 2;
} else {
x = 3;
y = 4;
}
// could match with a smarter heuristic to avoid multiple assignments
let x;
if true {
let mut y = 5;
y = 6;
x = y;
} else {
x = 2;
}
let (x, y);
if true {
x = 1;
} else {
x = 2;
}
y = 3;
macro_rules! assign {
($i:ident) => {
$i = 1;
};
}
let x;
assign!(x);
let x;
if true {
assign!(x);
} else {
x = 2;
}
macro_rules! in_macro {
() => {
let x;
x = 1;
let x;
if true {
x = 1;
} else {
x = 2;
}
};
}
in_macro!();
println!("{}", x);
}

View file

@ -0,0 +1,108 @@
error: unneeded late initalization
--> $DIR/needless_late_init.rs:4:5
|
LL | let a;
| ^^^^^^
|
= note: `-D clippy::needless-late-init` implied by `-D warnings`
help: declare `a` here
|
LL | let a = match n {
| +++++++
help: remove the assignments from the match arms
|
LL ~ 1 => "one",
LL | _ => {
LL ~ "two"
|
help: add a semicolon after the match expression
|
LL | };
| +
error: unneeded late initalization
--> $DIR/needless_late_init.rs:13:5
|
LL | let b;
| ^^^^^^
|
help: declare `b` here
|
LL | let b = if n == 3 {
| +++++++
help: remove the assignments from the branches
|
LL ~ "four"
LL | } else {
LL ~ "five"
|
help: add a semicolon after the if expression
|
LL | };
| +
error: unneeded late initalization
--> $DIR/needless_late_init.rs:20:5
|
LL | let c;
| ^^^^^^
|
help: declare `c` here
|
LL | let c = if let Some(n) = Some(5) {
| +++++++
help: remove the assignments from the branches
|
LL ~ n
LL | } else {
LL ~ -50
|
help: add a semicolon after the if expression
|
LL | };
| +
error: unneeded late initalization
--> $DIR/needless_late_init.rs:27:5
|
LL | let d;
| ^^^^^^
|
help: declare `d` here
|
LL | let d = if true {
| +++++++
help: remove the assignments from the branches
|
LL ~ temp
LL | } else {
LL ~ 15
|
help: add a semicolon after the if expression
|
LL | };
| +
error: unneeded late initalization
--> $DIR/needless_late_init.rs:35:5
|
LL | let e;
| ^^^^^^
|
help: declare `e` here
|
LL | let e = if true {
| +++++++
help: remove the assignments from the branches
|
LL ~ format!("{} {}", a, b)
LL | } else {
LL ~ format!("{}", c)
|
help: add a semicolon after the if expression
|
LL | };
| +
error: aborting due to 5 previous errors

View file

@ -0,0 +1,38 @@
// run-rustfix
#![allow(unused, clippy::assign_op_pattern)]
fn main() {
let a = "zero";
let b = 1;
let c = 2;
let d: usize = 1;
let mut e = 1;
e = 2;
let f = match 1 {
1 => "three",
_ => return,
}; // has semi
let g: usize = if true {
5
} else {
panic!();
};
let h = format!("{}", e);
println!("{}", a);
}

View file

@ -0,0 +1,38 @@
// run-rustfix
#![allow(unused, clippy::assign_op_pattern)]
fn main() {
let a;
a = "zero";
let b;
let c;
b = 1;
c = 2;
let d: usize;
d = 1;
let mut e;
e = 1;
e = 2;
let f;
match 1 {
1 => f = "three",
_ => return,
}; // has semi
let g: usize;
if true {
g = 5;
} else {
panic!();
}
let h;
h = format!("{}", e);
println!("{}", a);
}

View file

@ -0,0 +1,103 @@
error: unneeded late initalization
--> $DIR/needless_late_init_fixable.rs:6:5
|
LL | let a;
| ^^^^^^
|
= note: `-D clippy::needless-late-init` implied by `-D warnings`
help: declare `a` here
|
LL | let a = "zero";
| ~~~~~
error: unneeded late initalization
--> $DIR/needless_late_init_fixable.rs:9:5
|
LL | let b;
| ^^^^^^
|
help: declare `b` here
|
LL | let b = 1;
| ~~~~~
error: unneeded late initalization
--> $DIR/needless_late_init_fixable.rs:10:5
|
LL | let c;
| ^^^^^^
|
help: declare `c` here
|
LL | let c = 2;
| ~~~~~
error: unneeded late initalization
--> $DIR/needless_late_init_fixable.rs:14:5
|
LL | let d: usize;
| ^^^^^^^^^^^^^
|
help: declare `d` here
|
LL | let d: usize = 1;
| ~~~~~~~~~~~~
error: unneeded late initalization
--> $DIR/needless_late_init_fixable.rs:17:5
|
LL | let mut e;
| ^^^^^^^^^^
|
help: declare `e` here
|
LL | let mut e = 1;
| ~~~~~~~~~
error: unneeded late initalization
--> $DIR/needless_late_init_fixable.rs:21:5
|
LL | let f;
| ^^^^^^
|
help: declare `f` here
|
LL | let f = match 1 {
| +++++++
help: remove the assignments from the match arms
|
LL | 1 => "three",
| ~~~~~~~
error: unneeded late initalization
--> $DIR/needless_late_init_fixable.rs:27:5
|
LL | let g: usize;
| ^^^^^^^^^^^^^
|
help: declare `g` here
|
LL | let g: usize = if true {
| ++++++++++++++
help: remove the assignments from the branches
|
LL | 5
|
help: add a semicolon after the if expression
|
LL | };
| +
error: unneeded late initalization
--> $DIR/needless_late_init_fixable.rs:34:5
|
LL | let h;
| ^^^^^^
|
help: declare `h` here
|
LL | let h = format!("{}", e);
| ~~~~~
error: aborting due to 8 previous errors

View file

@ -1,6 +1,7 @@
// non rustfixable, see redundant_closure_call_fixable.rs
#![warn(clippy::redundant_closure_call)]
#![allow(clippy::needless_late_init)]
fn main() {
let mut i = 1;

View file

@ -1,5 +1,5 @@
error: closure called just once immediately after it was declared
--> $DIR/redundant_closure_call_late.rs:15:5
--> $DIR/redundant_closure_call_late.rs:16:5
|
LL | i = redun_closure();
| ^^^^^^^^^^^^^^^^^^^
@ -7,13 +7,13 @@ LL | i = redun_closure();
= note: `-D clippy::redundant-closure-call` implied by `-D warnings`
error: closure called just once immediately after it was declared
--> $DIR/redundant_closure_call_late.rs:19:5
--> $DIR/redundant_closure_call_late.rs:20:5
|
LL | i = shadowed_closure();
| ^^^^^^^^^^^^^^^^^^^^^^
error: closure called just once immediately after it was declared
--> $DIR/redundant_closure_call_late.rs:21:5
--> $DIR/redundant_closure_call_late.rs:22:5
|
LL | i = shadowed_closure();
| ^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
#![warn(clippy::redundant_else)]
#![allow(clippy::needless_return, clippy::if_same_then_else)]
#![allow(clippy::needless_return, clippy::if_same_then_else, clippy::needless_late_init)]
fn main() {
loop {