mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-17 06:28:42 +00:00
Auto merge of #5134 - flip1995:snippet_block, r=phansch
Make it possible to correctly indent snippet_block snippets This adds a `indent_relative_to` arg to the `{snippet,expr}_block` functions. This makes it possible to keep the correct indentation of block like suggestions. In addition, this makes the `trim_multiline` function private and adds a `indent_of` function, to get the indentation of the first line of a span. The suggestion of `needless_continue` cannot be made auto applicable, since it would be also necessary to remove code following the linted expression. (Well, maybe it is possible, but I don't know how to do it. Expanding the suggestion span to the last expression, that should be removed didn't work) changelog: Improve suggestions, when blocks of code are involved
This commit is contained in:
commit
b5e6d6db41
22 changed files with 698 additions and 598 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::reexport::*;
|
||||
use crate::utils::{
|
||||
is_present_in_source, last_line_of_span, match_def_path, paths, snippet_opt, span_lint, span_lint_and_sugg,
|
||||
first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_sugg,
|
||||
span_lint_and_then, without_block_comments,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
|
@ -261,7 +261,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes {
|
|||
_ => {},
|
||||
}
|
||||
}
|
||||
let line_span = last_line_of_span(cx, attr.span);
|
||||
let line_span = first_line_of_span(cx, attr.span);
|
||||
|
||||
if let Some(mut sugg) = snippet_opt(cx, line_span) {
|
||||
if sugg.contains("#[") {
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::utils::*;
|
|||
use matches::matches;
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::lint::in_external_macro;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::*;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
|
@ -79,8 +80,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
|
|||
if in_external_macro(cx.sess(), expr.span) {
|
||||
return;
|
||||
}
|
||||
if let Some((check, then, _)) = higher::if_block(&expr) {
|
||||
if let ExprKind::Block(block, _) = &check.kind {
|
||||
if let Some((cond, _, _)) = higher::if_block(&expr) {
|
||||
if let ExprKind::Block(block, _) = &cond.kind {
|
||||
if block.rules == BlockCheckMode::DefaultBlock {
|
||||
if block.stmts.is_empty() {
|
||||
if let Some(ex) = &block.expr {
|
||||
|
@ -89,16 +90,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
|
|||
if expr.span.from_expansion() || differing_macro_contexts(expr.span, ex.span) {
|
||||
return;
|
||||
}
|
||||
span_lint_and_help(
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BLOCK_IN_IF_CONDITION_EXPR,
|
||||
check.span,
|
||||
cond.span,
|
||||
BRACED_EXPR_MESSAGE,
|
||||
&format!(
|
||||
"try\nif {} {} ... ",
|
||||
snippet_block(cx, ex.span, ".."),
|
||||
snippet_block(cx, then.span, "..")
|
||||
"try",
|
||||
format!(
|
||||
"{}",
|
||||
snippet_block_with_applicability(
|
||||
cx,
|
||||
ex.span,
|
||||
"..",
|
||||
Some(expr.span),
|
||||
&mut applicability
|
||||
)
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -107,22 +116,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
|
|||
return;
|
||||
}
|
||||
// move block higher
|
||||
span_lint_and_help(
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
BLOCK_IN_IF_CONDITION_STMT,
|
||||
check.span,
|
||||
expr.span.with_hi(cond.span.hi()),
|
||||
COMPLEX_BLOCK_MESSAGE,
|
||||
&format!(
|
||||
"try\nlet res = {};\nif res {} ... ",
|
||||
snippet_block(cx, block.span, ".."),
|
||||
snippet_block(cx, then.span, "..")
|
||||
"try",
|
||||
format!(
|
||||
"let res = {}; if res",
|
||||
snippet_block_with_applicability(
|
||||
cx,
|
||||
block.span,
|
||||
"..",
|
||||
Some(expr.span),
|
||||
&mut applicability
|
||||
),
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut visitor = ExVisitor { found_block: None, cx };
|
||||
walk_expr(&mut visitor, check);
|
||||
walk_expr(&mut visitor, cond);
|
||||
if let Some(block) = visitor.found_block {
|
||||
span_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
|
|||
|
||||
fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool {
|
||||
// We trim all opening braces and whitespaces and then check if the next string is a comment.
|
||||
let trimmed_block_text = snippet_block(cx, expr.span, "..")
|
||||
let trimmed_block_text = snippet_block(cx, expr.span, "..", None)
|
||||
.trim_start_matches(|c: char| c.is_whitespace() || c == '{')
|
||||
.to_owned();
|
||||
trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*")
|
||||
|
@ -116,7 +116,7 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) {
|
|||
block.span,
|
||||
"this `else { if .. }` block can be collapsed",
|
||||
"try",
|
||||
snippet_block_with_applicability(cx, else_.span, "..", &mut applicability).into_owned(),
|
||||
snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability).into_owned(),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
|
|||
format!(
|
||||
"if {} {}",
|
||||
lhs.and(&rhs),
|
||||
snippet_block(cx, content.span, ".."),
|
||||
snippet_block(cx, content.span, "..", Some(expr.span)),
|
||||
),
|
||||
Applicability::MachineApplicable, // snippet
|
||||
);
|
||||
|
|
|
@ -3,9 +3,9 @@ use crate::utils::paths;
|
|||
use crate::utils::sugg::Sugg;
|
||||
use crate::utils::usage::is_unused;
|
||||
use crate::utils::{
|
||||
expr_block, get_arg_name, in_macro, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath, match_type,
|
||||
match_var, multispan_sugg, remove_blocks, snippet, snippet_block, snippet_with_applicability, span_lint_and_help,
|
||||
span_lint_and_note, span_lint_and_sugg, span_lint_and_then, walk_ptrs_ty,
|
||||
expr_block, get_arg_name, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath,
|
||||
match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, snippet_with_applicability,
|
||||
span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, walk_ptrs_ty,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use rustc::lint::in_external_macro;
|
||||
|
@ -434,7 +434,7 @@ fn report_single_match_single_pattern(
|
|||
) {
|
||||
let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH };
|
||||
let els_str = els.map_or(String::new(), |els| {
|
||||
format!(" else {}", expr_block(cx, els, None, ".."))
|
||||
format!(" else {}", expr_block(cx, els, None, "..", Some(expr.span)))
|
||||
});
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -447,7 +447,7 @@ fn report_single_match_single_pattern(
|
|||
"if let {} = {} {}{}",
|
||||
snippet(cx, arms[0].pat.span, ".."),
|
||||
snippet(cx, ex.span, ".."),
|
||||
expr_block(cx, &arms[0].body, None, ".."),
|
||||
expr_block(cx, &arms[0].body, None, "..", Some(expr.span)),
|
||||
els_str,
|
||||
),
|
||||
Applicability::HasPlaceholders,
|
||||
|
@ -523,17 +523,21 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], e
|
|||
(false, false) => Some(format!(
|
||||
"if {} {} else {}",
|
||||
snippet(cx, ex.span, "b"),
|
||||
expr_block(cx, true_expr, None, ".."),
|
||||
expr_block(cx, false_expr, None, "..")
|
||||
expr_block(cx, true_expr, None, "..", Some(expr.span)),
|
||||
expr_block(cx, false_expr, None, "..", Some(expr.span))
|
||||
)),
|
||||
(false, true) => Some(format!(
|
||||
"if {} {}",
|
||||
snippet(cx, ex.span, "b"),
|
||||
expr_block(cx, true_expr, None, "..")
|
||||
expr_block(cx, true_expr, None, "..", Some(expr.span))
|
||||
)),
|
||||
(true, false) => {
|
||||
let test = Sugg::hir(cx, ex, "..");
|
||||
Some(format!("if {} {}", !test, expr_block(cx, false_expr, None, "..")))
|
||||
Some(format!(
|
||||
"if {} {}",
|
||||
!test,
|
||||
expr_block(cx, false_expr, None, "..", Some(expr.span))
|
||||
))
|
||||
},
|
||||
(true, true) => None,
|
||||
};
|
||||
|
@ -832,7 +836,7 @@ fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[A
|
|||
let mut snippet_body = if match_body.span.from_expansion() {
|
||||
Sugg::hir_with_macro_callsite(cx, match_body, "..").to_string()
|
||||
} else {
|
||||
snippet_block(cx, match_body.span, "..").to_owned().to_string()
|
||||
snippet_block(cx, match_body.span, "..", Some(expr.span)).to_string()
|
||||
};
|
||||
|
||||
// Do we need to add ';' to suggestion ?
|
||||
|
@ -861,10 +865,11 @@ fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[A
|
|||
"this match could be written as a `let` statement",
|
||||
"consider using `let` statement",
|
||||
format!(
|
||||
"let {} = {};\n{}",
|
||||
"let {} = {};\n{}{}",
|
||||
snippet_with_applicability(cx, bind_names, "..", &mut applicability),
|
||||
snippet_with_applicability(cx, matched_vars, "..", &mut applicability),
|
||||
snippet_body
|
||||
" ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
|
||||
snippet_body,
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
|
|
|
@ -36,10 +36,10 @@
|
|||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::{original_sp, DUMMY_SP};
|
||||
use std::borrow::Cow;
|
||||
use rustc_span::Span;
|
||||
use syntax::ast;
|
||||
|
||||
use crate::utils::{snippet, snippet_block, span_lint_and_help, trim_multiline};
|
||||
use crate::utils::{indent_of, snippet, snippet_block, span_lint_and_help};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** The lint checks for `if`-statements appearing in loops
|
||||
|
@ -119,9 +119,9 @@ declare_clippy_lint! {
|
|||
declare_lint_pass!(NeedlessContinue => [NEEDLESS_CONTINUE]);
|
||||
|
||||
impl EarlyLintPass for NeedlessContinue {
|
||||
fn check_expr(&mut self, ctx: &EarlyContext<'_>, expr: &ast::Expr) {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
|
||||
if !expr.span.from_expansion() {
|
||||
check_and_warn(ctx, expr);
|
||||
check_and_warn(cx, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,93 +273,96 @@ struct LintData<'a> {
|
|||
block_stmts: &'a [ast::Stmt],
|
||||
}
|
||||
|
||||
const MSG_REDUNDANT_ELSE_BLOCK: &str = "This `else` block is redundant.\n";
|
||||
const MSG_REDUNDANT_ELSE_BLOCK: &str = "this `else` block is redundant";
|
||||
|
||||
const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "There is no need for an explicit `else` block for this `if` \
|
||||
expression\n";
|
||||
const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "there is no need for an explicit `else` block for this `if` \
|
||||
expression";
|
||||
|
||||
const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "Consider dropping the `else` clause and merging the code that \
|
||||
follows (in the loop) with the `if` block, like so:\n";
|
||||
const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "consider dropping the `else` clause and merging the code that \
|
||||
follows (in the loop) with the `if` block";
|
||||
|
||||
const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the `else` clause, and moving out the code in the `else` \
|
||||
block, like so:\n";
|
||||
const DROP_ELSE_BLOCK_MSG: &str = "consider dropping the `else` clause";
|
||||
|
||||
fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) {
|
||||
fn emit_warning<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) {
|
||||
// snip is the whole *help* message that appears after the warning.
|
||||
// message is the warning message.
|
||||
// expr is the expression which the lint warning message refers to.
|
||||
let (snip, message, expr) = match typ {
|
||||
LintType::ContinueInsideElseBlock => (
|
||||
suggestion_snippet_for_continue_inside_else(ctx, data, header),
|
||||
suggestion_snippet_for_continue_inside_else(cx, data),
|
||||
MSG_REDUNDANT_ELSE_BLOCK,
|
||||
data.else_expr,
|
||||
),
|
||||
LintType::ContinueInsideThenBlock => (
|
||||
suggestion_snippet_for_continue_inside_if(ctx, data, header),
|
||||
suggestion_snippet_for_continue_inside_if(cx, data),
|
||||
MSG_ELSE_BLOCK_NOT_NEEDED,
|
||||
data.if_expr,
|
||||
),
|
||||
};
|
||||
span_lint_and_help(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip);
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
NEEDLESS_CONTINUE,
|
||||
expr.span,
|
||||
message,
|
||||
&format!("{}\n{}", header, snip),
|
||||
);
|
||||
}
|
||||
|
||||
fn suggestion_snippet_for_continue_inside_if<'a>(
|
||||
ctx: &EarlyContext<'_>,
|
||||
data: &'a LintData<'_>,
|
||||
header: &str,
|
||||
) -> String {
|
||||
let cond_code = snippet(ctx, data.if_cond.span, "..");
|
||||
fn suggestion_snippet_for_continue_inside_if<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String {
|
||||
let cond_code = snippet(cx, data.if_cond.span, "..");
|
||||
|
||||
let if_code = format!("if {} {{\n continue;\n}}\n", cond_code);
|
||||
/* ^^^^--- Four spaces of indentation. */
|
||||
// region B
|
||||
let else_code = snippet(ctx, data.else_expr.span, "..").into_owned();
|
||||
let else_code = erode_block(&else_code);
|
||||
let else_code = trim_multiline(Cow::from(else_code), false);
|
||||
let continue_code = snippet_block(cx, data.if_block.span, "..", Some(data.if_expr.span));
|
||||
|
||||
let mut ret = String::from(header);
|
||||
ret.push_str(&if_code);
|
||||
ret.push_str(&else_code);
|
||||
ret.push_str("\n...");
|
||||
ret
|
||||
let else_code = snippet_block(cx, data.else_expr.span, "..", Some(data.if_expr.span));
|
||||
|
||||
let indent_if = indent_of(cx, data.if_expr.span).unwrap_or(0);
|
||||
format!(
|
||||
"{indent}if {} {}\n{indent}{}",
|
||||
cond_code,
|
||||
continue_code,
|
||||
else_code,
|
||||
indent = " ".repeat(indent_if),
|
||||
)
|
||||
}
|
||||
|
||||
fn suggestion_snippet_for_continue_inside_else<'a>(
|
||||
ctx: &EarlyContext<'_>,
|
||||
data: &'a LintData<'_>,
|
||||
header: &str,
|
||||
) -> String {
|
||||
let cond_code = snippet(ctx, data.if_cond.span, "..");
|
||||
let mut if_code = format!("if {} {{\n", cond_code);
|
||||
fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String {
|
||||
let cond_code = snippet(cx, data.if_cond.span, "..");
|
||||
|
||||
// Region B
|
||||
let block_code = &snippet(ctx, data.if_block.span, "..").into_owned();
|
||||
let block_code = erode_block(block_code);
|
||||
let block_code = trim_multiline(Cow::from(block_code), false);
|
||||
|
||||
if_code.push_str(&block_code);
|
||||
let block_code = erode_from_back(&snippet_block(cx, data.if_block.span, "..", Some(data.if_expr.span)));
|
||||
|
||||
// Region C
|
||||
// These is the code in the loop block that follows the if/else construction
|
||||
// we are complaining about. We want to pull all of this code into the
|
||||
// `then` block of the `if` statement.
|
||||
let indent = span_of_first_expr_in_block(data.if_block)
|
||||
.and_then(|span| indent_of(cx, span))
|
||||
.unwrap_or(0);
|
||||
let to_annex = data.block_stmts[data.stmt_idx + 1..]
|
||||
.iter()
|
||||
.map(|stmt| original_sp(stmt.span, DUMMY_SP))
|
||||
.map(|span| snippet_block(ctx, span, "..").into_owned())
|
||||
.map(|span| {
|
||||
let snip = snippet_block(cx, span, "..", None).into_owned();
|
||||
snip.lines()
|
||||
.map(|line| format!("{}{}", " ".repeat(indent), line))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let mut ret = String::from(header);
|
||||
|
||||
ret.push_str(&if_code);
|
||||
ret.push_str("\n// Merged code follows...");
|
||||
ret.push_str(&to_annex);
|
||||
ret.push_str("\n}\n");
|
||||
ret
|
||||
let indent_if = indent_of(cx, data.if_expr.span).unwrap_or(0);
|
||||
format!(
|
||||
"{indent_if}if {} {}\n{indent}// merged code follows:\n{}\n{indent_if}}}",
|
||||
cond_code,
|
||||
block_code,
|
||||
to_annex,
|
||||
indent = " ".repeat(indent),
|
||||
indent_if = " ".repeat(indent_if),
|
||||
)
|
||||
}
|
||||
|
||||
fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) {
|
||||
fn check_and_warn<'a>(cx: &EarlyContext<'_>, expr: &'a ast::Expr) {
|
||||
with_loop_block(expr, |loop_block, label| {
|
||||
for (i, stmt) in loop_block.stmts.iter().enumerate() {
|
||||
with_if_expr(stmt, |if_expr, cond, then_block, else_expr| {
|
||||
|
@ -373,22 +376,22 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) {
|
|||
};
|
||||
if needless_continue_in_else(else_expr, label) {
|
||||
emit_warning(
|
||||
ctx,
|
||||
cx,
|
||||
data,
|
||||
DROP_ELSE_BLOCK_AND_MERGE_MSG,
|
||||
LintType::ContinueInsideElseBlock,
|
||||
);
|
||||
} else if is_first_block_stmt_continue(then_block, label) {
|
||||
emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock);
|
||||
emit_warning(cx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Eats at `s` from the end till a closing brace `}` is encountered, and then
|
||||
/// continues eating till a non-whitespace character is found.
|
||||
/// e.g., the string
|
||||
/// Eats at `s` from the end till a closing brace `}` is encountered, and then continues eating
|
||||
/// till a non-whitespace character is found. e.g., the string. If no closing `}` is present, the
|
||||
/// string will be preserved.
|
||||
///
|
||||
/// ```rust
|
||||
/// {
|
||||
|
@ -402,12 +405,9 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) {
|
|||
/// {
|
||||
/// let x = 5;
|
||||
/// ```
|
||||
///
|
||||
/// NOTE: when there is no closing brace in `s`, `s` is _not_ preserved, i.e.,
|
||||
/// an empty string will be returned in that case.
|
||||
#[must_use]
|
||||
pub fn erode_from_back(s: &str) -> String {
|
||||
let mut ret = String::from(s);
|
||||
fn erode_from_back(s: &str) -> String {
|
||||
let mut ret = s.to_string();
|
||||
while ret.pop().map_or(false, |c| c != '}') {}
|
||||
while let Some(c) = ret.pop() {
|
||||
if !c.is_whitespace() {
|
||||
|
@ -415,41 +415,48 @@ pub fn erode_from_back(s: &str) -> String {
|
|||
break;
|
||||
}
|
||||
}
|
||||
ret
|
||||
if ret.is_empty() {
|
||||
s.to_string()
|
||||
} else {
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Eats at `s` from the front by first skipping all leading whitespace. Then,
|
||||
/// any number of opening braces are eaten, followed by any number of newlines.
|
||||
/// e.g., the string
|
||||
///
|
||||
/// ```ignore
|
||||
/// {
|
||||
/// something();
|
||||
/// inside_a_block();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// is transformed to
|
||||
///
|
||||
/// ```ignore
|
||||
/// something();
|
||||
/// inside_a_block();
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn erode_from_front(s: &str) -> String {
|
||||
s.chars()
|
||||
.skip_while(|c| c.is_whitespace())
|
||||
.skip_while(|c| *c == '{')
|
||||
.skip_while(|c| *c == '\n')
|
||||
.collect::<String>()
|
||||
fn span_of_first_expr_in_block(block: &ast::Block) -> Option<Span> {
|
||||
block.stmts.iter().next().map(|stmt| stmt.span)
|
||||
}
|
||||
|
||||
/// If `s` contains the code for a block, delimited by braces, this function
|
||||
/// tries to get the contents of the block. If there is no closing brace
|
||||
/// present,
|
||||
/// an empty string is returned.
|
||||
#[must_use]
|
||||
pub fn erode_block(s: &str) -> String {
|
||||
erode_from_back(&erode_from_front(s))
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::erode_from_back;
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_erode_from_back() {
|
||||
let input = "\
|
||||
{
|
||||
let x = 5;
|
||||
let y = format!(\"{}\", 42);
|
||||
}";
|
||||
|
||||
let expected = "\
|
||||
{
|
||||
let x = 5;
|
||||
let y = format!(\"{}\", 42);";
|
||||
|
||||
let got = erode_from_back(input);
|
||||
assert_eq!(expected, got);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_erode_from_back_no_brace() {
|
||||
let input = "\
|
||||
let x = 5;
|
||||
let y = something();
|
||||
";
|
||||
let expected = input;
|
||||
let got = erode_from_back(input);
|
||||
assert_eq!(expected, got);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ use rustc_hir::Node;
|
|||
use rustc_hir::*;
|
||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use rustc_span::source_map::original_sp;
|
||||
use rustc_span::symbol::{self, kw, Symbol};
|
||||
use rustc_span::{BytePos, Pos, Span, DUMMY_SP};
|
||||
use smallvec::SmallVec;
|
||||
|
@ -533,19 +534,49 @@ pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
|||
cx.sess().source_map().span_to_snippet(span).ok()
|
||||
}
|
||||
|
||||
/// Converts a span (from a block) to a code snippet if available, otherwise use
|
||||
/// default.
|
||||
/// This trims the code of indentation, except for the first line. Use it for
|
||||
/// blocks or block-like
|
||||
/// Converts a span (from a block) to a code snippet if available, otherwise use default.
|
||||
///
|
||||
/// This trims the code of indentation, except for the first line. Use it for blocks or block-like
|
||||
/// things which need to be printed as such.
|
||||
///
|
||||
/// The `indent_relative_to` arg can be used, to provide a span, where the indentation of the
|
||||
/// resulting snippet of the given span.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// snippet_block(cx, expr.span, "..")
|
||||
/// snippet_block(cx, block.span, "..", None)
|
||||
/// // where, `block` is the block of the if expr
|
||||
/// if x {
|
||||
/// y;
|
||||
/// }
|
||||
/// // will return the snippet
|
||||
/// {
|
||||
/// y;
|
||||
/// }
|
||||
/// ```
|
||||
pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// snippet_block(cx, block.span, "..", Some(if_expr.span))
|
||||
/// // where, `block` is the block of the if expr
|
||||
/// if x {
|
||||
/// y;
|
||||
/// }
|
||||
/// // will return the snippet
|
||||
/// {
|
||||
/// y;
|
||||
/// } // aligned with `if`
|
||||
/// ```
|
||||
/// Note that the first line of the snippet always has 0 indentation.
|
||||
pub fn snippet_block<'a, T: LintContext>(
|
||||
cx: &T,
|
||||
span: Span,
|
||||
default: &'a str,
|
||||
indent_relative_to: Option<Span>,
|
||||
) -> Cow<'a, str> {
|
||||
let snip = snippet(cx, span, default);
|
||||
trim_multiline(snip, true)
|
||||
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
|
||||
trim_multiline(snip, true, indent)
|
||||
}
|
||||
|
||||
/// Same as `snippet_block`, but adapts the applicability level by the rules of
|
||||
|
@ -554,27 +585,73 @@ pub fn snippet_block_with_applicability<'a, T: LintContext>(
|
|||
cx: &T,
|
||||
span: Span,
|
||||
default: &'a str,
|
||||
indent_relative_to: Option<Span>,
|
||||
applicability: &mut Applicability,
|
||||
) -> Cow<'a, str> {
|
||||
let snip = snippet_with_applicability(cx, span, default, applicability);
|
||||
trim_multiline(snip, true)
|
||||
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
|
||||
trim_multiline(snip, true, indent)
|
||||
}
|
||||
|
||||
/// Returns a new Span that covers the full last line of the given Span
|
||||
pub fn last_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
|
||||
/// Returns a new Span that extends the original Span to the first non-whitespace char of the first
|
||||
/// line.
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let x = ();
|
||||
/// // ^^
|
||||
/// // will be converted to
|
||||
/// let x = ();
|
||||
/// // ^^^^^^^^^^
|
||||
/// ```
|
||||
pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
|
||||
if let Some(first_char_pos) = first_char_in_first_line(cx, span) {
|
||||
span.with_lo(first_char_pos)
|
||||
} else {
|
||||
span
|
||||
}
|
||||
}
|
||||
|
||||
fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> {
|
||||
let line_span = line_span(cx, span);
|
||||
if let Some(snip) = snippet_opt(cx, line_span) {
|
||||
snip.find(|c: char| !c.is_whitespace())
|
||||
.map(|pos| line_span.lo() + BytePos::from_usize(pos))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the indentation of the line of a span
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let x = ();
|
||||
/// // ^^ -- will return 0
|
||||
/// let x = ();
|
||||
/// // ^^ -- will return 4
|
||||
/// ```
|
||||
pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
|
||||
if let Some(snip) = snippet_opt(cx, line_span(cx, span)) {
|
||||
snip.find(|c: char| !c.is_whitespace())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Extends the span to the beginning of the spans line, incl. whitespaces.
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let x = ();
|
||||
/// // ^^
|
||||
/// // will be converted to
|
||||
/// let x = ();
|
||||
/// // ^^^^^^^^^^^^^^
|
||||
/// ```
|
||||
fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
|
||||
let span = original_sp(span, DUMMY_SP);
|
||||
let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
|
||||
let line_no = source_map_and_line.line;
|
||||
let line_start = &source_map_and_line.sf.lines[line_no];
|
||||
let span = Span::new(*line_start, span.hi(), span.ctxt());
|
||||
if_chain! {
|
||||
if let Some(snip) = snippet_opt(cx, span);
|
||||
if let Some(first_ch_pos) = snip.find(|c: char| !c.is_whitespace());
|
||||
then {
|
||||
span.with_lo(span.lo() + BytePos::from_usize(first_ch_pos))
|
||||
} else {
|
||||
span
|
||||
}
|
||||
}
|
||||
let line_start = source_map_and_line.sf.lines[line_no];
|
||||
Span::new(line_start, span.hi(), span.ctxt())
|
||||
}
|
||||
|
||||
/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
|
||||
|
@ -584,8 +661,9 @@ pub fn expr_block<'a, T: LintContext>(
|
|||
expr: &Expr<'_>,
|
||||
option: Option<String>,
|
||||
default: &'a str,
|
||||
indent_relative_to: Option<Span>,
|
||||
) -> Cow<'a, str> {
|
||||
let code = snippet_block(cx, expr.span, default);
|
||||
let code = snippet_block(cx, expr.span, default, indent_relative_to);
|
||||
let string = option.unwrap_or_default();
|
||||
if expr.span.from_expansion() {
|
||||
Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
|
||||
|
@ -600,14 +678,14 @@ pub fn expr_block<'a, T: LintContext>(
|
|||
|
||||
/// Trim indentation from a multiline string with possibility of ignoring the
|
||||
/// first line.
|
||||
pub fn trim_multiline(s: Cow<'_, str>, ignore_first: bool) -> Cow<'_, str> {
|
||||
let s_space = trim_multiline_inner(s, ignore_first, ' ');
|
||||
let s_tab = trim_multiline_inner(s_space, ignore_first, '\t');
|
||||
trim_multiline_inner(s_tab, ignore_first, ' ')
|
||||
fn trim_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>) -> Cow<'_, str> {
|
||||
let s_space = trim_multiline_inner(s, ignore_first, indent, ' ');
|
||||
let s_tab = trim_multiline_inner(s_space, ignore_first, indent, '\t');
|
||||
trim_multiline_inner(s_tab, ignore_first, indent, ' ')
|
||||
}
|
||||
|
||||
fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_, str> {
|
||||
let x = s
|
||||
fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>, ch: char) -> Cow<'_, str> {
|
||||
let mut x = s
|
||||
.lines()
|
||||
.skip(ignore_first as usize)
|
||||
.filter_map(|l| {
|
||||
|
@ -620,6 +698,9 @@ fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_
|
|||
})
|
||||
.min()
|
||||
.unwrap_or(0);
|
||||
if let Some(indent) = indent {
|
||||
x = x.saturating_sub(indent);
|
||||
}
|
||||
if x > 0 {
|
||||
Cow::Owned(
|
||||
s.lines()
|
||||
|
@ -1141,87 +1222,6 @@ pub fn is_normalizable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, param_env: ty::Para
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{trim_multiline, without_block_comments};
|
||||
|
||||
#[test]
|
||||
fn test_trim_multiline_single_line() {
|
||||
assert_eq!("", trim_multiline("".into(), false));
|
||||
assert_eq!("...", trim_multiline("...".into(), false));
|
||||
assert_eq!("...", trim_multiline(" ...".into(), false));
|
||||
assert_eq!("...", trim_multiline("\t...".into(), false));
|
||||
assert_eq!("...", trim_multiline("\t\t...".into(), false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_trim_multiline_block() {
|
||||
assert_eq!("\
|
||||
if x {
|
||||
y
|
||||
} else {
|
||||
z
|
||||
}", trim_multiline(" if x {
|
||||
y
|
||||
} else {
|
||||
z
|
||||
}".into(), false));
|
||||
assert_eq!("\
|
||||
if x {
|
||||
\ty
|
||||
} else {
|
||||
\tz
|
||||
}", trim_multiline(" if x {
|
||||
\ty
|
||||
} else {
|
||||
\tz
|
||||
}".into(), false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_trim_multiline_empty_line() {
|
||||
assert_eq!("\
|
||||
if x {
|
||||
y
|
||||
|
||||
} else {
|
||||
z
|
||||
}", trim_multiline(" if x {
|
||||
y
|
||||
|
||||
} else {
|
||||
z
|
||||
}".into(), false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_without_block_comments_lines_without_block_comments() {
|
||||
let result = without_block_comments(vec!["/*", "", "*/"]);
|
||||
println!("result: {:?}", result);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
|
||||
assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
|
||||
|
||||
let result = without_block_comments(vec!["/* rust", "", "*/"]);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["/* one-line comment */"]);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["foo", "bar", "baz"]);
|
||||
assert_eq!(result, vec!["foo", "bar", "baz"]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn match_def_path<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, did: DefId, syms: &[&str]) -> bool {
|
||||
let path = cx.get_def_path(did);
|
||||
path.len() == syms.len() && path.into_iter().zip(syms.iter()).all(|(a, &b)| a.as_str() == b)
|
||||
|
@ -1369,3 +1369,84 @@ pub fn is_trait_impl_item(cx: &LateContext<'_, '_>, hir_id: HirId) -> bool {
|
|||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{trim_multiline, without_block_comments};
|
||||
|
||||
#[test]
|
||||
fn test_trim_multiline_single_line() {
|
||||
assert_eq!("", trim_multiline("".into(), false, None));
|
||||
assert_eq!("...", trim_multiline("...".into(), false, None));
|
||||
assert_eq!("...", trim_multiline(" ...".into(), false, None));
|
||||
assert_eq!("...", trim_multiline("\t...".into(), false, None));
|
||||
assert_eq!("...", trim_multiline("\t\t...".into(), false, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_trim_multiline_block() {
|
||||
assert_eq!("\
|
||||
if x {
|
||||
y
|
||||
} else {
|
||||
z
|
||||
}", trim_multiline(" if x {
|
||||
y
|
||||
} else {
|
||||
z
|
||||
}".into(), false, None));
|
||||
assert_eq!("\
|
||||
if x {
|
||||
\ty
|
||||
} else {
|
||||
\tz
|
||||
}", trim_multiline(" if x {
|
||||
\ty
|
||||
} else {
|
||||
\tz
|
||||
}".into(), false, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_trim_multiline_empty_line() {
|
||||
assert_eq!("\
|
||||
if x {
|
||||
y
|
||||
|
||||
} else {
|
||||
z
|
||||
}", trim_multiline(" if x {
|
||||
y
|
||||
|
||||
} else {
|
||||
z
|
||||
}".into(), false, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_without_block_comments_lines_without_block_comments() {
|
||||
let result = without_block_comments(vec!["/*", "", "*/"]);
|
||||
println!("result: {:?}", result);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
|
||||
assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
|
||||
|
||||
let result = without_block_comments(vec!["/* rust", "", "*/"]);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["/* one-line comment */"]);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]);
|
||||
assert!(result.is_empty());
|
||||
|
||||
let result = without_block_comments(vec!["foo", "bar", "baz"]);
|
||||
assert_eq!(result, vec!["foo", "bar", "baz"]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
// Tests for the various helper functions used by the needless_continue
|
||||
// lint that don't belong in utils.
|
||||
|
||||
use clippy_lints::needless_continue::{erode_block, erode_from_back, erode_from_front};
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_erode_from_back() {
|
||||
let input = "\
|
||||
{
|
||||
let x = 5;
|
||||
let y = format!(\"{}\", 42);
|
||||
}";
|
||||
|
||||
let expected = "\
|
||||
{
|
||||
let x = 5;
|
||||
let y = format!(\"{}\", 42);";
|
||||
|
||||
let got = erode_from_back(input);
|
||||
assert_eq!(expected, got);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_erode_from_back_no_brace() {
|
||||
let input = "\
|
||||
let x = 5;
|
||||
let y = something();
|
||||
";
|
||||
let expected = "";
|
||||
let got = erode_from_back(input);
|
||||
assert_eq!(expected, got);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_erode_from_front() {
|
||||
let input = "
|
||||
{
|
||||
something();
|
||||
inside_a_block();
|
||||
}
|
||||
";
|
||||
let expected =
|
||||
" something();
|
||||
inside_a_block();
|
||||
}
|
||||
";
|
||||
let got = erode_from_front(input);
|
||||
println!("input: {}\nexpected:\n{}\ngot:\n{}", input, expected, got);
|
||||
assert_eq!(expected, got);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_erode_from_front_no_brace() {
|
||||
let input = "
|
||||
something();
|
||||
inside_a_block();
|
||||
";
|
||||
let expected =
|
||||
"something();
|
||||
inside_a_block();
|
||||
";
|
||||
let got = erode_from_front(input);
|
||||
println!("input: {}\nexpected:\n{}\ngot:\n{}", input, expected, got);
|
||||
assert_eq!(expected, got);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn test_erode_block() {
|
||||
|
||||
let input = "
|
||||
{
|
||||
something();
|
||||
inside_a_block();
|
||||
}
|
||||
";
|
||||
let expected =
|
||||
" something();
|
||||
inside_a_block();";
|
||||
let got = erode_block(input);
|
||||
println!("input: {}\nexpected:\n{}\ngot:\n{}", input, expected, got);
|
||||
assert_eq!(expected, got);
|
||||
}
|
75
tests/ui/block_in_if_condition.fixed
Normal file
75
tests/ui/block_in_if_condition.fixed
Normal file
|
@ -0,0 +1,75 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::block_in_if_condition_expr)]
|
||||
#![warn(clippy::block_in_if_condition_stmt)]
|
||||
#![allow(unused, clippy::let_and_return)]
|
||||
#![warn(clippy::nonminimal_bool)]
|
||||
|
||||
macro_rules! blocky {
|
||||
() => {{
|
||||
true
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! blocky_too {
|
||||
() => {{
|
||||
let r = true;
|
||||
r
|
||||
}};
|
||||
}
|
||||
|
||||
fn macro_if() {
|
||||
if blocky!() {}
|
||||
|
||||
if blocky_too!() {}
|
||||
}
|
||||
|
||||
fn condition_has_block() -> i32 {
|
||||
let res = {
|
||||
let x = 3;
|
||||
x == 3
|
||||
}; if res {
|
||||
6
|
||||
} else {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
fn condition_has_block_with_single_expression() -> i32 {
|
||||
if true {
|
||||
6
|
||||
} else {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
fn condition_is_normal() -> i32 {
|
||||
let x = 3;
|
||||
if x == 3 {
|
||||
6
|
||||
} else {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
fn condition_is_unsafe_block() {
|
||||
let a: i32 = 1;
|
||||
|
||||
// this should not warn because the condition is an unsafe block
|
||||
if unsafe { 1u32 == std::mem::transmute(a) } {
|
||||
println!("1u32 == a");
|
||||
}
|
||||
}
|
||||
|
||||
fn block_in_assert() {
|
||||
let opt = Some(42);
|
||||
assert!(opt
|
||||
.as_ref()
|
||||
.and_then(|val| {
|
||||
let mut v = val * 2;
|
||||
v -= 1;
|
||||
Some(v * 3)
|
||||
})
|
||||
.is_some());
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -1,3 +1,4 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::block_in_if_condition_expr)]
|
||||
#![warn(clippy::block_in_if_condition_stmt)]
|
||||
#![allow(unused, clippy::let_and_return)]
|
||||
|
@ -41,37 +42,6 @@ fn condition_has_block_with_single_expression() -> i32 {
|
|||
}
|
||||
}
|
||||
|
||||
fn predicate<F: FnOnce(T) -> bool, T>(pfn: F, val: T) -> bool {
|
||||
pfn(val)
|
||||
}
|
||||
|
||||
fn pred_test() {
|
||||
let v = 3;
|
||||
let sky = "blue";
|
||||
// This is a sneaky case, where the block isn't directly in the condition,
|
||||
// but is actually nside a closure that the condition is using.
|
||||
// The same principle applies -- add some extra expressions to make sure
|
||||
// linter isn't confused by them.
|
||||
if v == 3
|
||||
&& sky == "blue"
|
||||
&& predicate(
|
||||
|x| {
|
||||
let target = 3;
|
||||
x == target
|
||||
},
|
||||
v,
|
||||
)
|
||||
{}
|
||||
|
||||
if predicate(
|
||||
|x| {
|
||||
let target = 3;
|
||||
x == target
|
||||
},
|
||||
v,
|
||||
) {}
|
||||
}
|
||||
|
||||
fn condition_is_normal() -> i32 {
|
||||
let x = 3;
|
||||
if true && x == 3 {
|
||||
|
@ -81,10 +51,6 @@ fn condition_is_normal() -> i32 {
|
|||
}
|
||||
}
|
||||
|
||||
fn closure_without_block() {
|
||||
if predicate(|x| x == 3, 6) {}
|
||||
}
|
||||
|
||||
fn condition_is_unsafe_block() {
|
||||
let a: i32 = 1;
|
||||
|
||||
|
@ -94,16 +60,6 @@ fn condition_is_unsafe_block() {
|
|||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
fn macro_in_closure() {
|
||||
let option = Some(true);
|
||||
|
||||
if option.unwrap_or_else(|| unimplemented!()) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn block_in_assert() {
|
||||
let opt = Some(42);
|
||||
assert!(opt
|
||||
|
@ -115,3 +71,5 @@ fn block_in_assert() {
|
|||
})
|
||||
.is_some());
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,62 +1,36 @@
|
|||
error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
|
||||
--> $DIR/block_in_if_condition.rs:26:8
|
||||
--> $DIR/block_in_if_condition.rs:27:5
|
||||
|
|
||||
LL | if {
|
||||
| ________^
|
||||
LL | / if {
|
||||
LL | | let x = 3;
|
||||
LL | | x == 3
|
||||
LL | | } {
|
||||
| |_____^
|
||||
|
|
||||
= note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings`
|
||||
= help: try
|
||||
let res = {
|
||||
let x = 3;
|
||||
x == 3
|
||||
};
|
||||
if res {
|
||||
6
|
||||
} ...
|
||||
help: try
|
||||
|
|
||||
LL | let res = {
|
||||
LL | let x = 3;
|
||||
LL | x == 3
|
||||
LL | }; if res {
|
||||
|
|
||||
|
||||
error: omit braces around single expression condition
|
||||
--> $DIR/block_in_if_condition.rs:37:8
|
||||
--> $DIR/block_in_if_condition.rs:38:8
|
||||
|
|
||||
LL | if { true } {
|
||||
| ^^^^^^^^
|
||||
| ^^^^^^^^ help: try: `true`
|
||||
|
|
||||
= note: `-D clippy::block-in-if-condition-expr` implied by `-D warnings`
|
||||
= help: try
|
||||
if true {
|
||||
6
|
||||
} ...
|
||||
|
||||
error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
|
||||
--> $DIR/block_in_if_condition.rs:58:17
|
||||
|
|
||||
LL | |x| {
|
||||
| _________________^
|
||||
LL | | let target = 3;
|
||||
LL | | x == target
|
||||
LL | | },
|
||||
| |_____________^
|
||||
|
||||
error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
|
||||
--> $DIR/block_in_if_condition.rs:67:13
|
||||
|
|
||||
LL | |x| {
|
||||
| _____________^
|
||||
LL | | let target = 3;
|
||||
LL | | x == target
|
||||
LL | | },
|
||||
| |_________^
|
||||
|
||||
error: this boolean expression can be simplified
|
||||
--> $DIR/block_in_if_condition.rs:77:8
|
||||
--> $DIR/block_in_if_condition.rs:47:8
|
||||
|
|
||||
LL | if true && x == 3 {
|
||||
| ^^^^^^^^^^^^^^ help: try: `x == 3`
|
||||
|
|
||||
= note: `-D clippy::nonminimal-bool` implied by `-D warnings`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
48
tests/ui/block_in_if_condition_closure.rs
Normal file
48
tests/ui/block_in_if_condition_closure.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
#![warn(clippy::block_in_if_condition_expr)]
|
||||
#![warn(clippy::block_in_if_condition_stmt)]
|
||||
#![allow(unused, clippy::let_and_return)]
|
||||
|
||||
fn predicate<F: FnOnce(T) -> bool, T>(pfn: F, val: T) -> bool {
|
||||
pfn(val)
|
||||
}
|
||||
|
||||
fn pred_test() {
|
||||
let v = 3;
|
||||
let sky = "blue";
|
||||
// This is a sneaky case, where the block isn't directly in the condition,
|
||||
// but is actually nside a closure that the condition is using.
|
||||
// The same principle applies -- add some extra expressions to make sure
|
||||
// linter isn't confused by them.
|
||||
if v == 3
|
||||
&& sky == "blue"
|
||||
&& predicate(
|
||||
|x| {
|
||||
let target = 3;
|
||||
x == target
|
||||
},
|
||||
v,
|
||||
)
|
||||
{}
|
||||
|
||||
if predicate(
|
||||
|x| {
|
||||
let target = 3;
|
||||
x == target
|
||||
},
|
||||
v,
|
||||
) {}
|
||||
}
|
||||
|
||||
fn closure_without_block() {
|
||||
if predicate(|x| x == 3, 6) {}
|
||||
}
|
||||
|
||||
fn macro_in_closure() {
|
||||
let option = Some(true);
|
||||
|
||||
if option.unwrap_or_else(|| unimplemented!()) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
24
tests/ui/block_in_if_condition_closure.stderr
Normal file
24
tests/ui/block_in_if_condition_closure.stderr
Normal file
|
@ -0,0 +1,24 @@
|
|||
error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
|
||||
--> $DIR/block_in_if_condition_closure.rs:19:17
|
||||
|
|
||||
LL | |x| {
|
||||
| _________________^
|
||||
LL | | let target = 3;
|
||||
LL | | x == target
|
||||
LL | | },
|
||||
| |_____________^
|
||||
|
|
||||
= note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings`
|
||||
|
||||
error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
|
||||
--> $DIR/block_in_if_condition_closure.rs:28:13
|
||||
|
|
||||
LL | |x| {
|
||||
| _____________^
|
||||
LL | | let target = 3;
|
||||
LL | | x == target
|
||||
LL | | },
|
||||
| |_________^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -10,57 +10,57 @@ fn main() {
|
|||
if x == "hello" {
|
||||
print!("Hello ");
|
||||
} else if y == "world" {
|
||||
println!("world!")
|
||||
}
|
||||
println!("world!")
|
||||
}
|
||||
|
||||
if x == "hello" {
|
||||
print!("Hello ");
|
||||
} else if let Some(42) = Some(42) {
|
||||
println!("world!")
|
||||
}
|
||||
println!("world!")
|
||||
}
|
||||
|
||||
if x == "hello" {
|
||||
print!("Hello ");
|
||||
} else if y == "world" {
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
|
||||
if x == "hello" {
|
||||
print!("Hello ");
|
||||
} else if let Some(42) = Some(42) {
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
|
||||
if let Some(42) = Some(42) {
|
||||
print!("Hello ");
|
||||
} else if let Some(42) = Some(42) {
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
|
||||
if let Some(42) = Some(42) {
|
||||
print!("Hello ");
|
||||
} else if x == "hello" {
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
|
||||
if let Some(42) = Some(42) {
|
||||
print!("Hello ");
|
||||
} else if let Some(42) = Some(42) {
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
println!("world")
|
||||
}
|
||||
else {
|
||||
println!("!")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | } else if y == "world" {
|
||||
LL | println!("world!")
|
||||
LL | }
|
||||
LL | println!("world!")
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `else { if .. }` block can be collapsed
|
||||
|
@ -31,8 +31,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | } else if let Some(42) = Some(42) {
|
||||
LL | println!("world!")
|
||||
LL | }
|
||||
LL | println!("world!")
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `else { if .. }` block can be collapsed
|
||||
|
@ -51,11 +51,11 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | } else if y == "world" {
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `else { if .. }` block can be collapsed
|
||||
|
@ -74,11 +74,11 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | } else if let Some(42) = Some(42) {
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `else { if .. }` block can be collapsed
|
||||
|
@ -97,11 +97,11 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | } else if let Some(42) = Some(42) {
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `else { if .. }` block can be collapsed
|
||||
|
@ -120,11 +120,11 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | } else if x == "hello" {
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `else { if .. }` block can be collapsed
|
||||
|
@ -143,11 +143,11 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | } else if let Some(42) = Some(42) {
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
LL | println!("world")
|
||||
LL | }
|
||||
LL | else {
|
||||
LL | println!("!")
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
|
|
@ -7,28 +7,28 @@ fn main() {
|
|||
let x = "hello";
|
||||
let y = "world";
|
||||
if x == "hello" && y == "world" {
|
||||
println!("Hello world!");
|
||||
}
|
||||
println!("Hello world!");
|
||||
}
|
||||
|
||||
if (x == "hello" || x == "world") && (y == "world" || y == "hello") {
|
||||
println!("Hello world!");
|
||||
}
|
||||
println!("Hello world!");
|
||||
}
|
||||
|
||||
if x == "hello" && x == "world" && (y == "world" || y == "hello") {
|
||||
println!("Hello world!");
|
||||
}
|
||||
println!("Hello world!");
|
||||
}
|
||||
|
||||
if (x == "hello" || x == "world") && y == "world" && y == "hello" {
|
||||
println!("Hello world!");
|
||||
}
|
||||
println!("Hello world!");
|
||||
}
|
||||
|
||||
if x == "hello" && x == "world" && y == "world" && y == "hello" {
|
||||
println!("Hello world!");
|
||||
}
|
||||
println!("Hello world!");
|
||||
}
|
||||
|
||||
if 42 == 1337 && 'a' != 'A' {
|
||||
println!("world!")
|
||||
}
|
||||
println!("world!")
|
||||
}
|
||||
|
||||
// Works because any if with an else statement cannot be collapsed.
|
||||
if x == "hello" {
|
||||
|
@ -81,8 +81,8 @@ fn main() {
|
|||
}
|
||||
|
||||
if x == "hello" && y == "world" { // Collapsible
|
||||
println!("Hello world!");
|
||||
}
|
||||
println!("Hello world!");
|
||||
}
|
||||
|
||||
if x == "hello" {
|
||||
print!("Hello ");
|
||||
|
|
|
@ -12,8 +12,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | if x == "hello" && y == "world" {
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `if` statement can be collapsed
|
||||
|
@ -29,8 +29,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | if (x == "hello" || x == "world") && (y == "world" || y == "hello") {
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `if` statement can be collapsed
|
||||
|
@ -46,8 +46,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | if x == "hello" && x == "world" && (y == "world" || y == "hello") {
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `if` statement can be collapsed
|
||||
|
@ -63,8 +63,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | if (x == "hello" || x == "world") && y == "world" && y == "hello" {
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `if` statement can be collapsed
|
||||
|
@ -80,8 +80,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | if x == "hello" && x == "world" && y == "world" && y == "hello" {
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `if` statement can be collapsed
|
||||
|
@ -97,8 +97,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | if 42 == 1337 && 'a' != 'A' {
|
||||
LL | println!("world!")
|
||||
LL | }
|
||||
LL | println!("world!")
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this `if` statement can be collapsed
|
||||
|
@ -114,8 +114,8 @@ LL | | }
|
|||
help: try
|
||||
|
|
||||
LL | if x == "hello" && y == "world" { // Collapsible
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
LL | println!("Hello world!");
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
|
|
@ -40,8 +40,8 @@ LL | | };
|
|||
help: consider using an `if`/`else` expression
|
||||
|
|
||||
LL | if !test {
|
||||
LL | println!("Noooo!");
|
||||
LL | };
|
||||
LL | println!("Noooo!");
|
||||
LL | };
|
||||
|
|
||||
|
||||
error: you seem to be trying to match on a boolean expression
|
||||
|
@ -58,8 +58,8 @@ LL | | };
|
|||
help: consider using an `if`/`else` expression
|
||||
|
|
||||
LL | if !test {
|
||||
LL | println!("Noooo!");
|
||||
LL | };
|
||||
LL | println!("Noooo!");
|
||||
LL | };
|
||||
|
|
||||
|
||||
error: you seem to be trying to match on a boolean expression
|
||||
|
@ -76,8 +76,8 @@ LL | | };
|
|||
help: consider using an `if`/`else` expression
|
||||
|
|
||||
LL | if !(test && test) {
|
||||
LL | println!("Noooo!");
|
||||
LL | };
|
||||
LL | println!("Noooo!");
|
||||
LL | };
|
||||
|
|
||||
|
||||
error: equal expressions as operands to `&&`
|
||||
|
@ -103,10 +103,10 @@ LL | | };
|
|||
help: consider using an `if`/`else` expression
|
||||
|
|
||||
LL | if test {
|
||||
LL | println!("Yes!");
|
||||
LL | } else {
|
||||
LL | println!("Noooo!");
|
||||
LL | };
|
||||
LL | println!("Yes!");
|
||||
LL | } else {
|
||||
LL | println!("Noooo!");
|
||||
LL | };
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
|
|
@ -14,12 +14,12 @@ fn main() {
|
|||
let c = 3;
|
||||
// Lint
|
||||
let (x, y, z) = (a, b, c);
|
||||
{
|
||||
println!("{} {} {}", x, y, z);
|
||||
}
|
||||
{
|
||||
println!("{} {} {}", x, y, z);
|
||||
}
|
||||
// Lint
|
||||
let (x, y, z) = (a, b, c);
|
||||
println!("{} {} {}", x, y, z);
|
||||
println!("{} {} {}", x, y, z);
|
||||
// Ok
|
||||
match a {
|
||||
2 => println!("2"),
|
||||
|
@ -35,29 +35,29 @@ println!("{} {} {}", x, y, z);
|
|||
println!("whatever");
|
||||
// Lint
|
||||
{
|
||||
let x = 29;
|
||||
println!("x has a value of {}", x);
|
||||
}
|
||||
let x = 29;
|
||||
println!("x has a value of {}", x);
|
||||
}
|
||||
// Lint
|
||||
{
|
||||
let e = 5 * a;
|
||||
if e >= 5 {
|
||||
println!("e is superior to 5");
|
||||
let e = 5 * a;
|
||||
if e >= 5 {
|
||||
println!("e is superior to 5");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Lint
|
||||
let p = Point { x: 0, y: 7 };
|
||||
let Point { x, y } = p;
|
||||
println!("Coords: ({}, {})", x, y);
|
||||
println!("Coords: ({}, {})", x, y);
|
||||
// Lint
|
||||
let Point { x: x1, y: y1 } = p;
|
||||
println!("Coords: ({}, {})", x1, y1);
|
||||
println!("Coords: ({}, {})", x1, y1);
|
||||
// Lint
|
||||
let x = 5;
|
||||
let ref r = x;
|
||||
println!("Got a reference to {}", r);
|
||||
println!("Got a reference to {}", r);
|
||||
// Lint
|
||||
let mut x = 5;
|
||||
let ref mut mr = x;
|
||||
println!("Got a mutable reference to {}", mr);
|
||||
println!("Got a mutable reference to {}", mr);
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ LL | | }
|
|||
help: consider using `let` statement
|
||||
|
|
||||
LL | let (x, y, z) = (a, b, c);
|
||||
LL | {
|
||||
LL | println!("{} {} {}", x, y, z);
|
||||
LL | }
|
||||
LL | {
|
||||
LL | println!("{} {} {}", x, y, z);
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this match could be written as a `let` statement
|
||||
|
@ -28,7 +28,7 @@ LL | | }
|
|||
help: consider using `let` statement
|
||||
|
|
||||
LL | let (x, y, z) = (a, b, c);
|
||||
LL | println!("{} {} {}", x, y, z);
|
||||
LL | println!("{} {} {}", x, y, z);
|
||||
|
|
||||
|
||||
error: this match could be replaced by its body itself
|
||||
|
@ -53,9 +53,9 @@ LL | | }
|
|||
help: consider using the match body instead
|
||||
|
|
||||
LL | {
|
||||
LL | let x = 29;
|
||||
LL | println!("x has a value of {}", x);
|
||||
LL | }
|
||||
LL | let x = 29;
|
||||
LL | println!("x has a value of {}", x);
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this match could be replaced by its body itself
|
||||
|
@ -73,11 +73,11 @@ LL | | }
|
|||
help: consider using the match body instead
|
||||
|
|
||||
LL | {
|
||||
LL | let e = 5 * a;
|
||||
LL | if e >= 5 {
|
||||
LL | println!("e is superior to 5");
|
||||
LL | let e = 5 * a;
|
||||
LL | if e >= 5 {
|
||||
LL | println!("e is superior to 5");
|
||||
LL | }
|
||||
LL | }
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: this match could be written as a `let` statement
|
||||
|
@ -91,7 +91,7 @@ LL | | }
|
|||
help: consider using `let` statement
|
||||
|
|
||||
LL | let Point { x, y } = p;
|
||||
LL | println!("Coords: ({}, {})", x, y);
|
||||
LL | println!("Coords: ({}, {})", x, y);
|
||||
|
|
||||
|
||||
error: this match could be written as a `let` statement
|
||||
|
@ -105,7 +105,7 @@ LL | | }
|
|||
help: consider using `let` statement
|
||||
|
|
||||
LL | let Point { x: x1, y: y1 } = p;
|
||||
LL | println!("Coords: ({}, {})", x1, y1);
|
||||
LL | println!("Coords: ({}, {})", x1, y1);
|
||||
|
|
||||
|
||||
error: this match could be written as a `let` statement
|
||||
|
@ -119,7 +119,7 @@ LL | | }
|
|||
help: consider using `let` statement
|
||||
|
|
||||
LL | let ref r = x;
|
||||
LL | println!("Got a reference to {}", r);
|
||||
LL | println!("Got a reference to {}", r);
|
||||
|
|
||||
|
||||
error: this match could be written as a `let` statement
|
||||
|
@ -133,7 +133,7 @@ LL | | }
|
|||
help: consider using `let` statement
|
||||
|
|
||||
LL | let ref mut mr = x;
|
||||
LL | println!("Got a mutable reference to {}", mr);
|
||||
LL | println!("Got a mutable reference to {}", mr);
|
||||
|
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
error: This `else` block is redundant.
|
||||
|
||||
error: this `else` block is redundant
|
||||
--> $DIR/needless_continue.rs:28:16
|
||||
|
|
||||
LL | } else {
|
||||
|
@ -9,34 +8,33 @@ LL | | }
|
|||
| |_________^
|
||||
|
|
||||
= note: `-D clippy::needless-continue` implied by `-D warnings`
|
||||
= help: Consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block, like so:
|
||||
if i % 2 == 0 && i % 3 == 0 {
|
||||
println!("{}", i);
|
||||
println!("{}", i + 1);
|
||||
if i % 5 == 0 {
|
||||
println!("{}", i + 2);
|
||||
}
|
||||
let i = 0;
|
||||
println!("bar {} ", i);
|
||||
// Merged code follows...println!("bleh");
|
||||
{
|
||||
println!("blah");
|
||||
}
|
||||
if !(!(i == 2) || !(i == 5)) {
|
||||
println!("lama");
|
||||
}
|
||||
if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
|
||||
continue;
|
||||
} else {
|
||||
println!("Blabber");
|
||||
println!("Jabber");
|
||||
}
|
||||
println!("bleh");
|
||||
}
|
||||
|
||||
|
||||
error: There is no need for an explicit `else` block for this `if` expression
|
||||
= help: consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block
|
||||
if i % 2 == 0 && i % 3 == 0 {
|
||||
println!("{}", i);
|
||||
println!("{}", i + 1);
|
||||
if i % 5 == 0 {
|
||||
println!("{}", i + 2);
|
||||
}
|
||||
let i = 0;
|
||||
println!("bar {} ", i);
|
||||
// merged code follows:
|
||||
println!("bleh");
|
||||
{
|
||||
println!("blah");
|
||||
}
|
||||
if !(!(i == 2) || !(i == 5)) {
|
||||
println!("lama");
|
||||
}
|
||||
if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
|
||||
continue;
|
||||
} else {
|
||||
println!("Blabber");
|
||||
println!("Jabber");
|
||||
}
|
||||
println!("bleh");
|
||||
}
|
||||
|
||||
error: there is no need for an explicit `else` block for this `if` expression
|
||||
--> $DIR/needless_continue.rs:43:9
|
||||
|
|
||||
LL | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
|
||||
|
@ -47,16 +45,16 @@ LL | | println!("Jabber");
|
|||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
= help: Consider dropping the `else` clause, and moving out the code in the `else` block, like so:
|
||||
if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
|
||||
continue;
|
||||
}
|
||||
println!("Blabber");
|
||||
println!("Jabber");
|
||||
...
|
||||
|
||||
error: This `else` block is redundant.
|
||||
= help: consider dropping the `else` clause
|
||||
if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
|
||||
continue;
|
||||
}
|
||||
{
|
||||
println!("Blabber");
|
||||
println!("Jabber");
|
||||
}
|
||||
|
||||
error: this `else` block is redundant
|
||||
--> $DIR/needless_continue.rs:100:24
|
||||
|
|
||||
LL | } else {
|
||||
|
@ -65,22 +63,21 @@ LL | | continue 'inner; // should lint here
|
|||
LL | | }
|
||||
| |_________________^
|
||||
|
|
||||
= help: Consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block, like so:
|
||||
if condition() {
|
||||
println!("bar-3");
|
||||
// Merged code follows...println!("bar-4");
|
||||
update_condition();
|
||||
if condition() {
|
||||
continue; // should lint here
|
||||
} else {
|
||||
println!("bar-5");
|
||||
}
|
||||
println!("bar-6");
|
||||
}
|
||||
|
||||
|
||||
error: There is no need for an explicit `else` block for this `if` expression
|
||||
= help: consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block
|
||||
if condition() {
|
||||
println!("bar-3");
|
||||
// merged code follows:
|
||||
println!("bar-4");
|
||||
update_condition();
|
||||
if condition() {
|
||||
continue; // should lint here
|
||||
} else {
|
||||
println!("bar-5");
|
||||
}
|
||||
println!("bar-6");
|
||||
}
|
||||
|
||||
error: there is no need for an explicit `else` block for this `if` expression
|
||||
--> $DIR/needless_continue.rs:106:17
|
||||
|
|
||||
LL | / if condition() {
|
||||
|
@ -90,12 +87,13 @@ LL | | println!("bar-5");
|
|||
LL | | }
|
||||
| |_________________^
|
||||
|
|
||||
= help: Consider dropping the `else` clause, and moving out the code in the `else` block, like so:
|
||||
if condition() {
|
||||
continue;
|
||||
}
|
||||
println!("bar-5");
|
||||
...
|
||||
= help: consider dropping the `else` clause
|
||||
if condition() {
|
||||
continue; // should lint here
|
||||
}
|
||||
{
|
||||
println!("bar-5");
|
||||
}
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ LL | | };
|
|||
help: try this
|
||||
|
|
||||
LL | if let Some(y) = x {
|
||||
LL | println!("{:?}", y);
|
||||
LL | };
|
||||
LL | println!("{:?}", y);
|
||||
LL | };
|
||||
|
|
||||
|
||||
error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
|
||||
|
|
|
@ -14,9 +14,9 @@ LL | | }
|
|||
help: try this
|
||||
|
|
||||
LL | if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else {
|
||||
LL | let x = 5;
|
||||
LL | None
|
||||
LL | }
|
||||
LL | let x = 5;
|
||||
LL | None
|
||||
LL | }
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
Loading…
Add table
Reference in a new issue