]> git.lizzy.rs Git - rust.git/commitdiff
When cast needs a dereference point at full cast
authorEsteban Küber <esteban@kuber.com.ar>
Thu, 8 Dec 2016 19:06:18 +0000 (11:06 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Thu, 15 Dec 2016 01:33:03 +0000 (17:33 -0800)
After the fix of #37453 in PR #37369, instead of pointing at only the
cast type, point at the full cast span when a cast needs a dereference:

```
error: casting `&{float}` as `f32` is invalid
  --> ../../../src/test/ui/mismatched_types/cast-rfc0401.rs:81:30
   |
81 |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
   |                              ^^^^^^^^ cannot cast `&{float}` as `f32`
   |
help: did you mean `*s`?
  --> ../../../src/test/ui/mismatched_types/cast-rfc0401.rs:81:30
   |
81 |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
   |                              ^
```

instead of

```
error: casting `&{float}` as `f32` is invalid
  --> ../../../src/test/ui/mismatched_types/cast-rfc0401.rs:81:35
   |
81 |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
   |                              -    ^^^
   |                              |
   |                              |
   |                              did you mean `*s`?
   |                              cannot cast `&{float}` as `f32`
```

src/librustc_typeck/check/cast.rs
src/test/compile-fail/cast-rfc0401.rs [deleted file]
src/test/ui/mismatched_types/cast-rfc0401.rs [new file with mode: 0644]
src/test/ui/mismatched_types/cast-rfc0401.stderr [new file with mode: 0644]

index f2c8ef46a7e252db6a090ee80222797cec8d5fe1..265dcada1f810651a76401793644cfb0d17c1261 100644 (file)
@@ -142,20 +142,21 @@ pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
     fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
         match e {
             CastError::NeedDeref => {
+                let error_span = self.span;
                 let cast_ty = fcx.ty_to_string(self.cast_ty);
-                let mut err = fcx.type_error_struct(self.cast_span,
+                let mut err = fcx.type_error_struct(error_span,
                                        |actual| {
                                            format!("casting `{}` as `{}` is invalid",
                                                    actual,
                                                    cast_ty)
                                        },
                                        self.expr_ty);
-                err.span_label(self.expr.span,
+                err.span_label(error_span,
                                &format!("cannot cast `{}` as `{}`",
                                         fcx.ty_to_string(self.expr_ty),
                                         cast_ty));
                 if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) {
-                    err.span_label(self.expr.span,
+                    err.span_help(self.expr.span,
                                    &format!("did you mean `*{}`?", snippet));
                 }
                 err.emit();
diff --git a/src/test/compile-fail/cast-rfc0401.rs b/src/test/compile-fail/cast-rfc0401.rs
deleted file mode 100644 (file)
index b98f464..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn illegal_cast<U:?Sized,V:?Sized>(u: *const U) -> *const V
-{
-    u as *const V
-    //~^ ERROR casting
-    //~^^ NOTE vtable kinds
-}
-
-fn illegal_cast_2<U:?Sized>(u: *const U) -> *const str
-{
-    u as *const str
-    //~^ ERROR casting
-    //~^^ NOTE vtable kinds
-}
-
-trait Foo { fn foo(&self) {} }
-impl<T> Foo for T {}
-
-trait Bar { fn foo(&self) {} }
-impl<T> Bar for T {}
-
-enum E {
-    A, B
-}
-
-fn main()
-{
-    let f: f32 = 1.2;
-    let v = 0 as *const u8;
-    let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])};
-    let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])};
-    let foo: &Foo = &f;
-
-    let _ = v as &u8; //~ ERROR non-scalar
-    let _ = v as E; //~ ERROR non-scalar
-    let _ = v as fn(); //~ ERROR non-scalar
-    let _ = v as (u32,); //~ ERROR non-scalar
-    let _ = Some(&v) as *const u8; //~ ERROR non-scalar
-
-    let _ = v as f32;
-    //~^ ERROR casting
-    let _ = main as f64;
-    //~^ ERROR casting
-    let _ = &v as usize;
-    //~^ ERROR casting
-    //~^^ HELP through a raw pointer first
-    let _ = f as *const u8;
-    //~^ ERROR casting
-    let _ = 3_i32 as bool;
-    //~^ ERROR cannot cast as `bool` [E0054]
-    //~| unsupported cast
-    //~| HELP compare with zero
-    let _ = E::A as bool;
-    //~^ ERROR cannot cast as `bool` [E0054]
-    //~| unsupported cast
-    //~| HELP compare with zero
-    let _ = 0x61u32 as char; //~ ERROR only `u8` can be cast
-
-    let _ = false as f32;
-    //~^ ERROR casting
-    //~^^ HELP through an integer first
-    let _ = E::A as f32;
-    //~^ ERROR casting
-    //~^^ HELP through an integer first
-    let _ = 'a' as f32;
-    //~^ ERROR casting
-    //~^^ HELP through an integer first
-
-    let _ = false as *const u8;
-    //~^ ERROR casting
-    let _ = E::A as *const u8;
-    //~^ ERROR casting
-    let _ = 'a' as *const u8;
-    //~^ ERROR casting
-
-    let _ = 42usize as *const [u8]; //~ ERROR casting
-    let _ = v as *const [u8]; //~ ERROR cannot cast
-    let _ = fat_v as *const Foo;
-    //~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied
-    //~| NOTE the trait `std::marker::Sized` is not implemented for `[u8]`
-    //~| NOTE `[u8]` does not have a constant size known at compile-time
-    //~| NOTE required for the cast to the object type `Foo`
-    let _ = foo as *const str; //~ ERROR casting
-    let _ = foo as *mut str; //~ ERROR casting
-    let _ = main as *mut str; //~ ERROR casting
-    let _ = &f as *mut f32; //~ ERROR casting
-    let _ = &f as *const f64; //~ ERROR casting
-    let _ = fat_sv as usize;
-    //~^ ERROR casting
-    //~^^ HELP through a thin pointer first
-
-    let a : *const str = "hello";
-    let _ = a as *const Foo;
-    //~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied
-    //~| NOTE the trait `std::marker::Sized` is not implemented for `str`
-    //~| NOTE `str` does not have a constant size known at compile-time
-    //~| NOTE required for the cast to the object type `Foo`
-
-    // check no error cascade
-    let _ = main.f as *const u32; //~ no field `f` on type `fn() {main}`
-
-    let cf: *const Foo = &0;
-    let _ = cf as *const [u16];
-    //~^ ERROR casting
-    //~^^ NOTE vtable kinds
-    let _ = cf as *const Bar;
-    //~^ ERROR casting
-    //~^^ NOTE vtable kinds
-
-    vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
-    //~^ ERROR casting `&{float}` as `f32` is invalid
-    //~| NOTE cannot cast `&{float}` as `f32`
-    //~| NOTE did you mean `*s`?
-}
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.rs b/src/test/ui/mismatched_types/cast-rfc0401.rs
new file mode 100644 (file)
index 0000000..f72be0d
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn illegal_cast<U:?Sized,V:?Sized>(u: *const U) -> *const V
+{
+    u as *const V
+}
+
+fn illegal_cast_2<U:?Sized>(u: *const U) -> *const str
+{
+    u as *const str
+}
+
+trait Foo { fn foo(&self) {} }
+impl<T> Foo for T {}
+
+trait Bar { fn foo(&self) {} }
+impl<T> Bar for T {}
+
+enum E {
+    A, B
+}
+
+fn main()
+{
+    let f: f32 = 1.2;
+    let v = 0 as *const u8;
+    let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])};
+    let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])};
+    let foo: &Foo = &f;
+
+    let _ = v as &u8;
+    let _ = v as E;
+    let _ = v as fn();
+    let _ = v as (u32,);
+    let _ = Some(&v) as *const u8;
+
+    let _ = v as f32;
+    let _ = main as f64;
+    let _ = &v as usize;
+    let _ = f as *const u8;
+    let _ = 3_i32 as bool;
+    let _ = E::A as bool;
+    let _ = 0x61u32 as char;
+
+    let _ = false as f32;
+    let _ = E::A as f32;
+    let _ = 'a' as f32;
+
+    let _ = false as *const u8;
+    let _ = E::A as *const u8;
+    let _ = 'a' as *const u8;
+
+    let _ = 42usize as *const [u8];
+    let _ = v as *const [u8];
+    let _ = fat_v as *const Foo;
+    let _ = foo as *const str;
+    let _ = foo as *mut str;
+    let _ = main as *mut str;
+    let _ = &f as *mut f32;
+    let _ = &f as *const f64;
+    let _ = fat_sv as usize;
+
+    let a : *const str = "hello";
+    let _ = a as *const Foo;
+
+    // check no error cascade
+    let _ = main.f as *const u32;
+
+    let cf: *const Foo = &0;
+    let _ = cf as *const [u16];
+    let _ = cf as *const Bar;
+
+    vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+}
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr
new file mode 100644 (file)
index 0000000..7fd10f3
--- /dev/null
@@ -0,0 +1,240 @@
+error: casting `*const U` as `*const V` is invalid
+  --> $DIR/cast-rfc0401.rs:13:5
+   |
+13 |     u as *const V
+   |     ^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error: casting `*const U` as `*const str` is invalid
+  --> $DIR/cast-rfc0401.rs:18:5
+   |
+18 |     u as *const str
+   |     ^^^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error: no field `f` on type `fn() {main}`
+  --> $DIR/cast-rfc0401.rs:75:18
+   |
+75 |     let _ = main.f as *const u32;
+   |                  ^
+
+error: non-scalar cast: `*const u8` as `&u8`
+  --> $DIR/cast-rfc0401.rs:39:13
+   |
+39 |     let _ = v as &u8;
+   |             ^^^^^^^^
+
+error: non-scalar cast: `*const u8` as `E`
+  --> $DIR/cast-rfc0401.rs:40:13
+   |
+40 |     let _ = v as E;
+   |             ^^^^^^
+
+error: non-scalar cast: `*const u8` as `fn()`
+  --> $DIR/cast-rfc0401.rs:41:13
+   |
+41 |     let _ = v as fn();
+   |             ^^^^^^^^^
+
+error: non-scalar cast: `*const u8` as `(u32,)`
+  --> $DIR/cast-rfc0401.rs:42:13
+   |
+42 |     let _ = v as (u32,);
+   |             ^^^^^^^^^^^
+
+error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8`
+  --> $DIR/cast-rfc0401.rs:43:13
+   |
+43 |     let _ = Some(&v) as *const u8;
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `*const u8` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:45:13
+   |
+45 |     let _ = v as f32;
+   |             ^^^^^^^^
+
+error: casting `fn() {main}` as `f64` is invalid
+  --> $DIR/cast-rfc0401.rs:46:13
+   |
+46 |     let _ = main as f64;
+   |             ^^^^^^^^^^^
+
+error: casting `&*const u8` as `usize` is invalid
+  --> $DIR/cast-rfc0401.rs:47:13
+   |
+47 |     let _ = &v as usize;
+   |             ^^^^^^^^^^^
+   |
+   = help: cast through a raw pointer first
+
+error: casting `f32` as `*const u8` is invalid
+  --> $DIR/cast-rfc0401.rs:48:13
+   |
+48 |     let _ = f as *const u8;
+   |             ^^^^^^^^^^^^^^
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-rfc0401.rs:49:13
+   |
+49 |     let _ = 3_i32 as bool;
+   |             ^^^^^^^^^^^^^ unsupported cast
+   |
+   = help: compare with zero instead
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-rfc0401.rs:50:13
+   |
+50 |     let _ = E::A as bool;
+   |             ^^^^^^^^^^^^ unsupported cast
+   |
+   = help: compare with zero instead
+
+error: only `u8` can be cast as `char`, not `u32`
+  --> $DIR/cast-rfc0401.rs:51:13
+   |
+51 |     let _ = 0x61u32 as char;
+   |             ^^^^^^^^^^^^^^^
+
+error: casting `bool` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:53:13
+   |
+53 |     let _ = false as f32;
+   |             ^^^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error: casting `E` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:54:13
+   |
+54 |     let _ = E::A as f32;
+   |             ^^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error: casting `char` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:55:13
+   |
+55 |     let _ = 'a' as f32;
+   |             ^^^^^^^^^^
+   |
+   = help: cast through an integer first
+
+error: casting `bool` as `*const u8` is invalid
+  --> $DIR/cast-rfc0401.rs:57:13
+   |
+57 |     let _ = false as *const u8;
+   |             ^^^^^^^^^^^^^^^^^^
+
+error: casting `E` as `*const u8` is invalid
+  --> $DIR/cast-rfc0401.rs:58:13
+   |
+58 |     let _ = E::A as *const u8;
+   |             ^^^^^^^^^^^^^^^^^
+
+error: casting `char` as `*const u8` is invalid
+  --> $DIR/cast-rfc0401.rs:59:13
+   |
+59 |     let _ = 'a' as *const u8;
+   |             ^^^^^^^^^^^^^^^^
+
+error: casting `usize` as `*const [u8]` is invalid
+  --> $DIR/cast-rfc0401.rs:61:13
+   |
+61 |     let _ = 42usize as *const [u8];
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
+  --> $DIR/cast-rfc0401.rs:62:13
+   |
+62 |     let _ = v as *const [u8];
+   |             ^^^^^^^^^^^^^^^^
+
+error: casting `&Foo` as `*const str` is invalid
+  --> $DIR/cast-rfc0401.rs:64:13
+   |
+64 |     let _ = foo as *const str;
+   |             ^^^^^^^^^^^^^^^^^
+
+error: casting `&Foo` as `*mut str` is invalid
+  --> $DIR/cast-rfc0401.rs:65:13
+   |
+65 |     let _ = foo as *mut str;
+   |             ^^^^^^^^^^^^^^^
+
+error: casting `fn() {main}` as `*mut str` is invalid
+  --> $DIR/cast-rfc0401.rs:66:13
+   |
+66 |     let _ = main as *mut str;
+   |             ^^^^^^^^^^^^^^^^
+
+error: casting `&f32` as `*mut f32` is invalid
+  --> $DIR/cast-rfc0401.rs:67:13
+   |
+67 |     let _ = &f as *mut f32;
+   |             ^^^^^^^^^^^^^^
+
+error: casting `&f32` as `*const f64` is invalid
+  --> $DIR/cast-rfc0401.rs:68:13
+   |
+68 |     let _ = &f as *const f64;
+   |             ^^^^^^^^^^^^^^^^
+
+error: casting `*const [i8]` as `usize` is invalid
+  --> $DIR/cast-rfc0401.rs:69:13
+   |
+69 |     let _ = fat_sv as usize;
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: cast through a thin pointer first
+
+error: casting `*const Foo` as `*const [u16]` is invalid
+  --> $DIR/cast-rfc0401.rs:78:13
+   |
+78 |     let _ = cf as *const [u16];
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error: casting `*const Foo` as `*const Bar` is invalid
+  --> $DIR/cast-rfc0401.rs:79:13
+   |
+79 |     let _ = cf as *const Bar;
+   |             ^^^^^^^^^^^^^^^^
+   |
+   = note: vtable kinds may not match
+
+error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
+  --> $DIR/cast-rfc0401.rs:63:13
+   |
+63 |     let _ = fat_v as *const Foo;
+   |             ^^^^^ the trait `std::marker::Sized` is not implemented for `[u8]`
+   |
+   = note: `[u8]` does not have a constant size known at compile-time
+   = note: required for the cast to the object type `Foo`
+
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+  --> $DIR/cast-rfc0401.rs:72:13
+   |
+72 |     let _ = a as *const Foo;
+   |             ^ the trait `std::marker::Sized` is not implemented for `str`
+   |
+   = note: `str` does not have a constant size known at compile-time
+   = note: required for the cast to the object type `Foo`
+
+error: casting `&{float}` as `f32` is invalid
+  --> $DIR/cast-rfc0401.rs:81:30
+   |
+81 |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+   |                              ^^^^^^^^ cannot cast `&{float}` as `f32`
+   |
+help: did you mean `*s`?
+  --> $DIR/cast-rfc0401.rs:81:30
+   |
+81 |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+   |                              ^
+
+error: aborting due to 34 previous errors
+