Skip to content

Commit 2969137

Browse files
Add invalid unary operator usage error code
1 parent 998b197 commit 2969137

File tree

5 files changed

+64
-6
lines changed

5 files changed

+64
-6
lines changed

src/librustc_typeck/check/op.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
316316
match self.lookup_op_method(ex, operand_ty, vec![], mname, trait_did, operand_expr) {
317317
Ok(t) => t,
318318
Err(()) => {
319-
self.type_error_message(ex.span, |actual| {
320-
format!("cannot apply unary operator `{}` to type `{}`",
321-
op_str, actual)
322-
}, operand_ty);
319+
let actual = self.resolve_type_vars_if_possible(&operand_ty);
320+
if !actual.references_error() {
321+
struct_span_err!(self.tcx.sess, ex.span, E0600,
322+
"cannot apply unary operator `{}` to type `{}`",
323+
op_str, actual).emit();
324+
}
323325
self.tcx.types.err
324326
}
325327
}

src/librustc_typeck/diagnostics.rs

+43
Original file line numberDiff line numberDiff line change
@@ -4052,6 +4052,49 @@ x.chocolate(); // error: no method named `chocolate` found for type `Mouth`
40524052
```
40534053
"##,
40544054

4055+
E0600: r##"
4056+
An unary operator was used on a type which doesn't implement it.
4057+
4058+
Example of erroneous code:
4059+
4060+
```compile_fail,E0600
4061+
enum Question {
4062+
Yes,
4063+
No,
4064+
}
4065+
4066+
!Question::Yes; // error: cannot apply unary operator `!` to type `Question`
4067+
```
4068+
4069+
In this case, `Question` would need to implement the `std::ops::Not` trait in
4070+
order to be able to use `!` on it. Let's implement it:
4071+
4072+
```
4073+
use std::ops::Not;
4074+
4075+
enum Question {
4076+
Yes,
4077+
No,
4078+
}
4079+
4080+
// We implement the `Not` trait on the enum.
4081+
impl Not for Question {
4082+
type Output = bool;
4083+
4084+
fn not(self) -> bool {
4085+
match self {
4086+
Question::Yes => false, // If the `Answer` is `Yes`, then it
4087+
// returns false.
4088+
Question::No => true, // And here we do the opposite.
4089+
}
4090+
}
4091+
}
4092+
4093+
assert_eq!(!Question::Yes, false);
4094+
assert_eq!(!Question::No, true);
4095+
```
4096+
"##,
4097+
40554098
}
40564099

40574100
register_diagnostics! {

src/test/compile-fail/E0600.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
!"a"; //~ ERROR E0600
13+
}

src/test/ui/codemap_tests/issue-28308.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: cannot apply unary operator `!` to type `&'static str`
1+
error[E0600]: cannot apply unary operator `!` to type `&'static str`
22
--> $DIR/issue-28308.rs:12:5
33
|
44
12 | assert!("foo");

src/test/ui/reachable/expr_unary.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: cannot apply unary operator `!` to type `!`
1+
error[E0600]: cannot apply unary operator `!` to type `!`
22
--> $DIR/expr_unary.rs:18:16
33
|
44
18 | let x: ! = ! { return; 22 };

0 commit comments

Comments
 (0)