Skip to content

Commit ebb0ff6

Browse files
committed
Merge remote-tracking branch 'upstream/master' into rustup
2 parents c586717 + da27c97 commit ebb0ff6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+743
-293
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4946,6 +4946,7 @@ Released 2018-09-13
49464946
[`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints
49474947
[`block_in_if_condition_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_expr
49484948
[`block_in_if_condition_stmt`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_stmt
4949+
[`blocks_in_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_conditions
49494950
[`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions
49504951
[`bool_assert_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison
49514952
[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
@@ -5462,6 +5463,7 @@ Released 2018-09-13
54625463
[`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns
54635464
[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
54645465
[`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
5466+
[`repeat_vec_with_capacity`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_vec_with_capacity
54655467
[`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
54665468
[`reserve_after_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#reserve_after_initialization
54675469
[`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
2+
use clippy_utils::source::snippet_block_with_applicability;
3+
use clippy_utils::ty::implements_trait;
4+
use clippy_utils::visitors::{for_each_expr, Descend};
5+
use clippy_utils::{get_parent_expr, higher};
6+
use core::ops::ControlFlow;
7+
use rustc_errors::Applicability;
8+
use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource};
9+
use rustc_lint::{LateContext, LateLintPass, LintContext};
10+
use rustc_middle::lint::in_external_macro;
11+
use rustc_session::declare_lint_pass;
12+
use rustc_span::sym;
13+
14+
declare_clippy_lint! {
15+
/// ### What it does
16+
/// Checks for `if` conditions that use blocks containing an
17+
/// expression, statements or conditions that use closures with blocks.
18+
///
19+
/// ### Why is this bad?
20+
/// Style, using blocks in the condition makes it hard to read.
21+
///
22+
/// ### Examples
23+
/// ```no_run
24+
/// # fn somefunc() -> bool { true };
25+
/// if { true } { /* ... */ }
26+
///
27+
/// if { let x = somefunc(); x } { /* ... */ }
28+
/// ```
29+
///
30+
/// Use instead:
31+
/// ```no_run
32+
/// # fn somefunc() -> bool { true };
33+
/// if true { /* ... */ }
34+
///
35+
/// let res = { let x = somefunc(); x };
36+
/// if res { /* ... */ }
37+
/// ```
38+
#[clippy::version = "1.45.0"]
39+
pub BLOCKS_IN_CONDITIONS,
40+
style,
41+
"useless or complex blocks that can be eliminated in conditions"
42+
}
43+
44+
declare_lint_pass!(BlocksInConditions => [BLOCKS_IN_CONDITIONS]);
45+
46+
const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition";
47+
48+
impl<'tcx> LateLintPass<'tcx> for BlocksInConditions {
49+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
50+
if in_external_macro(cx.sess(), expr.span) {
51+
return;
52+
}
53+
54+
let Some((cond, keyword, desc)) = higher::If::hir(expr)
55+
.map(|hif| (hif.cond, "if", "an `if` condition"))
56+
.or(if let ExprKind::Match(match_ex, _, MatchSource::Normal) = expr.kind {
57+
Some((match_ex, "match", "a `match` scrutinee"))
58+
} else {
59+
None
60+
})
61+
else {
62+
return;
63+
};
64+
let complex_block_message = &format!(
65+
"in {desc}, avoid complex blocks or closures with blocks; \
66+
instead, move the block or closure higher and bind it with a `let`",
67+
);
68+
69+
if let ExprKind::Block(block, _) = &cond.kind {
70+
if block.rules == BlockCheckMode::DefaultBlock {
71+
if block.stmts.is_empty() {
72+
if let Some(ex) = &block.expr {
73+
// don't dig into the expression here, just suggest that they remove
74+
// the block
75+
if expr.span.from_expansion() || ex.span.from_expansion() {
76+
return;
77+
}
78+
let mut applicability = Applicability::MachineApplicable;
79+
span_lint_and_sugg(
80+
cx,
81+
BLOCKS_IN_CONDITIONS,
82+
cond.span,
83+
BRACED_EXPR_MESSAGE,
84+
"try",
85+
snippet_block_with_applicability(cx, ex.span, "..", Some(expr.span), &mut applicability)
86+
.to_string(),
87+
applicability,
88+
);
89+
}
90+
} else {
91+
let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
92+
if span.from_expansion() || expr.span.from_expansion() {
93+
return;
94+
}
95+
// move block higher
96+
let mut applicability = Applicability::MachineApplicable;
97+
span_lint_and_sugg(
98+
cx,
99+
BLOCKS_IN_CONDITIONS,
100+
expr.span.with_hi(cond.span.hi()),
101+
complex_block_message,
102+
"try",
103+
format!(
104+
"let res = {}; {keyword} res",
105+
snippet_block_with_applicability(cx, block.span, "..", Some(expr.span), &mut applicability),
106+
),
107+
applicability,
108+
);
109+
}
110+
}
111+
} else {
112+
let _: Option<!> = for_each_expr(cond, |e| {
113+
if let ExprKind::Closure(closure) = e.kind {
114+
// do not lint if the closure is called using an iterator (see #1141)
115+
if let Some(parent) = get_parent_expr(cx, e)
116+
&& let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind
117+
&& let caller = cx.typeck_results().expr_ty(self_arg)
118+
&& let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
119+
&& implements_trait(cx, caller, iter_id, &[])
120+
{
121+
return ControlFlow::Continue(Descend::No);
122+
}
123+
124+
let body = cx.tcx.hir().body(closure.body);
125+
let ex = &body.value;
126+
if let ExprKind::Block(block, _) = ex.kind {
127+
if !body.value.span.from_expansion() && !block.stmts.is_empty() {
128+
span_lint(cx, BLOCKS_IN_CONDITIONS, ex.span, complex_block_message);
129+
return ControlFlow::Continue(Descend::No);
130+
}
131+
}
132+
}
133+
ControlFlow::Continue(Descend::Yes)
134+
});
135+
}
136+
}
137+
}

clippy_lints/src/blocks_in_if_conditions.rs

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

clippy_lints/src/declared_lints.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
6363
crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
6464
crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,
6565
crate::await_holding_invalid::AWAIT_HOLDING_REFCELL_REF_INFO,
66-
crate::blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS_INFO,
66+
crate::blocks_in_conditions::BLOCKS_IN_CONDITIONS_INFO,
6767
crate::bool_assert_comparison::BOOL_ASSERT_COMPARISON_INFO,
6868
crate::bool_to_int_with_if::BOOL_TO_INT_WITH_IF_INFO,
6969
crate::booleans::NONMINIMAL_BOOL_INFO,
@@ -598,6 +598,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
598598
crate::reference::DEREF_ADDROF_INFO,
599599
crate::regex::INVALID_REGEX_INFO,
600600
crate::regex::TRIVIAL_REGEX_INFO,
601+
crate::repeat_vec_with_capacity::REPEAT_VEC_WITH_CAPACITY_INFO,
601602
crate::reserve_after_initialization::RESERVE_AFTER_INITIALIZATION_INFO,
602603
crate::return_self_not_must_use::RETURN_SELF_NOT_MUST_USE_INFO,
603604
crate::returns::LET_AND_RETURN_INFO,

clippy_lints/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ mod assertions_on_result_states;
7474
mod async_yields_async;
7575
mod attrs;
7676
mod await_holding_invalid;
77-
mod blocks_in_if_conditions;
77+
mod blocks_in_conditions;
7878
mod bool_assert_comparison;
7979
mod bool_to_int_with_if;
8080
mod booleans;
@@ -289,6 +289,7 @@ mod ref_option_ref;
289289
mod ref_patterns;
290290
mod reference;
291291
mod regex;
292+
mod repeat_vec_with_capacity;
292293
mod reserve_after_initialization;
293294
mod return_self_not_must_use;
294295
mod returns;
@@ -653,7 +654,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
653654
store.register_late_pass(|_| Box::<significant_drop_tightening::SignificantDropTightening<'_>>::default());
654655
store.register_late_pass(|_| Box::new(len_zero::LenZero));
655656
store.register_late_pass(|_| Box::new(attrs::Attributes));
656-
store.register_late_pass(|_| Box::new(blocks_in_if_conditions::BlocksInIfConditions));
657+
store.register_late_pass(|_| Box::new(blocks_in_conditions::BlocksInConditions));
657658
store.register_late_pass(|_| Box::new(unicode::Unicode));
658659
store.register_late_pass(|_| Box::new(uninit_vec::UninitVec));
659660
store.register_late_pass(|_| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
@@ -1069,6 +1070,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
10691070
store.register_late_pass(|_| Box::new(iter_without_into_iter::IterWithoutIntoIter));
10701071
store.register_late_pass(|_| Box::new(iter_over_hash_type::IterOverHashType));
10711072
store.register_late_pass(|_| Box::new(impl_hash_with_borrow_str_and_bytes::ImplHashWithBorrowStrBytes));
1073+
store.register_late_pass(|_| Box::new(repeat_vec_with_capacity::RepeatVecWithCapacity));
10721074
// add lints here, do not remove this comment, it's used in `new_lint`
10731075
}
10741076

clippy_lints/src/macro_use.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ struct PathAndSpan {
3636
span: Span,
3737
}
3838

39-
/// `MacroRefData` includes the name of the macro.
39+
/// `MacroRefData` includes the name of the macro
40+
/// and the path from `SourceMap::span_to_filename`.
4041
#[derive(Debug, Clone)]
4142
pub struct MacroRefData {
4243
name: String,

clippy_lints/src/manual_string_new.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,16 @@ fn parse_call(cx: &LateContext<'_>, span: Span, func: &Expr<'_>, args: &[Expr<'_
108108

109109
let arg_kind = &args[0].kind;
110110
if let ExprKind::Path(qpath) = &func.kind {
111-
if let QPath::TypeRelative(_, _) = qpath {
112-
// String::from(...) or String::try_from(...)
113-
if let QPath::TypeRelative(ty, path_seg) = qpath
114-
&& [sym::from, sym::try_from].contains(&path_seg.ident.name)
115-
&& let TyKind::Path(qpath) = &ty.kind
116-
&& let QPath::Resolved(_, path) = qpath
117-
&& let [path_seg] = path.segments
118-
&& path_seg.ident.name == sym::String
119-
&& is_expr_kind_empty_str(arg_kind)
120-
{
121-
warn_then_suggest(cx, span);
122-
}
111+
// String::from(...) or String::try_from(...)
112+
if let QPath::TypeRelative(ty, path_seg) = qpath
113+
&& [sym::from, sym::try_from].contains(&path_seg.ident.name)
114+
&& let TyKind::Path(qpath) = &ty.kind
115+
&& let QPath::Resolved(_, path) = qpath
116+
&& let [path_seg] = path.segments
117+
&& path_seg.ident.name == sym::String
118+
&& is_expr_kind_empty_str(arg_kind)
119+
{
120+
warn_then_suggest(cx, span);
123121
} else if let QPath::Resolved(_, path) = qpath {
124122
// From::from(...) or TryFrom::try_from(...)
125123
if let [path_seg1, path_seg2] = path.segments

clippy_lints/src/methods/unnecessary_sort_by.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use clippy_utils::ty::implements_trait;
55
use rustc_errors::Applicability;
66
use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath};
77
use rustc_lint::LateContext;
8-
use rustc_middle::ty::{self, GenericArgKind};
8+
use rustc_middle::ty;
9+
use rustc_middle::ty::GenericArgKind;
910
use rustc_span::sym;
1011
use rustc_span::symbol::Ident;
1112
use std::iter;

0 commit comments

Comments
 (0)