Skip to content

Commit 7e638e1

Browse files
committed
add more expressions to check
1 parent 0dfeca0 commit 7e638e1

File tree

3 files changed

+84
-24
lines changed

3 files changed

+84
-24
lines changed

clippy_lints/src/mutable_debug_assertion.rs

+64-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::utils::{is_direct_expn_of, span_lint};
2+
use core::ops::Deref;
23
use if_chain::if_chain;
34
use matches::matches;
4-
use rustc::hir::{Expr, ExprKind, Mutability, StmtKind, UnOp};
5+
use rustc::hir::{Expr, ExprKind, Guard, Mutability, StmtKind, UnOp};
56
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
67
use rustc::{declare_lint_pass, declare_tool_lint, ty};
78
use syntax_pos::Span;
@@ -31,19 +32,67 @@ declare_clippy_lint! {
3132

3233
declare_lint_pass!(DebugAssertWithMutCall => [DEBUG_ASSERT_WITH_MUT_CALL]);
3334

34-
fn check_for_mutable_call(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
35+
fn check_for_mutable_call(cx: &LateContext<'_, '_>, span: Span, e: &Expr) -> Option<Span> {
3536
match &e.kind {
36-
ExprKind::AddrOf(Mutability::MutMutable, _) => true,
37-
ExprKind::AddrOf(Mutability::MutImmutable, expr) | ExprKind::Unary(_, expr) => check_for_mutable_call(cx, expr),
38-
ExprKind::Binary(_, lhs, rhs) => check_for_mutable_call(cx, lhs) | check_for_mutable_call(cx, rhs),
39-
ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => {
40-
(*args).iter().any(|a| check_for_mutable_call(cx, a))
37+
ExprKind::AddrOf(Mutability::MutMutable, _) => Some(span),
38+
ExprKind::AddrOf(Mutability::MutImmutable, expr)
39+
| ExprKind::Assign(_, expr)
40+
| ExprKind::AssignOp(_, _, expr)
41+
| ExprKind::Box(expr)
42+
| ExprKind::Break(_, Some(expr))
43+
| ExprKind::Cast(expr, _)
44+
| ExprKind::DropTemps(expr)
45+
| ExprKind::Field(expr, _)
46+
| ExprKind::Repeat(expr, _)
47+
| ExprKind::Ret(Some(expr))
48+
| ExprKind::Type(expr, _)
49+
| ExprKind::Unary(_, expr)
50+
| ExprKind::Yield(expr, _) => check_for_mutable_call(cx, expr.span, expr),
51+
ExprKind::Binary(_, lhs, rhs) | ExprKind::Index(lhs, rhs) => {
52+
check_for_mutable_call(cx, lhs.span, lhs).or_else(|| check_for_mutable_call(cx, rhs.span, rhs))
4153
},
42-
ExprKind::Path(_) => cx.tables.adjustments().get(e.hir_id).map_or(false, |adj| {
43-
adj.iter()
54+
ExprKind::Array(args) | ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) | ExprKind::Tup(args) => {
55+
(*args).iter().find_map(|a| check_for_mutable_call(cx, span, a))
56+
},
57+
ExprKind::Path(_) => cx.tables.adjustments().get(e.hir_id).and_then(|adj| {
58+
if adj
59+
.iter()
4460
.any(|a| matches!(a.target.kind, ty::Ref(_, _, Mutability::MutMutable)))
61+
{
62+
Some(span)
63+
} else {
64+
None
65+
}
66+
}),
67+
ExprKind::Match(header, arm, _) => check_for_mutable_call(cx, header.span, header).or_else(|| {
68+
(*arm).iter().find_map(|a| {
69+
check_for_mutable_call(cx, a.body.span, &a.body).or_else(|| {
70+
a.guard.as_ref().and_then(|g| {
71+
let Guard::If(e) = g;
72+
check_for_mutable_call(cx, e.span, &e)
73+
})
74+
})
75+
})
4576
}),
46-
_ => false,
77+
ExprKind::Block(block, _) | ExprKind::Loop(block, _, _) => block
78+
.stmts
79+
.iter()
80+
.filter_map(|s| match &s.kind {
81+
StmtKind::Local(l) => l.init.as_ref().map(|x| x.deref()),
82+
StmtKind::Expr(e) => Some(e),
83+
StmtKind::Semi(e) => Some(e),
84+
StmtKind::Item(_) => None,
85+
})
86+
.chain(block.expr.as_ref().map(|x| x.deref()))
87+
.find_map(|a| check_for_mutable_call(cx, a.span, a)),
88+
ExprKind::Err
89+
| ExprKind::Lit(_)
90+
| ExprKind::Continue(_)
91+
| ExprKind::InlineAsm(_, _, _)
92+
| ExprKind::Struct(_, _, _)
93+
| ExprKind::Closure(_, _, _, _, _)
94+
| ExprKind::Break(_, None)
95+
| ExprKind::Ret(None) => None,
4796
}
4897
}
4998

@@ -60,9 +109,7 @@ fn extract_call(cx: &LateContext<'_, '_>, e: &Expr) -> Option<Span> {
60109
if let ExprKind::Unary(UnOp::UnNot, ref condition) = droptmp.kind;
61110
then {
62111
// debug_assert
63-
if check_for_mutable_call(cx, condition) {
64-
return Some(condition.span);
65-
}
112+
return check_for_mutable_call(cx, condition.span, condition)
66113
} else {
67114
// debug_assert_{eq,ne}
68115
if_chain! {
@@ -73,13 +120,13 @@ fn extract_call(cx: &LateContext<'_, '_>, e: &Expr) -> Option<Span> {
73120
if conditions.len() == 2;
74121
then {
75122
if let ExprKind::AddrOf(_, ref lhs) = conditions[0].kind {
76-
if check_for_mutable_call(cx, lhs) {
77-
return Some(lhs.span);
123+
if let Some(span) = check_for_mutable_call(cx, lhs.span, lhs) {
124+
return Some(span);
78125
}
79126
}
80127
if let ExprKind::AddrOf(_, ref rhs) = conditions[1].kind {
81-
if check_for_mutable_call(cx, rhs) {
82-
return Some(rhs.span);
128+
if let Some(span) = check_for_mutable_call(cx, rhs.span, rhs) {
129+
return Some(span);
83130
}
84131
}
85132
}

tests/ui/debug_assert_with_mut_call.rs

+7
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ fn misc() {
9898
debug_assert!(bool_mut(&mut 3), "w/o format");
9999
debug_assert!(bool_ref(&3), "{} format", "w/");
100100
debug_assert!(bool_mut(&mut 3), "{} format", "w/");
101+
102+
// sub block
103+
let mut x = 42_u32;
104+
debug_assert!({
105+
bool_mut(&mut x);
106+
x > 10
107+
});
101108
}
102109

103110
fn main() {

tests/ui/debug_assert_with_mut_call.stderr

+13-7
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ LL | debug_assert!(bool_mut(&mut 3));
77
= note: `#[deny(clippy::debug_assert_with_mut_call)]` on by default
88

99
error: do not call functions with mutable arguments inside of a `debug_assert!`
10-
--> $DIR/debug_assert_with_mut_call.rs:41:19
10+
--> $DIR/debug_assert_with_mut_call.rs:41:20
1111
|
1212
LL | debug_assert!(!bool_mut(&mut 3));
13-
| ^^^^^^^^^^^^^^^^^
13+
| ^^^^^^^^^^^^^^^^
1414

1515
error: do not call functions with mutable arguments inside of a `debug_assert!`
1616
--> $DIR/debug_assert_with_mut_call.rs:43:25
@@ -43,10 +43,10 @@ LL | debug_assert!(S.bool_self_mut());
4343
| ^^^^^^^^^^^^^^^^^
4444

4545
error: do not call functions with mutable arguments inside of a `debug_assert!`
46-
--> $DIR/debug_assert_with_mut_call.rs:63:19
46+
--> $DIR/debug_assert_with_mut_call.rs:63:20
4747
|
4848
LL | debug_assert!(!S.bool_self_mut());
49-
| ^^^^^^^^^^^^^^^^^^
49+
| ^^^^^^^^^^^^^^^^^
5050

5151
error: do not call functions with mutable arguments inside of a `debug_assert!`
5252
--> $DIR/debug_assert_with_mut_call.rs:64:19
@@ -133,10 +133,10 @@ LL | debug_assert!(bool_mut(a));
133133
| ^^^^^^^^^^^
134134

135135
error: do not call functions with mutable arguments inside of a `debug_assert!`
136-
--> $DIR/debug_assert_with_mut_call.rs:91:19
136+
--> $DIR/debug_assert_with_mut_call.rs:91:31
137137
|
138138
LL | debug_assert!(!(bool_ref(&u32_mut(&mut 3))));
139-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
139+
| ^^^^^^^^^^^^^^^
140140

141141
error: do not call functions with mutable arguments inside of a `debug_assert!`
142142
--> $DIR/debug_assert_with_mut_call.rs:94:22
@@ -156,5 +156,11 @@ error: do not call functions with mutable arguments inside of a `debug_assert!`
156156
LL | debug_assert!(bool_mut(&mut 3), "{} format", "w/");
157157
| ^^^^^^^^^^^^^^^^
158158

159-
error: aborting due to 26 previous errors
159+
error: do not call functions with mutable arguments inside of a `debug_assert!`
160+
--> $DIR/debug_assert_with_mut_call.rs:105:9
161+
|
162+
LL | bool_mut(&mut x);
163+
| ^^^^^^^^^^^^^^^^
164+
165+
error: aborting due to 27 previous errors
160166

0 commit comments

Comments
 (0)