about summary refs log tree commit diff
path: root/src/test/ui/numeric
diff options
context:
space:
mode:
authorAyaz Hafiz <ayaz.hafiz.1@gmail.com>2020-06-13 16:22:24 -0700
committerAyaz Hafiz <ayaz.hafiz.1@gmail.com>2020-06-13 16:22:24 -0700
commitafbbd383ccee8b91b1d1bbdcfb0f7a906bba71f7 (patch)
tree93bab1420d7be7d085c6c85bea5c97f261b85818 /src/test/ui/numeric
parent06e47688bf15d0215edbe05b21603062f6d2eb5d (diff)
downloadrust-afbbd383ccee8b91b1d1bbdcfb0f7a906bba71f7.tar.gz
rust-afbbd383ccee8b91b1d1bbdcfb0f7a906bba71f7.zip
Note numeric literals that can never fit in an expected type
re https://github.com/rust-lang/rust/pull/72380#discussion_r438289385

Given the toy code

```rust
fn is_positive(n: usize) {
  n > -1_isize;
}
```

We currently get a type mismatch error like the following:

```
error[E0308]: mismatched types
 --> src/main.rs:2:9
  |
2 |     n > -1_isize;
  |         ^^^^^^^^ expected `usize`, found `isize`
  |
help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
  |
2 |     n > (-1_isize).try_into().unwrap();
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

But clearly, `-1` can never fit into a `usize`, so the suggestion will
always panic. A more useful message would tell the user that the value
can never fit in the expected type:

```
error[E0308]: mismatched types
 --> test.rs:2:9
  |
2 |     n > -1_isize;
  |         ^^^^^^^^ expected `usize`, found `isize`
  |
note: `-1_isize` can never fit into `usize`
 --> test.rs:2:9
  |
2 |     n > -1_isize;
  |         ^^^^^^^^
```

Which is what this commit implements.

I only added this check for negative literals because

- Currently we can only perform such a check for literals (constant
  value propagation is outside the scope of the typechecker at this
  point)
- A lint error for out-of-range numeric literals is already emitted

IMO it makes more sense to put this check in librustc_lint, but as far
as I can tell the typecheck pass happens before the lint pass, so I've
added it here.

r? @estebank
Diffstat (limited to 'src/test/ui/numeric')
-rw-r--r--src/test/ui/numeric/numeric-cast-no-fix.rs22
-rw-r--r--src/test/ui/numeric/numeric-cast-no-fix.stderr74
2 files changed, 96 insertions, 0 deletions
diff --git a/src/test/ui/numeric/numeric-cast-no-fix.rs b/src/test/ui/numeric/numeric-cast-no-fix.rs
new file mode 100644
index 00000000000..8bfd8333541
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast-no-fix.rs
@@ -0,0 +1,22 @@
+#[allow(unused_must_use)]
+fn main() {
+    let x_usize: usize = 1;
+    let x_u128: u128 = 2;
+    let x_u64: u64 = 3;
+    let x_u32: u32 = 4;
+    let x_u16: u16 = 5;
+    let x_u8: u8 = 6;
+
+    x_usize > -1_isize;
+    //~^ ERROR mismatched types
+    x_u128 > -1_isize;
+    //~^ ERROR mismatched types
+    x_u64 > -1_isize;
+    //~^ ERROR mismatched types
+    x_u32 > -1_isize;
+    //~^ ERROR mismatched types
+    x_u16 > -1_isize;
+    //~^ ERROR mismatched types
+    x_u8 > -1_isize;
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/numeric/numeric-cast-no-fix.stderr b/src/test/ui/numeric/numeric-cast-no-fix.stderr
new file mode 100644
index 00000000000..51e263d636f
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast-no-fix.stderr
@@ -0,0 +1,74 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-no-fix.rs:10:15
+   |
+LL |     x_usize > -1_isize;
+   |               ^^^^^^^^ expected `usize`, found `isize`
+   |
+note: `-1_isize` can never fit into `usize`
+  --> $DIR/numeric-cast-no-fix.rs:10:15
+   |
+LL |     x_usize > -1_isize;
+   |               ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-no-fix.rs:12:14
+   |
+LL |     x_u128 > -1_isize;
+   |              ^^^^^^^^ expected `u128`, found `isize`
+   |
+note: `-1_isize` can never fit into `u128`
+  --> $DIR/numeric-cast-no-fix.rs:12:14
+   |
+LL |     x_u128 > -1_isize;
+   |              ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-no-fix.rs:14:13
+   |
+LL |     x_u64 > -1_isize;
+   |             ^^^^^^^^ expected `u64`, found `isize`
+   |
+note: `-1_isize` can never fit into `u64`
+  --> $DIR/numeric-cast-no-fix.rs:14:13
+   |
+LL |     x_u64 > -1_isize;
+   |             ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-no-fix.rs:16:13
+   |
+LL |     x_u32 > -1_isize;
+   |             ^^^^^^^^ expected `u32`, found `isize`
+   |
+note: `-1_isize` can never fit into `u32`
+  --> $DIR/numeric-cast-no-fix.rs:16:13
+   |
+LL |     x_u32 > -1_isize;
+   |             ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-no-fix.rs:18:13
+   |
+LL |     x_u16 > -1_isize;
+   |             ^^^^^^^^ expected `u16`, found `isize`
+   |
+note: `-1_isize` can never fit into `u16`
+  --> $DIR/numeric-cast-no-fix.rs:18:13
+   |
+LL |     x_u16 > -1_isize;
+   |             ^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-no-fix.rs:20:12
+   |
+LL |     x_u8 > -1_isize;
+   |            ^^^^^^^^ expected `u8`, found `isize`
+   |
+help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize`
+   |
+LL |     isize::from(x_u8) > -1_isize;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.