Skip to content

Commit

Permalink
Rollup merge of #91122 - dtolnay:not, r=m-ou-se
Browse files Browse the repository at this point in the history
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 `!`
```
  • Loading branch information
matthiaskrgr authored Jan 23, 2022
2 parents 59d9ad9 + 3136c5f commit 55a1f8b
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 7 deletions.
11 changes: 11 additions & 0 deletions library/core/src/ops/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,17 @@ macro_rules! not_impl {

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

#[stable(feature = "not_never", since = "1.60.0")]
#[rustc_const_unstable(feature = "const_ops", issue = "90080")]
impl const Not for ! {
type Output = !;

#[inline]
fn not(self) -> ! {
match self {}
}
}

/// The bitwise AND operator `&`.
///
/// Note that `Rhs` is `Self` by default, but this is not mandatory.
Expand Down
6 changes: 6 additions & 0 deletions library/core/tests/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,9 @@ fn deref_on_ref() {
let y = deref(&mut x);
assert_eq!(y, 4);
}

#[test]
#[allow(unreachable_code)]
fn test_not_never() {
if !return () {}
}
4 changes: 2 additions & 2 deletions src/test/ui/reachable/expr_unary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#![deny(unreachable_code)]

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

fn main() { }
10 changes: 5 additions & 5 deletions src/test/ui/reachable/expr_unary.stderr
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error[E0600]: cannot apply unary operator `!` to type `!`
error[E0614]: type `!` cannot be dereferenced
--> $DIR/expr_unary.rs:8:16
|
LL | let x: ! = ! { return; };
| ^^^^^^^^^^^^^ cannot apply unary operator `!`
LL | let x: ! = * { return; };
| ^^^^^^^^^^^^^

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

error: aborting due to 2 previous errors

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

0 comments on commit 55a1f8b

Please sign in to comment.