Skip to content

Commit d3534a6

Browse files
committed
fix issues 10836
1 parent f1fd467 commit d3534a6

File tree

3 files changed

+54
-17
lines changed

3 files changed

+54
-17
lines changed

clippy_lints/src/booleans.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ use rustc_errors::Applicability;
88
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
99
use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
1010
use rustc_lint::{LateContext, LateLintPass, Level};
11+
use rustc_middle::ty::{self, Ty};
1112
use rustc_session::{declare_lint_pass, declare_tool_lint};
1213
use rustc_span::def_id::LocalDefId;
1314
use rustc_span::source_map::Span;
1415
use rustc_span::sym;
16+
use rustc_span::symbol::Ident;
1517

1618
declare_clippy_lint! {
1719
/// ### What it does
@@ -89,6 +91,27 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool {
8991
}
9092
}
9193

94+
fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
95+
cx.tcx
96+
.lang_items()
97+
.not_trait()
98+
.filter(|trait_id| implements_trait(cx, ty, *trait_id, &[]))
99+
.and_then(|trait_id| {
100+
cx.tcx.associated_items(trait_id).find_by_name_and_kind(
101+
cx.tcx,
102+
Ident::from_str("Output"),
103+
ty::AssocKind::Type,
104+
trait_id,
105+
)
106+
})
107+
.map_or(false, |assoc_item| {
108+
let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, []));
109+
let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj);
110+
111+
nty.is_bool()
112+
})
113+
}
114+
92115
struct NonminimalBoolVisitor<'a, 'tcx> {
93116
cx: &'a LateContext<'tcx>,
94117
}
@@ -473,6 +496,12 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
473496
self.bool_expr(e);
474497
},
475498
ExprKind::Unary(UnOp::Not, inner) => {
499+
if let ExprKind::Unary(UnOp::Not, ex) = inner.kind {
500+
let ty = self.cx.typeck_results().expr_ty(ex);
501+
if is_impl_not_trait_with_bool_out(self.cx, ty) {
502+
return;
503+
}
504+
}
476505
if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() {
477506
self.bool_expr(e);
478507
}

tests/ui/nonminimal_bool.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ fn main() {
1010
let e: bool = unimplemented!();
1111
let _ = !true;
1212
let _ = !false;
13+
// vvv Should not lint
1314
let _ = !!a;
1415
let _ = false || a;
1516
// don't lint on cfgs
@@ -54,7 +55,6 @@ fn issue4548() {
5455

5556
fn check_expect() {
5657
let a: bool = unimplemented!();
57-
#[expect(clippy::nonminimal_bool)]
5858
let _ = !!a;
5959
}
6060

@@ -110,3 +110,17 @@ fn issue_10435() {
110110
println!("{}", line!());
111111
}
112112
}
113+
114+
fn issue10836() {
115+
struct Foo(bool);
116+
impl std::ops::Not for Foo {
117+
type Output = bool;
118+
119+
fn not(self) -> Self::Output {
120+
!self.0
121+
}
122+
}
123+
124+
// Should not lint
125+
let _: bool = !!Foo(true);
126+
}

tests/ui/nonminimal_bool.stderr

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,31 @@ LL | let _ = !false;
1313
| ^^^^^^ help: try: `true`
1414

1515
error: this boolean expression can be simplified
16-
--> $DIR/nonminimal_bool.rs:13:13
17-
|
18-
LL | let _ = !!a;
19-
| ^^^ help: try: `a`
20-
21-
error: this boolean expression can be simplified
22-
--> $DIR/nonminimal_bool.rs:14:13
16+
--> $DIR/nonminimal_bool.rs:15:13
2317
|
2418
LL | let _ = false || a;
2519
| ^^^^^^^^^^ help: try: `a`
2620

2721
error: this boolean expression can be simplified
28-
--> $DIR/nonminimal_bool.rs:18:13
22+
--> $DIR/nonminimal_bool.rs:19:13
2923
|
3024
LL | let _ = !(!a && b);
3125
| ^^^^^^^^^^ help: try: `a || !b`
3226

3327
error: this boolean expression can be simplified
34-
--> $DIR/nonminimal_bool.rs:19:13
28+
--> $DIR/nonminimal_bool.rs:20:13
3529
|
3630
LL | let _ = !(!a || b);
3731
| ^^^^^^^^^^ help: try: `a && !b`
3832

3933
error: this boolean expression can be simplified
40-
--> $DIR/nonminimal_bool.rs:20:13
34+
--> $DIR/nonminimal_bool.rs:21:13
4135
|
4236
LL | let _ = !a && !(b && c);
4337
| ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)`
4438

4539
error: this boolean expression can be simplified
46-
--> $DIR/nonminimal_bool.rs:28:13
40+
--> $DIR/nonminimal_bool.rs:29:13
4741
|
4842
LL | let _ = a == b && c == 5 && a == b;
4943
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -56,7 +50,7 @@ LL | let _ = a == b && c == 5;
5650
| ~~~~~~~~~~~~~~~~
5751

5852
error: this boolean expression can be simplified
59-
--> $DIR/nonminimal_bool.rs:29:13
53+
--> $DIR/nonminimal_bool.rs:30:13
6054
|
6155
LL | let _ = a == b || c == 5 || a == b;
6256
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -69,7 +63,7 @@ LL | let _ = a == b || c == 5;
6963
| ~~~~~~~~~~~~~~~~
7064

7165
error: this boolean expression can be simplified
72-
--> $DIR/nonminimal_bool.rs:30:13
66+
--> $DIR/nonminimal_bool.rs:31:13
7367
|
7468
LL | let _ = a == b && c == 5 && b == a;
7569
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -82,7 +76,7 @@ LL | let _ = a == b && c == 5;
8276
| ~~~~~~~~~~~~~~~~
8377

8478
error: this boolean expression can be simplified
85-
--> $DIR/nonminimal_bool.rs:31:13
79+
--> $DIR/nonminimal_bool.rs:32:13
8680
|
8781
LL | let _ = a != b || !(a != b || c == d);
8882
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +89,7 @@ LL | let _ = a != b || c != d;
9589
| ~~~~~~~~~~~~~~~~
9690

9791
error: this boolean expression can be simplified
98-
--> $DIR/nonminimal_bool.rs:32:13
92+
--> $DIR/nonminimal_bool.rs:33:13
9993
|
10094
LL | let _ = a != b && !(a != b && c == d);
10195
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -113,5 +107,5 @@ error: this boolean expression can be simplified
113107
LL | if matches!(true, true) && true {
114108
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)`
115109

116-
error: aborting due to 13 previous errors
110+
error: aborting due to 12 previous errors
117111

0 commit comments

Comments
 (0)