Skip to content

Commit 20a9ff7

Browse files
authored
Merge pull request #367 from dtolnay/notbool
Switch to custom Not trait instead of `!` operator
2 parents 2b42f62 + cbd91b8 commit 20a9ff7

File tree

4 files changed

+123
-33
lines changed

4 files changed

+123
-33
lines changed

src/ensure.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -815,24 +815,24 @@ macro_rules! __fancy_ensure {
815815
#[macro_export]
816816
macro_rules! __fallback_ensure {
817817
($cond:expr $(,)?) => {
818-
if !$cond {
818+
if $crate::__private::not($cond) {
819819
return $crate::__private::Err($crate::Error::msg(
820820
$crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`")
821821
));
822822
}
823823
};
824824
($cond:expr, $msg:literal $(,)?) => {
825-
if !$cond {
825+
if $crate::__private::not($cond) {
826826
return $crate::__private::Err($crate::__anyhow!($msg));
827827
}
828828
};
829829
($cond:expr, $err:expr $(,)?) => {
830-
if !$cond {
830+
if $crate::__private::not($cond) {
831831
return $crate::__private::Err($crate::__anyhow!($err));
832832
}
833833
};
834834
($cond:expr, $fmt:expr, $($arg:tt)*) => {
835-
if !$cond {
835+
if $crate::__private::not($cond) {
836836
return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*));
837837
}
838838
};

src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,7 @@ pub fn Ok<T>(t: T) -> Result<T> {
651651
// Not public API. Referenced by macro-generated code.
652652
#[doc(hidden)]
653653
pub mod __private {
654+
use self::not::Bool;
654655
use crate::Error;
655656
use alloc::fmt;
656657
use core::fmt::Arguments;
@@ -699,4 +700,31 @@ pub mod __private {
699700
pub fn must_use(error: Error) -> Error {
700701
error
701702
}
703+
704+
#[doc(hidden)]
705+
#[inline]
706+
pub fn not(cond: impl Bool) -> bool {
707+
cond.not()
708+
}
709+
710+
mod not {
711+
#[doc(hidden)]
712+
pub trait Bool {
713+
fn not(self) -> bool;
714+
}
715+
716+
impl Bool for bool {
717+
#[inline]
718+
fn not(self) -> bool {
719+
!self
720+
}
721+
}
722+
723+
impl Bool for &bool {
724+
#[inline]
725+
fn not(self) -> bool {
726+
!*self
727+
}
728+
}
729+
}
702730
}

tests/ui/ensure-nonbool.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
11
use anyhow::{ensure, Result};
2-
use std::ops::Deref;
2+
use std::ops::{Deref, Not};
33

44
struct Bool(bool);
55

66
struct DerefBool(bool);
77

8+
struct NotBool(bool);
9+
810
impl Deref for DerefBool {
911
type Target = bool;
1012
fn deref(&self) -> &Self::Target {
1113
&self.0
1214
}
1315
}
1416

17+
impl Not for NotBool {
18+
type Output = bool;
19+
fn not(self) -> Self::Output {
20+
!self.0
21+
}
22+
}
23+
1524
fn main() -> Result<()> {
1625
ensure!("...");
1726

@@ -24,5 +33,8 @@ fn main() -> Result<()> {
2433
ensure!(db);
2534
ensure!(&db);
2635

36+
let nb = NotBool(true);
37+
ensure!(nb);
38+
2739
Ok(())
2840
}

tests/ui/ensure-nonbool.stderr

Lines changed: 78 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,91 @@
1-
error[E0600]: cannot apply unary operator `!` to type `&'static str`
2-
--> tests/ui/ensure-nonbool.rs:16:5
1+
error[E0277]: the trait bound `&str: __private::not::Bool` is not satisfied
2+
--> tests/ui/ensure-nonbool.rs:25:13
33
|
4-
16 | ensure!("...");
5-
| ^^^^^^^^^^^^^^ cannot apply unary operator `!`
4+
25 | ensure!("...");
5+
| --------^^^^^-
6+
| | |
7+
| | the trait `__private::not::Bool` is not implemented for `&str`
8+
| required by a bound introduced by this call
69
|
7-
= note: this error originates in the macro `$crate::__fallback_ensure` which comes from the expansion of the macro `ensure` (in Nightly builds, run with -Z macro-backtrace for more info)
10+
= help: the following other types implement trait `__private::not::Bool`:
11+
&bool
12+
bool
13+
note: required by a bound in `anyhow::__private::not`
14+
--> src/lib.rs
15+
|
16+
| pub fn not(cond: impl Bool) -> bool {
17+
| ^^^^ required by this bound in `not`
818

9-
error[E0600]: cannot apply unary operator `!` to type `&mut bool`
10-
--> tests/ui/ensure-nonbool.rs:20:23
19+
error[E0277]: the trait bound `&mut bool: __private::not::Bool` is not satisfied
20+
--> tests/ui/ensure-nonbool.rs:29:31
21+
|
22+
29 | Bool(cond) => ensure!(cond),
23+
| --------^^^^-
24+
| | |
25+
| | the trait `__private::not::Bool` is not implemented for `&mut bool`
26+
| required by a bound introduced by this call
1127
|
12-
20 | Bool(cond) => ensure!(cond),
13-
| ^^^^^^^^^^^^^ cannot apply unary operator `!`
28+
= help: the following other types implement trait `__private::not::Bool`:
29+
&bool
30+
bool
31+
= note: `__private::not::Bool` is implemented for `&bool`, but not for `&mut bool`
32+
note: required by a bound in `anyhow::__private::not`
33+
--> src/lib.rs
1434
|
15-
= note: this error originates in the macro `$crate::__fallback_ensure` which comes from the expansion of the macro `ensure` (in Nightly builds, run with -Z macro-backtrace for more info)
35+
| pub fn not(cond: impl Bool) -> bool {
36+
| ^^^^ required by this bound in `not`
1637

17-
error[E0600]: cannot apply unary operator `!` to type `DerefBool`
18-
--> tests/ui/ensure-nonbool.rs:24:5
38+
error[E0277]: the trait bound `DerefBool: __private::not::Bool` is not satisfied
39+
--> tests/ui/ensure-nonbool.rs:33:13
1940
|
20-
24 | ensure!(db);
21-
| ^^^^^^^^^^^ cannot apply unary operator `!`
41+
33 | ensure!(db);
42+
| --------^^-
43+
| | |
44+
| | the trait `__private::not::Bool` is not implemented for `DerefBool`
45+
| required by a bound introduced by this call
2246
|
23-
note: an implementation of `Not` might be missing for `DerefBool`
24-
--> tests/ui/ensure-nonbool.rs:6:1
47+
= help: the following other types implement trait `__private::not::Bool`:
48+
&bool
49+
bool
50+
note: required by a bound in `anyhow::__private::not`
51+
--> src/lib.rs
52+
|
53+
| pub fn not(cond: impl Bool) -> bool {
54+
| ^^^^ required by this bound in `not`
55+
56+
error[E0277]: the trait bound `&DerefBool: __private::not::Bool` is not satisfied
57+
--> tests/ui/ensure-nonbool.rs:34:13
2558
|
26-
6 | struct DerefBool(bool);
27-
| ^^^^^^^^^^^^^^^^ must implement `Not`
28-
note: the trait `Not` must be implemented
29-
--> $RUST/core/src/ops/bit.rs
59+
34 | ensure!(&db);
60+
| --------^^^-
61+
| | |
62+
| | the trait `__private::not::Bool` is not implemented for `&DerefBool`
63+
| required by a bound introduced by this call
3064
|
31-
| pub trait Not {
32-
| ^^^^^^^^^^^^^
33-
= note: this error originates in the macro `$crate::__fallback_ensure` which comes from the expansion of the macro `ensure` (in Nightly builds, run with -Z macro-backtrace for more info)
65+
note: required by a bound in `anyhow::__private::not`
66+
--> src/lib.rs
67+
|
68+
| pub fn not(cond: impl Bool) -> bool {
69+
| ^^^^ required by this bound in `not`
70+
help: consider dereferencing here
71+
|
72+
34 | ensure!(&*db);
73+
| +
3474

35-
error[E0600]: cannot apply unary operator `!` to type `&DerefBool`
36-
--> tests/ui/ensure-nonbool.rs:25:5
75+
error[E0277]: the trait bound `NotBool: __private::not::Bool` is not satisfied
76+
--> tests/ui/ensure-nonbool.rs:37:13
77+
|
78+
37 | ensure!(nb);
79+
| --------^^-
80+
| | |
81+
| | the trait `__private::not::Bool` is not implemented for `NotBool`
82+
| required by a bound introduced by this call
3783
|
38-
25 | ensure!(&db);
39-
| ^^^^^^^^^^^^ cannot apply unary operator `!`
84+
= help: the following other types implement trait `__private::not::Bool`:
85+
&bool
86+
bool
87+
note: required by a bound in `anyhow::__private::not`
88+
--> src/lib.rs
4089
|
41-
= note: this error originates in the macro `$crate::__fallback_ensure` which comes from the expansion of the macro `ensure` (in Nightly builds, run with -Z macro-backtrace for more info)
90+
| pub fn not(cond: impl Bool) -> bool {
91+
| ^^^^ required by this bound in `not`

0 commit comments

Comments
 (0)