Skip to content

Commit 30effc1

Browse files
Add E0606
1 parent 0e4b8ff commit 30effc1

File tree

4 files changed

+83
-64
lines changed

4 files changed

+83
-64
lines changed

src/librustc_typeck/check/cast.rs

Lines changed: 29 additions & 42 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+
struct_span_err!(sess, span, 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,20 +188,23 @@ 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")
@@ -217,15 +224,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
217224
primitive types. Consider using the `From` trait")
218225
.emit();
219226
}
220-
CastError::IllegalCast => {
221-
fcx.type_error_message(self.span,
222-
|actual| {
223-
format!("casting `{}` as `{}` is invalid",
224-
actual,
225-
fcx.ty_to_string(self.cast_ty))
226-
},
227-
self.expr_ty);
228-
}
229227
CastError::SizedUnsizedCast => {
230228
fcx.type_error_message(self.span,
231229
|actual| {
@@ -236,17 +234,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
236234
},
237235
self.expr_ty)
238236
}
239-
CastError::DifferingKinds => {
240-
fcx.type_error_struct(self.span,
241-
|actual| {
242-
format!("casting `{}` as `{}` is invalid",
243-
actual,
244-
fcx.ty_to_string(self.cast_ty))
245-
},
246-
self.expr_ty)
247-
.note("vtable kinds may not match")
248-
.emit();
249-
}
250237
}
251238
}
252239

src/librustc_typeck/diagnostics.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4251,6 +4251,25 @@ v as *const i8; // ok!
42514251
```
42524252
"##,
42534253

4254+
E0606: r##"
4255+
An incompatible cast was attempted.
4256+
4257+
Erroneous code example:
4258+
4259+
```compile_fail,E0606
4260+
let x = &0u8; // Here, `x` is a `&u8`.
4261+
let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid
4262+
```
4263+
4264+
When casting, keep in mind that only primitive types cast be casted into each
4265+
others. Example:
4266+
4267+
```
4268+
let x = &0u8;
4269+
let y: u32 = *x as u32; // We dereference it first and then cast it.
4270+
```
4271+
"##,
4272+
42544273
E0609: r##"
42554274
Attempted to access a non-existent field in a struct.
42564275

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/ui/mismatched_types/cast-rfc0401.stderr

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
error: casting `*const U` as `*const V` is invalid
1+
error[E0606]: casting `*const U` as `*const V` is invalid
22
--> $DIR/cast-rfc0401.rs:13:5
33
|
44
13 | u as *const V
55
| ^^^^^^^^^^^^^
66
|
77
= note: vtable kinds may not match
88

9-
error: casting `*const U` as `*const str` is invalid
9+
error[E0606]: casting `*const U` as `*const str` is invalid
1010
--> $DIR/cast-rfc0401.rs:18:5
1111
|
1212
18 | u as *const str
@@ -60,27 +60,27 @@ error[E0605]: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8`
6060
|
6161
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
6262

63-
error: casting `*const u8` as `f32` is invalid
63+
error[E0606]: casting `*const u8` as `f32` is invalid
6464
--> $DIR/cast-rfc0401.rs:45:13
6565
|
6666
45 | let _ = v as f32;
6767
| ^^^^^^^^
6868

69-
error: casting `fn() {main}` as `f64` is invalid
69+
error[E0606]: casting `fn() {main}` as `f64` is invalid
7070
--> $DIR/cast-rfc0401.rs:46:13
7171
|
7272
46 | let _ = main as f64;
7373
| ^^^^^^^^^^^
7474

75-
error: casting `&*const u8` as `usize` is invalid
75+
error[E0606]: casting `&*const u8` as `usize` is invalid
7676
--> $DIR/cast-rfc0401.rs:47:13
7777
|
7878
47 | let _ = &v as usize;
7979
| ^^^^^^^^^^^
8080
|
8181
= help: cast through a raw pointer first
8282

83-
error: casting `f32` as `*const u8` is invalid
83+
error[E0606]: casting `f32` as `*const u8` is invalid
8484
--> $DIR/cast-rfc0401.rs:48:13
8585
|
8686
48 | let _ = f as *const u8;
@@ -108,49 +108,49 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
108108
51 | let _ = 0x61u32 as char;
109109
| ^^^^^^^^^^^^^^^
110110

111-
error: casting `bool` as `f32` is invalid
111+
error[E0606]: casting `bool` as `f32` is invalid
112112
--> $DIR/cast-rfc0401.rs:53:13
113113
|
114114
53 | let _ = false as f32;
115115
| ^^^^^^^^^^^^
116116
|
117117
= help: cast through an integer first
118118

119-
error: casting `E` as `f32` is invalid
119+
error[E0606]: casting `E` as `f32` is invalid
120120
--> $DIR/cast-rfc0401.rs:54:13
121121
|
122122
54 | let _ = E::A as f32;
123123
| ^^^^^^^^^^^
124124
|
125125
= help: cast through an integer first
126126

127-
error: casting `char` as `f32` is invalid
127+
error[E0606]: casting `char` as `f32` is invalid
128128
--> $DIR/cast-rfc0401.rs:55:13
129129
|
130130
55 | let _ = 'a' as f32;
131131
| ^^^^^^^^^^
132132
|
133133
= help: cast through an integer first
134134

135-
error: casting `bool` as `*const u8` is invalid
135+
error[E0606]: casting `bool` as `*const u8` is invalid
136136
--> $DIR/cast-rfc0401.rs:57:13
137137
|
138138
57 | let _ = false as *const u8;
139139
| ^^^^^^^^^^^^^^^^^^
140140

141-
error: casting `E` as `*const u8` is invalid
141+
error[E0606]: casting `E` as `*const u8` is invalid
142142
--> $DIR/cast-rfc0401.rs:58:13
143143
|
144144
58 | let _ = E::A as *const u8;
145145
| ^^^^^^^^^^^^^^^^^
146146

147-
error: casting `char` as `*const u8` is invalid
147+
error[E0606]: casting `char` as `*const u8` is invalid
148148
--> $DIR/cast-rfc0401.rs:59:13
149149
|
150150
59 | let _ = 'a' as *const u8;
151151
| ^^^^^^^^^^^^^^^^
152152

153-
error: casting `usize` as `*const [u8]` is invalid
153+
error[E0606]: casting `usize` as `*const [u8]` is invalid
154154
--> $DIR/cast-rfc0401.rs:61:13
155155
|
156156
61 | let _ = 42usize as *const [u8];
@@ -162,53 +162,53 @@ error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
162162
62 | let _ = v as *const [u8];
163163
| ^^^^^^^^^^^^^^^^
164164

165-
error: casting `&Foo` as `*const str` is invalid
165+
error[E0606]: casting `&Foo` as `*const str` is invalid
166166
--> $DIR/cast-rfc0401.rs:64:13
167167
|
168168
64 | let _ = foo as *const str;
169169
| ^^^^^^^^^^^^^^^^^
170170

171-
error: casting `&Foo` as `*mut str` is invalid
171+
error[E0606]: casting `&Foo` as `*mut str` is invalid
172172
--> $DIR/cast-rfc0401.rs:65:13
173173
|
174174
65 | let _ = foo as *mut str;
175175
| ^^^^^^^^^^^^^^^
176176

177-
error: casting `fn() {main}` as `*mut str` is invalid
177+
error[E0606]: casting `fn() {main}` as `*mut str` is invalid
178178
--> $DIR/cast-rfc0401.rs:66:13
179179
|
180180
66 | let _ = main as *mut str;
181181
| ^^^^^^^^^^^^^^^^
182182

183-
error: casting `&f32` as `*mut f32` is invalid
183+
error[E0606]: casting `&f32` as `*mut f32` is invalid
184184
--> $DIR/cast-rfc0401.rs:67:13
185185
|
186186
67 | let _ = &f as *mut f32;
187187
| ^^^^^^^^^^^^^^
188188

189-
error: casting `&f32` as `*const f64` is invalid
189+
error[E0606]: casting `&f32` as `*const f64` is invalid
190190
--> $DIR/cast-rfc0401.rs:68:13
191191
|
192192
68 | let _ = &f as *const f64;
193193
| ^^^^^^^^^^^^^^^^
194194

195-
error: casting `*const [i8]` as `usize` is invalid
195+
error[E0606]: casting `*const [i8]` as `usize` is invalid
196196
--> $DIR/cast-rfc0401.rs:69:13
197197
|
198198
69 | let _ = fat_sv as usize;
199199
| ^^^^^^^^^^^^^^^
200200
|
201201
= help: cast through a thin pointer first
202202

203-
error: casting `*const Foo` as `*const [u16]` is invalid
203+
error[E0606]: casting `*const Foo` as `*const [u16]` is invalid
204204
--> $DIR/cast-rfc0401.rs:78:13
205205
|
206206
78 | let _ = cf as *const [u16];
207207
| ^^^^^^^^^^^^^^^^^^
208208
|
209209
= note: vtable kinds may not match
210210

211-
error: casting `*const Foo` as `*const Bar` is invalid
211+
error[E0606]: casting `*const Foo` as `*const Bar` is invalid
212212
--> $DIR/cast-rfc0401.rs:79:13
213213
|
214214
79 | let _ = cf as *const Bar;
@@ -234,7 +234,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
234234
= help: the trait `std::marker::Sized` is not implemented for `str`
235235
= note: required for the cast to the object type `Foo`
236236

237-
error: casting `&{float}` as `f32` is invalid
237+
error[E0606]: casting `&{float}` as `f32` is invalid
238238
--> $DIR/cast-rfc0401.rs:81:30
239239
|
240240
81 | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();

0 commit comments

Comments
 (0)