Rollup merge of #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 `!`
```
This commit is contained in:
Matthias Krüger 2022-01-23 01:09:41 +01:00 committed by GitHub
commit 55a1f8b955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 7 deletions

View File

@ -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.

View File

@ -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 () {}
}

View File

@ -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() { }

View File

@ -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
@ -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`.