提交 b2c31300 编写于 作者: C Corey Farwell 提交者: GitHub

Rollup merge of #42519 - GuillaumeGomez:create-more-error-codes, r=QuietMisdreavus

Create more error codes

Fixes #31174.
Part of #42229.

cc @Susurrus
......@@ -40,9 +40,11 @@
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> {
type_error_struct!(sess, span, expr_ty, 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")
......@@ -205,51 +212,23 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
.emit();
}
CastError::CastToChar => {
fcx.type_error_message(self.span,
|actual| {
format!("only `u8` can be cast as `char`, not `{}`",
actual)
},
self.expr_ty);
type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604,
"only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit();
}
CastError::NonScalar => {
fcx.type_error_message(self.span,
|actual| {
format!("non-scalar cast: `{}` as `{}`",
actual,
fcx.ty_to_string(self.cast_ty))
},
self.expr_ty);
}
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);
type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605,
"non-primitive cast: `{}` as `{}`",
self.expr_ty,
fcx.ty_to_string(self.cast_ty))
.note("an `as` expression can only be used to convert between \
primitive types. Consider using the `From` trait")
.emit();
}
CastError::SizedUnsizedCast => {
fcx.type_error_message(self.span,
|actual| {
format!("cannot cast thin pointer `{}` to fat pointer \
`{}`",
actual,
fcx.ty_to_string(self.cast_ty))
},
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();
type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607,
"cannot cast thin pointer `{}` to fat pointer `{}`",
self.expr_ty,
fcx.ty_to_string(self.cast_ty)).emit();
}
}
}
......
......@@ -4208,6 +4208,104 @@ trait was performed.
```
"##,
E0604: r##"
A cast to `char` was attempted on a type other than `u8`.
Erroneous code example:
```compile_fail,E0604
0u32 as char; // error: only `u8` can be cast as `char`, not `u32`
```
As the error message indicates, only `u8` can be cast into `char`. Example:
```
let c = 86u8 as char; // ok!
assert_eq!(c, 'V');
```
For more information about casts, take a look at The Book:
https://doc.rust-lang.org/book/first-edition/casting-between-types.html
"##,
E0605: r##"
An invalid cast was attempted.
Erroneous code examples:
```compile_fail,E0605
let x = 0u8;
x as Vec<u8>; // error: non-primitive cast: `u8` as `std::vec::Vec<u8>`
// Another example
let v = 0 as *const u8; // So here, `v` is a `*const u8`.
v as &u8; // error: non-primitive cast: `*const u8` as `&u8`
```
Only primitive types can be cast into each other. Examples:
```
let x = 0u8;
x as u32; // ok!
let v = 0 as *const u8;
v as *const i8; // ok!
```
For more information about casts, take a look at The Book:
https://doc.rust-lang.org/book/first-edition/casting-between-types.html
"##,
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 can be cast into each
other. Example:
```
let x = &0u8;
let y: u32 = *x as u32; // We dereference it first and then cast it.
```
For more information about casts, take a look at The Book:
https://doc.rust-lang.org/book/first-edition/casting-between-types.html
"##,
E0607: r##"
A cast between a thin and a fat pointer was attempted.
Erroneous code example:
```compile_fail,E0607
let v = 0 as *const u8;
v as *const [u8];
```
First: what are thin and fat pointers?
Thin pointers are "simple" pointers: they are purely a reference to a memory
address.
Fat pointers are pointers referencing Dynamically Sized Types (also called DST).
DST don't have a statically known size, therefore they can only exist behind
some kind of pointers that contain additional information. Slices and trait
objects are DSTs. In the case of slices, the additional information the fat
pointer holds is their size.
To fix this error, don't try to cast directly between thin and fat pointers.
For more information about casts, take a look at The Book:
https://doc.rust-lang.org/book/first-edition/casting-between-types.html
"##,
E0609: r##"
Attempted to access a non-existent field in a struct.
......
// 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() {
1u32 as char; //~ ERROR E0604
}
// 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() {
let x = 0u8;
x as Vec<u8>; //~ ERROR E0605
//~| NOTE an `as` expression can only be used to convert between primitive types
let v = 0 as *const u8;
v as &u8; //~ ERROR E0605
//~| NOTE an `as` expression can only be used to convert between primitive types
}
// 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
}
// 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() {
let v = 0 as *const u8;
v as *const [u8]; //~ ERROR E0607
}
......@@ -8,5 +8,5 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: non-scalar cast: `()` as `u32`
// error-pattern: non-primitive cast: `()` as `u32`
fn main() { let u = (assert!(true) as u32); }
......@@ -13,8 +13,8 @@ fn foo(_x: isize) { }
fn main() {
let v: u64 = 5;
let x = foo as extern "C" fn() -> isize;
//~^ ERROR non-scalar cast
//~^ ERROR non-primitive cast
let y = v as extern "Rust" fn(isize) -> (isize, isize);
//~^ ERROR non-scalar cast
//~^ ERROR non-primitive cast
y(x());
}
......@@ -8,5 +8,5 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: non-scalar cast: `u32` as `()`
// error-pattern: non-primitive cast: `u32` as `()`
fn main() { let u = 0u32 as (); }
......@@ -14,5 +14,5 @@
fn main() {
let b = 0u8;
let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
//~^ ERROR non-scalar cast
//~^ ERROR non-primitive cast
}
......@@ -17,7 +17,7 @@ fn cast_a() {
}
fn cast_b() {
let y = 22 as !; //~ ERROR non-scalar cast
let y = 22 as !; //~ ERROR non-primitive cast
}
fn main() { }
......@@ -22,7 +22,7 @@ fn main() {
a as isize; //~ ERROR casting
a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
b as usize; //~ ERROR non-scalar cast
b as usize; //~ ERROR non-primitive cast
p as usize;
//~^ ERROR casting
//~^^ HELP cast through a thin pointer
......
......@@ -10,5 +10,5 @@
fn main() {
let nil = ();
let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize`
let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize`
}
......@@ -9,5 +9,5 @@
// except according to those terms.
fn main() {
0 as &std::any::Any; //~ ERROR non-scalar cast
0 as &std::any::Any; //~ ERROR non-primitive cast
}
......@@ -19,7 +19,7 @@ fn get<'a>(&'a self, y: usize, x: usize) -> Option<&'a <Self as Index<usize>>::O
}
let i = y * self.columns() + x;
let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
//~^ERROR non-scalar cast
//~^ERROR non-primitive cast
Some(indexer.index(i))
}
}
......
......@@ -9,7 +9,7 @@
// except according to those terms.
fn bad (p: *const isize) {
let _q: &isize = p as &isize; //~ ERROR non-scalar cast
let _q: &isize = p as &isize; //~ ERROR non-primitive cast
}
fn main() { }
......@@ -8,13 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:non-scalar cast
#[derive(Debug)]
struct foo {
x: isize
}
fn main() {
println!("{}", foo{ x: 1 } as isize);
println!("{}", foo{ x: 1 } as isize); //~ non-primitive cast: `foo` as `isize` [E0605]
}
......@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//error-pattern: non-scalar cast
enum non_nullary {
nullary,
other(isize),
......@@ -17,5 +15,5 @@ enum non_nullary {
fn main() {
let v = non_nullary::nullary;
let val = v as isize;
let val = v as isize; //~ ERROR non-primitive cast: `non_nullary` as `isize` [E0605]
}
......@@ -11,7 +11,7 @@
enum E {}
fn f(e: E) {
println!("{}", (e as isize).to_string()); //~ ERROR non-scalar cast
println!("{}", (e as isize).to_string()); //~ ERROR non-primitive cast
}
fn main() {}
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
......@@ -20,49 +20,59 @@ error[E0609]: no field `f` on type `fn() {main}`
75 | let _ = main.f as *const u32;
| ^
error: non-scalar cast: `*const u8` as `&u8`
error[E0605]: non-primitive cast: `*const u8` as `&u8`
--> $DIR/cast-rfc0401.rs:39:13
|
39 | let _ = v as &u8;
| ^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
error: non-scalar cast: `*const u8` as `E`
error[E0605]: non-primitive cast: `*const u8` as `E`
--> $DIR/cast-rfc0401.rs:40:13
|
40 | let _ = v as E;
| ^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
error: non-scalar cast: `*const u8` as `fn()`
error[E0605]: non-primitive cast: `*const u8` as `fn()`
--> $DIR/cast-rfc0401.rs:41:13
|
41 | let _ = v as fn();
| ^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
error: non-scalar cast: `*const u8` as `(u32,)`
error[E0605]: non-primitive cast: `*const u8` as `(u32,)`
--> $DIR/cast-rfc0401.rs:42:13
|
42 | let _ = v as (u32,);
| ^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8`
error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8`
--> $DIR/cast-rfc0401.rs:43:13
|
43 | let _ = Some(&v) 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;
......@@ -70,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;
......@@ -92,13 +102,13 @@ error[E0054]: cannot cast as `bool`
|
= help: compare with zero instead
error: only `u8` can be cast as `char`, not `u32`
error[E0604]: 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
error[E0606]: casting `bool` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:53:13
|
53 | let _ = false as f32;
......@@ -106,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;
......@@ -114,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;
......@@ -122,67 +132,67 @@ 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];
| ^^^^^^^^^^^^^^^^^^^^^^
error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
error[E0607]: 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
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;
......@@ -190,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];
......@@ -198,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;
......@@ -224,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>>();
......
......@@ -7,7 +7,7 @@ error[E0308]: mismatched types
37 | write!(hello);
| -------------- in this macro invocation
error: non-scalar cast: `{integer}` as `()`
error[E0605]: non-primitive cast: `{integer}` as `()`
--> $DIR/issue-26480.rs:32:19
|
32 | ($x:expr) => ($x as ())
......@@ -15,6 +15,8 @@ error: non-scalar cast: `{integer}` as `()`
...
38 | cast!(2);
| --------- in this macro invocation
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
error: aborting due to previous error(s)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册