]> git.lizzy.rs Git - rust.git/commitdiff
Add E0606
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Wed, 7 Jun 2017 21:54:51 +0000 (23:54 +0200)
committerGuillaume Gomez <guillaume1.gomez@gmail.com>
Sat, 24 Jun 2017 19:27:45 +0000 (21:27 +0200)
src/librustc_typeck/check/cast.rs
src/librustc_typeck/diagnostics.rs
src/test/compile-fail/E0606.rs [new file with mode: 0644]
src/test/ui/mismatched_types/cast-rfc0401.stderr

index 69174dacaaa07fa7d79e541a2e8f59aca99f0270..5c255364311132eb91492781632481c916d90879 100644 (file)
 
 use super::{Diverges, FnCtxt};
 
-use lint;
+use errors::DiagnosticBuilder;
 use hir::def_id::DefId;
+use lint;
 use rustc::hir;
+use rustc::session::Session;
 use rustc::traits;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::cast::{CastKind, CastTy};
@@ -112,6 +114,18 @@ enum CastError {
     NonScalar,
 }
 
+fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session,
+                                              span: Span,
+                                              expr_ty: Ty<'tcx>,
+                                              cast_ty: Ty<'tcx>,
+                                              fcx: &FnCtxt<'a, 'gcx, 'tcx>)
+                                              -> DiagnosticBuilder<'a> {
+    struct_span_err!(sess, span, E0606,
+                     "casting `{}` as `{}` is invalid",
+                     fcx.ty_to_string(expr_ty),
+                     fcx.ty_to_string(cast_ty))
+}
+
 impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
     pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                expr: &'tcx hir::Expr,
@@ -146,14 +160,9 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
         match e {
             CastError::NeedDeref => {
                 let error_span = self.span;
+                let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
+                                                         self.cast_ty, fcx);
                 let cast_ty = fcx.ty_to_string(self.cast_ty);
-                let mut err = fcx.type_error_struct(error_span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   cast_ty)
-                                       },
-                                       self.expr_ty);
                 err.span_label(error_span,
                                format!("cannot cast `{}` as `{}`",
                                         fcx.ty_to_string(self.expr_ty),
@@ -166,13 +175,8 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
             }
             CastError::NeedViaThinPtr |
             CastError::NeedViaPtr => {
-                let mut err = fcx.type_error_struct(self.span,
-                                                    |actual| {
-                                                        format!("casting `{}` as `{}` is invalid",
-                                                                actual,
-                                                                fcx.ty_to_string(self.cast_ty))
-                                                    },
-                                                    self.expr_ty);
+                let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
+                                                         self.cast_ty, fcx);
                 if self.cast_ty.is_uint() {
                     err.help(&format!("cast through {} first",
                                       match e {
@@ -184,13 +188,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                 err.emit();
             }
             CastError::NeedViaInt => {
-                fcx.type_error_struct(self.span,
-                                      |actual| {
-                                          format!("casting `{}` as `{}` is invalid",
-                                                  actual,
-                                                  fcx.ty_to_string(self.cast_ty))
-                                      },
-                                      self.expr_ty)
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
                    .help(&format!("cast through {} first",
                                   match e {
                                       CastError::NeedViaInt => "an integer",
@@ -198,6 +196,15 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                                   }))
                    .emit();
             }
+            CastError::IllegalCast => {
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
+                    .emit();
+            }
+            CastError::DifferingKinds => {
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
+                    .note("vtable kinds may not match")
+                    .emit();
+            }
             CastError::CastToBool => {
                 struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
                     .span_label(self.span, "unsupported cast")
@@ -217,15 +224,6 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                                        primitive types. Consider using the `From` trait")
                                 .emit();
             }
-            CastError::IllegalCast => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty);
-            }
             CastError::SizedUnsizedCast => {
                 fcx.type_error_message(self.span,
                                        |actual| {
@@ -236,17 +234,6 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                                        },
                                        self.expr_ty)
             }
-            CastError::DifferingKinds => {
-                fcx.type_error_struct(self.span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty)
-                    .note("vtable kinds may not match")
-                    .emit();
-            }
         }
     }
 
index a787aadc6781c21a4b9dcb80288b36df2a4a6323..d3138af978aa7337d417ef329eccb2849e4d65a2 100644 (file)
@@ -4251,6 +4251,25 @@ trait was performed.
 ```
 "##,
 
+E0606: r##"
+An incompatible cast was attempted.
+
+Erroneous code example:
+
+```compile_fail,E0606
+let x = &0u8; // Here, `x` is a `&u8`.
+let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid
+```
+
+When casting, keep in mind that only primitive types cast be casted into each
+others. Example:
+
+```
+let x = &0u8;
+let y: u32 = *x as u32; // We dereference it first and then cast it.
+```
+"##,
+
 E0609: r##"
 Attempted to access a non-existent field in a struct.
 
diff --git a/src/test/compile-fail/E0606.rs b/src/test/compile-fail/E0606.rs
new file mode 100644 (file)
index 0000000..5507173
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 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 main() {
+    &0u8 as u8; //~ ERROR E0606
+}
index c79d242dc5e1991859f1b4eb752615d77ffd162b..b4c3106253e14fbc98382dba32f0950fc009eca2 100644 (file)
@@ -1,4 +1,4 @@
-error: casting `*const U` as `*const V` is invalid
+error[E0606]: casting `*const U` as `*const V` is invalid
   --> $DIR/cast-rfc0401.rs:13:5
    |
 13 |     u as *const V
@@ -6,7 +6,7 @@ error: casting `*const U` as `*const V` is invalid
    |
    = note: vtable kinds may not match
 
-error: casting `*const U` as `*const str` is invalid
+error[E0606]: casting `*const U` as `*const str` is invalid
   --> $DIR/cast-rfc0401.rs:18:5
    |
 18 |     u as *const str
@@ -60,19 +60,19 @@ error[E0605]: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8`
    |
    = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: casting `*const u8` as `f32` is invalid
+error[E0606]: 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
+error[E0606]: 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
+error[E0606]: casting `&*const u8` as `usize` is invalid
   --> $DIR/cast-rfc0401.rs:47:13
    |
 47 |     let _ = &v as usize;
@@ -80,7 +80,7 @@ error: casting `&*const u8` as `usize` is invalid
    |
    = help: cast through a raw pointer first
 
-error: casting `f32` as `*const u8` is invalid
+error[E0606]: casting `f32` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:48:13
    |
 48 |     let _ = f as *const u8;
@@ -108,7 +108,7 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
 51 |     let _ = 0x61u32 as char;
    |             ^^^^^^^^^^^^^^^
 
-error: casting `bool` as `f32` is invalid
+error[E0606]: casting `bool` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:53:13
    |
 53 |     let _ = false as f32;
@@ -116,7 +116,7 @@ error: casting `bool` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `E` as `f32` is invalid
+error[E0606]: casting `E` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:54:13
    |
 54 |     let _ = E::A as f32;
@@ -124,7 +124,7 @@ error: casting `E` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `char` as `f32` is invalid
+error[E0606]: casting `char` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:55:13
    |
 55 |     let _ = 'a' as f32;
@@ -132,25 +132,25 @@ error: casting `char` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `bool` as `*const u8` is invalid
+error[E0606]: 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
+error[E0606]: 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
+error[E0606]: 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
+error[E0606]: casting `usize` as `*const [u8]` is invalid
   --> $DIR/cast-rfc0401.rs:61:13
    |
 61 |     let _ = 42usize as *const [u8];
@@ -162,37 +162,37 @@ error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
 62 |     let _ = v as *const [u8];
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `&Foo` as `*const str` is invalid
+error[E0606]: 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
+error[E0606]: 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
+error[E0606]: 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
+error[E0606]: 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
+error[E0606]: 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
+error[E0606]: casting `*const [i8]` as `usize` is invalid
   --> $DIR/cast-rfc0401.rs:69:13
    |
 69 |     let _ = fat_sv as usize;
@@ -200,7 +200,7 @@ error: casting `*const [i8]` as `usize` is invalid
    |
    = help: cast through a thin pointer first
 
-error: casting `*const Foo` as `*const [u16]` is invalid
+error[E0606]: casting `*const Foo` as `*const [u16]` is invalid
   --> $DIR/cast-rfc0401.rs:78:13
    |
 78 |     let _ = cf as *const [u16];
@@ -208,7 +208,7 @@ error: casting `*const Foo` as `*const [u16]` is invalid
    |
    = note: vtable kinds may not match
 
-error: casting `*const Foo` as `*const Bar` is invalid
+error[E0606]: casting `*const Foo` as `*const Bar` is invalid
   --> $DIR/cast-rfc0401.rs:79:13
    |
 79 |     let _ = cf as *const Bar;
@@ -234,7 +234,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
    = help: the trait `std::marker::Sized` is not implemented for `str`
    = note: required for the cast to the object type `Foo`
 
-error: casting `&{float}` as `f32` is invalid
+error[E0606]: 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>>();