Skip to content

Commit c8be801

Browse files
authored
Rollup merge of rust-lang#91122 - dtolnay:not, r=m-ou-se
impl Not for ! The lack of this impl caused trouble for me in some degenerate cases of macro-generated code of the form `if !$cond {...}`, even without `feature(never_type)` on a stable compiler. Namely if `$cond` contains a `return` or `break` or similar diverging expression, which would otherwise be perfectly legal in boolean position, the code previously failed to compile with: ```console error[E0600]: cannot apply unary operator `!` to type `!` --> library/core/tests/ops.rs:239:8 | 239 | if !return () {} | ^^^^^^^^^^ cannot apply unary operator `!` ```
2 parents dd9c6ad + 3136c5f commit c8be801

File tree

4 files changed

+24
-7
lines changed

4 files changed

+24
-7
lines changed

library/core/src/ops/bit.rs

+11
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ macro_rules! not_impl {
6868

6969
not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
7070

71+
#[stable(feature = "not_never", since = "1.60.0")]
72+
#[rustc_const_unstable(feature = "const_ops", issue = "90080")]
73+
impl const Not for ! {
74+
type Output = !;
75+
76+
#[inline]
77+
fn not(self) -> ! {
78+
match self {}
79+
}
80+
}
81+
7182
/// The bitwise AND operator `&`.
7283
///
7384
/// Note that `Rhs` is `Self` by default, but this is not mandatory.

library/core/tests/ops.rs

+6
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,9 @@ fn deref_on_ref() {
232232
let y = deref(&mut x);
233233
assert_eq!(y, 4);
234234
}
235+
236+
#[test]
237+
#[allow(unreachable_code)]
238+
fn test_not_never() {
239+
if !return () {}
240+
}

src/test/ui/reachable/expr_unary.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#![deny(unreachable_code)]
66

77
fn foo() {
8-
let x: ! = ! { return; }; //~ ERROR unreachable
9-
//~| ERROR cannot apply unary operator `!` to type `!`
8+
let x: ! = * { return; }; //~ ERROR unreachable
9+
//~| ERROR type `!` cannot be dereferenced
1010
}
1111

1212
fn main() { }

src/test/ui/reachable/expr_unary.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
error[E0600]: cannot apply unary operator `!` to type `!`
1+
error[E0614]: type `!` cannot be dereferenced
22
--> $DIR/expr_unary.rs:8:16
33
|
4-
LL | let x: ! = ! { return; };
5-
| ^^^^^^^^^^^^^ cannot apply unary operator `!`
4+
LL | let x: ! = * { return; };
5+
| ^^^^^^^^^^^^^
66

77
error: unreachable expression
88
--> $DIR/expr_unary.rs:8:16
99
|
10-
LL | let x: ! = ! { return; };
10+
LL | let x: ! = * { return; };
1111
| ^^^^------^^^
1212
| | |
1313
| | any code following this expression is unreachable
@@ -21,4 +21,4 @@ LL | #![deny(unreachable_code)]
2121

2222
error: aborting due to 2 previous errors
2323

24-
For more information about this error, try `rustc --explain E0600`.
24+
For more information about this error, try `rustc --explain E0614`.

0 commit comments

Comments
 (0)