Skip to content

Commit 15431b3

Browse files
authored
Merge branch 'master' into mul-add-negative
2 parents 7747032 + 2be6c4a commit 15431b3

File tree

116 files changed

+1875
-1377
lines changed

Some content is hidden

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

116 files changed

+1875
-1377
lines changed

clippy_dev/src/update_lints.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@ fn generate_lint_files(
4545
renamed_lints: &[RenamedLint],
4646
) {
4747
let internal_lints = Lint::internal_lints(lints);
48-
let usable_lints = Lint::usable_lints(lints);
49-
let mut sorted_usable_lints = usable_lints.clone();
50-
sorted_usable_lints.sort_by_key(|lint| lint.name.clone());
48+
let mut usable_lints = Lint::usable_lints(lints);
49+
usable_lints.sort_by_key(|lint| lint.name.clone());
5150

5251
replace_region_in_file(
5352
update_mode,

clippy_lints/src/asm_syntax.rs

+4
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ declare_clippy_lint! {
6464
///
6565
/// ```rust,no_run
6666
/// # #![feature(asm)]
67+
/// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
6768
/// # unsafe { let ptr = "".as_ptr();
6869
/// # use std::arch::asm;
6970
/// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
@@ -72,6 +73,7 @@ declare_clippy_lint! {
7273
/// Use instead:
7374
/// ```rust,no_run
7475
/// # #![feature(asm)]
76+
/// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
7577
/// # unsafe { let ptr = "".as_ptr();
7678
/// # use std::arch::asm;
7779
/// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
@@ -103,6 +105,7 @@ declare_clippy_lint! {
103105
///
104106
/// ```rust,no_run
105107
/// # #![feature(asm)]
108+
/// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
106109
/// # unsafe { let ptr = "".as_ptr();
107110
/// # use std::arch::asm;
108111
/// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
@@ -111,6 +114,7 @@ declare_clippy_lint! {
111114
/// Use instead:
112115
/// ```rust,no_run
113116
/// # #![feature(asm)]
117+
/// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
114118
/// # unsafe { let ptr = "".as_ptr();
115119
/// # use std::arch::asm;
116120
/// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);

clippy_lints/src/await_holding_invalid.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_hir::{def::Res, AsyncGeneratorKind, Body, BodyId, GeneratorKind};
66
use rustc_lint::{LateContext, LateLintPass};
77
use rustc_middle::ty::GeneratorInteriorTypeCause;
88
use rustc_session::{declare_tool_lint, impl_lint_pass};
9-
use rustc_span::Span;
9+
use rustc_span::{sym, Span};
1010

1111
use crate::utils::conf::DisallowedType;
1212

@@ -276,9 +276,9 @@ fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedTy
276276
}
277277

278278
fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
279-
match_def_path(cx, def_id, &paths::MUTEX_GUARD)
280-
|| match_def_path(cx, def_id, &paths::RWLOCK_READ_GUARD)
281-
|| match_def_path(cx, def_id, &paths::RWLOCK_WRITE_GUARD)
279+
cx.tcx.is_diagnostic_item(sym::MutexGuard, def_id)
280+
|| cx.tcx.is_diagnostic_item(sym::RwLockReadGuard, def_id)
281+
|| cx.tcx.is_diagnostic_item(sym::RwLockWriteGuard, def_id)
282282
|| match_def_path(cx, def_id, &paths::PARKING_LOT_MUTEX_GUARD)
283283
|| match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD)
284284
|| match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD)

clippy_lints/src/blocks_in_if_conditions.rs

+28-40
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use clippy_utils::get_parent_expr;
33
use clippy_utils::higher;
44
use clippy_utils::source::snippet_block_with_applicability;
55
use clippy_utils::ty::implements_trait;
6+
use clippy_utils::visitors::{for_each_expr, Descend};
7+
use core::ops::ControlFlow;
68
use if_chain::if_chain;
79
use rustc_errors::Applicability;
8-
use rustc_hir::intravisit::{walk_expr, Visitor};
9-
use rustc_hir::{BlockCheckMode, Closure, Expr, ExprKind};
10+
use rustc_hir::{BlockCheckMode, Expr, ExprKind};
1011
use rustc_lint::{LateContext, LateLintPass, LintContext};
1112
use rustc_middle::lint::in_external_macro;
1213
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -44,39 +45,6 @@ declare_clippy_lint! {
4445

4546
declare_lint_pass!(BlocksInIfConditions => [BLOCKS_IN_IF_CONDITIONS]);
4647

47-
struct ExVisitor<'a, 'tcx> {
48-
found_block: Option<&'tcx Expr<'tcx>>,
49-
cx: &'a LateContext<'tcx>,
50-
}
51-
52-
impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
53-
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
54-
if let ExprKind::Closure(&Closure { body, .. }) = expr.kind {
55-
// do not lint if the closure is called using an iterator (see #1141)
56-
if_chain! {
57-
if let Some(parent) = get_parent_expr(self.cx, expr);
58-
if let ExprKind::MethodCall(_, self_arg, ..) = &parent.kind;
59-
let caller = self.cx.typeck_results().expr_ty(self_arg);
60-
if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
61-
if implements_trait(self.cx, caller, iter_id, &[]);
62-
then {
63-
return;
64-
}
65-
}
66-
67-
let body = self.cx.tcx.hir().body(body);
68-
let ex = &body.value;
69-
if let ExprKind::Block(block, _) = ex.kind {
70-
if !body.value.span.from_expansion() && !block.stmts.is_empty() {
71-
self.found_block = Some(ex);
72-
return;
73-
}
74-
}
75-
}
76-
walk_expr(self, expr);
77-
}
78-
}
79-
8048
const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition";
8149
const COMPLEX_BLOCK_MESSAGE: &str = "in an `if` condition, avoid complex blocks or closures with blocks; \
8250
instead, move the block or closure higher and bind it with a `let`";
@@ -144,11 +112,31 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions {
144112
}
145113
}
146114
} else {
147-
let mut visitor = ExVisitor { found_block: None, cx };
148-
walk_expr(&mut visitor, cond);
149-
if let Some(block) = visitor.found_block {
150-
span_lint(cx, BLOCKS_IN_IF_CONDITIONS, block.span, COMPLEX_BLOCK_MESSAGE);
151-
}
115+
let _: Option<!> = for_each_expr(cond, |e| {
116+
if let ExprKind::Closure(closure) = e.kind {
117+
// do not lint if the closure is called using an iterator (see #1141)
118+
if_chain! {
119+
if let Some(parent) = get_parent_expr(cx, e);
120+
if let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind;
121+
let caller = cx.typeck_results().expr_ty(self_arg);
122+
if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
123+
if implements_trait(cx, caller, iter_id, &[]);
124+
then {
125+
return ControlFlow::Continue(Descend::No);
126+
}
127+
}
128+
129+
let body = cx.tcx.hir().body(closure.body);
130+
let ex = &body.value;
131+
if let ExprKind::Block(block, _) = ex.kind {
132+
if !body.value.span.from_expansion() && !block.stmts.is_empty() {
133+
span_lint(cx, BLOCKS_IN_IF_CONDITIONS, ex.span, COMPLEX_BLOCK_MESSAGE);
134+
return ControlFlow::Continue(Descend::No);
135+
}
136+
}
137+
}
138+
ControlFlow::Continue(Descend::Yes)
139+
});
152140
}
153141
}
154142
}

clippy_lints/src/bool_to_int_with_if.rs

+3-18
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_hir::{Block, ExprKind};
33
use rustc_lint::{LateContext, LateLintPass};
44
use rustc_session::{declare_lint_pass, declare_tool_lint};
55

6-
use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, sugg::Sugg};
6+
use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, is_integer_literal, sugg::Sugg};
77
use rustc_errors::Applicability;
88

99
declare_clippy_lint! {
@@ -56,13 +56,9 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
5656
&& let Some(then_lit) = int_literal(then)
5757
&& let Some(else_lit) = int_literal(else_)
5858
{
59-
let inverted = if
60-
check_int_literal_equals_val(then_lit, 1)
61-
&& check_int_literal_equals_val(else_lit, 0) {
59+
let inverted = if is_integer_literal(then_lit, 1) && is_integer_literal(else_lit, 0) {
6260
false
63-
} else if
64-
check_int_literal_equals_val(then_lit, 0)
65-
&& check_int_literal_equals_val(else_lit, 1) {
61+
} else if is_integer_literal(then_lit, 0) && is_integer_literal(else_lit, 1) {
6662
true
6763
} else {
6864
// Expression isn't boolean, exit
@@ -123,14 +119,3 @@ fn int_literal<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>) -> Option<&'tcx rustc_hi
123119
None
124120
}
125121
}
126-
127-
fn check_int_literal_equals_val<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>, expected_value: u128) -> bool {
128-
if let ExprKind::Lit(lit) = &expr.kind
129-
&& let LitKind::Int(val, _) = lit.node
130-
&& val == expected_value
131-
{
132-
true
133-
} else {
134-
false
135-
}
136-
}

clippy_lints/src/casts/unnecessary_cast.rs

+50-26
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::get_parent_expr;
23
use clippy_utils::numeric_literal::NumericLiteral;
34
use clippy_utils::source::snippet_opt;
45
use if_chain::if_chain;
@@ -30,8 +31,10 @@ pub(super) fn check<'tcx>(
3031
}
3132
}
3233

34+
let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
35+
3336
if let Some(lit) = get_numeric_literal(cast_expr) {
34-
let literal_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
37+
let literal_str = &cast_str;
3538

3639
if_chain! {
3740
if let LitKind::Int(n, _) = lit.node;
@@ -49,58 +52,79 @@ pub(super) fn check<'tcx>(
4952

5053
match lit.node {
5154
LitKind::Int(_, LitIntType::Unsuffixed) if cast_to.is_integral() => {
52-
lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
55+
lint_unnecessary_cast(cx, expr, literal_str, cast_from, cast_to);
56+
return false;
5357
},
5458
LitKind::Float(_, LitFloatType::Unsuffixed) if cast_to.is_floating_point() => {
55-
lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
59+
lint_unnecessary_cast(cx, expr, literal_str, cast_from, cast_to);
60+
return false;
61+
},
62+
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => {
63+
return false;
5664
},
57-
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => {},
5865
LitKind::Int(_, LitIntType::Signed(_) | LitIntType::Unsigned(_))
5966
| LitKind::Float(_, LitFloatType::Suffixed(_))
6067
if cast_from.kind() == cast_to.kind() =>
6168
{
6269
if let Some(src) = snippet_opt(cx, cast_expr.span) {
6370
if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
6471
lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
72+
return true;
6573
}
6674
}
6775
},
68-
_ => {
69-
if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
70-
span_lint_and_sugg(
71-
cx,
72-
UNNECESSARY_CAST,
73-
expr.span,
74-
&format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
75-
"try",
76-
literal_str,
77-
Applicability::MachineApplicable,
78-
);
79-
return true;
80-
}
81-
},
76+
_ => {},
8277
}
8378
}
8479

80+
if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
81+
span_lint_and_sugg(
82+
cx,
83+
UNNECESSARY_CAST,
84+
expr.span,
85+
&format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
86+
"try",
87+
cast_str,
88+
Applicability::MachineApplicable,
89+
);
90+
return true;
91+
}
92+
8593
false
8694
}
8795

88-
fn lint_unnecessary_cast(cx: &LateContext<'_>, expr: &Expr<'_>, literal_str: &str, cast_from: Ty<'_>, cast_to: Ty<'_>) {
96+
fn lint_unnecessary_cast(
97+
cx: &LateContext<'_>,
98+
expr: &Expr<'_>,
99+
raw_literal_str: &str,
100+
cast_from: Ty<'_>,
101+
cast_to: Ty<'_>,
102+
) {
89103
let literal_kind_name = if cast_from.is_integral() { "integer" } else { "float" };
90-
let replaced_literal;
91-
let matchless = if literal_str.contains(['(', ')']) {
92-
replaced_literal = literal_str.replace(['(', ')'], "");
93-
&replaced_literal
94-
} else {
95-
literal_str
104+
// first we remove all matches so `-(1)` become `-1`, and remove trailing dots, so `1.` become `1`
105+
let literal_str = raw_literal_str
106+
.replace(['(', ')'], "")
107+
.trim_end_matches('.')
108+
.to_string();
109+
// we know need to check if the parent is a method call, to add parenthesis accordingly (eg:
110+
// (-1).foo() instead of -1.foo())
111+
let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
112+
&& let ExprKind::MethodCall(..) = parent_expr.kind
113+
&& literal_str.starts_with('-')
114+
{
115+
format!("({literal_str}_{cast_to})")
116+
117+
} else {
118+
format!("{literal_str}_{cast_to}")
96119
};
120+
97121
span_lint_and_sugg(
98122
cx,
99123
UNNECESSARY_CAST,
100124
expr.span,
101125
&format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"),
102126
"try",
103-
format!("{}_{cast_to}", matchless.trim_end_matches('.')),
127+
sugg,
104128
Applicability::MachineApplicable,
105129
);
106130
}

clippy_lints/src/checked_conversions.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
33
use clippy_utils::diagnostics::span_lint_and_sugg;
44
use clippy_utils::source::snippet_with_applicability;
5-
use clippy_utils::{in_constant, meets_msrv, msrvs, SpanlessEq};
5+
use clippy_utils::{in_constant, is_integer_literal, meets_msrv, msrvs, SpanlessEq};
66
use if_chain::if_chain;
7-
use rustc_ast::ast::LitKind;
87
use rustc_errors::Applicability;
98
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind};
109
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -223,16 +222,7 @@ fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
223222

224223
/// Check for `expr >= 0`
225224
fn check_lower_bound_zero<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> Option<Conversion<'a>> {
226-
if_chain! {
227-
if let ExprKind::Lit(ref lit) = &check.kind;
228-
if let LitKind::Int(0, _) = &lit.node;
229-
230-
then {
231-
Some(Conversion::new_any(candidate))
232-
} else {
233-
None
234-
}
235-
}
225+
is_integer_literal(check, 0).then(|| Conversion::new_any(candidate))
236226
}
237227

238228
/// Check for `expr >= (to_type::MIN as from_type)`

0 commit comments

Comments
 (0)