Skip to content

Commit b2c3130

Browse files
authored
Rollup merge of #42519 - GuillaumeGomez:create-more-error-codes, r=QuietMisdreavus
Create more error codes Fixes #31174. Part of #42229. cc @Susurrus
2 parents 77931c2 + bcf0d60 commit b2c3130

21 files changed

+255
-111
lines changed

src/librustc_typeck/check/cast.rs

Lines changed: 42 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@
4040
4141
use super::{Diverges, FnCtxt};
4242

43-
use lint;
43+
use errors::DiagnosticBuilder;
4444
use hir::def_id::DefId;
45+
use lint;
4546
use rustc::hir;
47+
use rustc::session::Session;
4648
use rustc::traits;
4749
use rustc::ty::{self, Ty, TypeFoldable};
4850
use rustc::ty::cast::{CastKind, CastTy};
@@ -112,6 +114,18 @@ enum CastError {
112114
NonScalar,
113115
}
114116

117+
fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session,
118+
span: Span,
119+
expr_ty: Ty<'tcx>,
120+
cast_ty: Ty<'tcx>,
121+
fcx: &FnCtxt<'a, 'gcx, 'tcx>)
122+
-> DiagnosticBuilder<'a> {
123+
type_error_struct!(sess, span, expr_ty, E0606,
124+
"casting `{}` as `{}` is invalid",
125+
fcx.ty_to_string(expr_ty),
126+
fcx.ty_to_string(cast_ty))
127+
}
128+
115129
impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
116130
pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
117131
expr: &'tcx hir::Expr,
@@ -146,14 +160,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
146160
match e {
147161
CastError::NeedDeref => {
148162
let error_span = self.span;
163+
let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
164+
self.cast_ty, fcx);
149165
let cast_ty = fcx.ty_to_string(self.cast_ty);
150-
let mut err = fcx.type_error_struct(error_span,
151-
|actual| {
152-
format!("casting `{}` as `{}` is invalid",
153-
actual,
154-
cast_ty)
155-
},
156-
self.expr_ty);
157166
err.span_label(error_span,
158167
format!("cannot cast `{}` as `{}`",
159168
fcx.ty_to_string(self.expr_ty),
@@ -166,13 +175,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
166175
}
167176
CastError::NeedViaThinPtr |
168177
CastError::NeedViaPtr => {
169-
let mut err = fcx.type_error_struct(self.span,
170-
|actual| {
171-
format!("casting `{}` as `{}` is invalid",
172-
actual,
173-
fcx.ty_to_string(self.cast_ty))
174-
},
175-
self.expr_ty);
178+
let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
179+
self.cast_ty, fcx);
176180
if self.cast_ty.is_uint() {
177181
err.help(&format!("cast through {} first",
178182
match e {
@@ -184,72 +188,47 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
184188
err.emit();
185189
}
186190
CastError::NeedViaInt => {
187-
fcx.type_error_struct(self.span,
188-
|actual| {
189-
format!("casting `{}` as `{}` is invalid",
190-
actual,
191-
fcx.ty_to_string(self.cast_ty))
192-
},
193-
self.expr_ty)
191+
make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
194192
.help(&format!("cast through {} first",
195193
match e {
196194
CastError::NeedViaInt => "an integer",
197195
_ => bug!(),
198196
}))
199197
.emit();
200198
}
199+
CastError::IllegalCast => {
200+
make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
201+
.emit();
202+
}
203+
CastError::DifferingKinds => {
204+
make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
205+
.note("vtable kinds may not match")
206+
.emit();
207+
}
201208
CastError::CastToBool => {
202209
struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
203210
.span_label(self.span, "unsupported cast")
204211
.help("compare with zero instead")
205212
.emit();
206213
}
207214
CastError::CastToChar => {
208-
fcx.type_error_message(self.span,
209-
|actual| {
210-
format!("only `u8` can be cast as `char`, not `{}`",
211-
actual)
212-
},
213-
self.expr_ty);
215+
type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604,
216+
"only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit();
214217
}
215218
CastError::NonScalar => {
216-
fcx.type_error_message(self.span,
217-
|actual| {
218-
format!("non-scalar cast: `{}` as `{}`",
219-
actual,
220-
fcx.ty_to_string(self.cast_ty))
221-
},
222-
self.expr_ty);
223-
}
224-
CastError::IllegalCast => {
225-
fcx.type_error_message(self.span,
226-
|actual| {
227-
format!("casting `{}` as `{}` is invalid",
228-
actual,
229-
fcx.ty_to_string(self.cast_ty))
230-
},
231-
self.expr_ty);
219+
type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605,
220+
"non-primitive cast: `{}` as `{}`",
221+
self.expr_ty,
222+
fcx.ty_to_string(self.cast_ty))
223+
.note("an `as` expression can only be used to convert between \
224+
primitive types. Consider using the `From` trait")
225+
.emit();
232226
}
233227
CastError::SizedUnsizedCast => {
234-
fcx.type_error_message(self.span,
235-
|actual| {
236-
format!("cannot cast thin pointer `{}` to fat pointer \
237-
`{}`",
238-
actual,
239-
fcx.ty_to_string(self.cast_ty))
240-
},
241-
self.expr_ty)
242-
}
243-
CastError::DifferingKinds => {
244-
fcx.type_error_struct(self.span,
245-
|actual| {
246-
format!("casting `{}` as `{}` is invalid",
247-
actual,
248-
fcx.ty_to_string(self.cast_ty))
249-
},
250-
self.expr_ty)
251-
.note("vtable kinds may not match")
252-
.emit();
228+
type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607,
229+
"cannot cast thin pointer `{}` to fat pointer `{}`",
230+
self.expr_ty,
231+
fcx.ty_to_string(self.cast_ty)).emit();
253232
}
254233
}
255234
}

src/librustc_typeck/diagnostics.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4208,6 +4208,104 @@ println!("{}", v[2]);
42084208
```
42094209
"##,
42104210

4211+
E0604: r##"
4212+
A cast to `char` was attempted on a type other than `u8`.
4213+
4214+
Erroneous code example:
4215+
4216+
```compile_fail,E0604
4217+
0u32 as char; // error: only `u8` can be cast as `char`, not `u32`
4218+
```
4219+
4220+
As the error message indicates, only `u8` can be cast into `char`. Example:
4221+
4222+
```
4223+
let c = 86u8 as char; // ok!
4224+
assert_eq!(c, 'V');
4225+
```
4226+
4227+
For more information about casts, take a look at The Book:
4228+
https://doc.rust-lang.org/book/first-edition/casting-between-types.html
4229+
"##,
4230+
4231+
E0605: r##"
4232+
An invalid cast was attempted.
4233+
4234+
Erroneous code examples:
4235+
4236+
```compile_fail,E0605
4237+
let x = 0u8;
4238+
x as Vec<u8>; // error: non-primitive cast: `u8` as `std::vec::Vec<u8>`
4239+
4240+
// Another example
4241+
4242+
let v = 0 as *const u8; // So here, `v` is a `*const u8`.
4243+
v as &u8; // error: non-primitive cast: `*const u8` as `&u8`
4244+
```
4245+
4246+
Only primitive types can be cast into each other. Examples:
4247+
4248+
```
4249+
let x = 0u8;
4250+
x as u32; // ok!
4251+
4252+
let v = 0 as *const u8;
4253+
v as *const i8; // ok!
4254+
```
4255+
4256+
For more information about casts, take a look at The Book:
4257+
https://doc.rust-lang.org/book/first-edition/casting-between-types.html
4258+
"##,
4259+
4260+
E0606: r##"
4261+
An incompatible cast was attempted.
4262+
4263+
Erroneous code example:
4264+
4265+
```compile_fail,E0606
4266+
let x = &0u8; // Here, `x` is a `&u8`.
4267+
let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid
4268+
```
4269+
4270+
When casting, keep in mind that only primitive types can be cast into each
4271+
other. Example:
4272+
4273+
```
4274+
let x = &0u8;
4275+
let y: u32 = *x as u32; // We dereference it first and then cast it.
4276+
```
4277+
4278+
For more information about casts, take a look at The Book:
4279+
https://doc.rust-lang.org/book/first-edition/casting-between-types.html
4280+
"##,
4281+
4282+
E0607: r##"
4283+
A cast between a thin and a fat pointer was attempted.
4284+
4285+
Erroneous code example:
4286+
4287+
```compile_fail,E0607
4288+
let v = 0 as *const u8;
4289+
v as *const [u8];
4290+
```
4291+
4292+
First: what are thin and fat pointers?
4293+
4294+
Thin pointers are "simple" pointers: they are purely a reference to a memory
4295+
address.
4296+
4297+
Fat pointers are pointers referencing Dynamically Sized Types (also called DST).
4298+
DST don't have a statically known size, therefore they can only exist behind
4299+
some kind of pointers that contain additional information. Slices and trait
4300+
objects are DSTs. In the case of slices, the additional information the fat
4301+
pointer holds is their size.
4302+
4303+
To fix this error, don't try to cast directly between thin and fat pointers.
4304+
4305+
For more information about casts, take a look at The Book:
4306+
https://doc.rust-lang.org/book/first-edition/casting-between-types.html
4307+
"##,
4308+
42114309
E0609: r##"
42124310
Attempted to access a non-existent field in a struct.
42134311

src/test/compile-fail/E0604.rs

Lines changed: 13 additions & 0 deletions
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+
1u32 as char; //~ ERROR E0604
13+
}

src/test/compile-fail/E0605.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
let x = 0u8;
13+
x as Vec<u8>; //~ ERROR E0605
14+
//~| NOTE an `as` expression can only be used to convert between primitive types
15+
16+
let v = 0 as *const u8;
17+
v as &u8; //~ ERROR E0605
18+
//~| NOTE an `as` expression can only be used to convert between primitive types
19+
}

src/test/compile-fail/E0606.rs

Lines changed: 13 additions & 0 deletions
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+
&0u8 as u8; //~ ERROR E0606
13+
}

src/test/compile-fail/E0607.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
let v = 0 as *const u8;
13+
v as *const [u8]; //~ ERROR E0607
14+
}

src/test/compile-fail/cast-from-nil.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern: non-scalar cast: `()` as `u32`
11+
// error-pattern: non-primitive cast: `()` as `u32`
1212
fn main() { let u = (assert!(true) as u32); }

src/test/compile-fail/cast-to-bare-fn.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ fn foo(_x: isize) { }
1313
fn main() {
1414
let v: u64 = 5;
1515
let x = foo as extern "C" fn() -> isize;
16-
//~^ ERROR non-scalar cast
16+
//~^ ERROR non-primitive cast
1717
let y = v as extern "Rust" fn(isize) -> (isize, isize);
18-
//~^ ERROR non-scalar cast
18+
//~^ ERROR non-primitive cast
1919
y(x());
2020
}

src/test/compile-fail/cast-to-nil.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern: non-scalar cast: `u32` as `()`
11+
// error-pattern: non-primitive cast: `u32` as `()`
1212
fn main() { let u = 0u32 as (); }

src/test/compile-fail/closure-no-fn-3.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414
fn main() {
1515
let b = 0u8;
1616
let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
17-
//~^ ERROR non-scalar cast
17+
//~^ ERROR non-primitive cast
1818
}

src/test/compile-fail/coerce-to-bang-cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn cast_a() {
1717
}
1818

1919
fn cast_b() {
20-
let y = 22 as !; //~ ERROR non-scalar cast
20+
let y = 22 as !; //~ ERROR non-primitive cast
2121
}
2222

2323
fn main() { }

src/test/compile-fail/fat-ptr-cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn main() {
2222
a as isize; //~ ERROR casting
2323
a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
2424
a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
25-
b as usize; //~ ERROR non-scalar cast
25+
b as usize; //~ ERROR non-primitive cast
2626
p as usize;
2727
//~^ ERROR casting
2828
//~^^ HELP cast through a thin pointer

src/test/compile-fail/issue-10991.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010

1111
fn main() {
1212
let nil = ();
13-
let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize`
13+
let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize`
1414
}

src/test/compile-fail/issue-22289.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
0 as &std::any::Any; //~ ERROR non-scalar cast
12+
0 as &std::any::Any; //~ ERROR non-primitive cast
1313
}

0 commit comments

Comments
 (0)