@@ -56,11 +56,16 @@ pub struct CastCheck<'tcx> {
56
56
span : Span ,
57
57
}
58
58
59
+ /// The kind of the unsize info (length or vtable) - we only allow casts between
60
+ /// fat pointers if their unsize-infos have the same kind.
59
61
#[ derive( Copy , Clone , PartialEq , Eq ) ]
60
62
enum UnsizeKind < ' tcx > {
61
63
Vtable ,
62
64
Length ,
63
- OfTy ( Ty < ' tcx > )
65
+ /// The unsize info of this projection
66
+ OfProjection ( & ' tcx ty:: ProjectionTy < ' tcx > ) ,
67
+ /// The unsize info of this parameter
68
+ OfParam ( & ' tcx ty:: ParamTy )
64
69
}
65
70
66
71
/// Returns the kind of unsize information of t, or None
@@ -77,8 +82,9 @@ fn unsize_kind<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
77
82
Some ( f) => unsize_kind ( fcx, f. mt . ty )
78
83
}
79
84
}
80
- ty:: ty_projection( ..) | ty:: ty_param( ..) =>
81
- Some ( UnsizeKind :: OfTy ( t) ) ,
85
+ // We should really try to normalize here.
86
+ ty:: ty_projection( ref pi) => Some ( UnsizeKind :: OfProjection ( pi) ) ,
87
+ ty:: ty_param( ref p) => Some ( UnsizeKind :: OfParam ( p) ) ,
82
88
_ => None
83
89
}
84
90
}
@@ -164,26 +170,26 @@ impl<'tcx> CastCheck<'tcx> {
164
170
}
165
171
166
172
fn trivial_cast_lint < ' a > ( & self , fcx : & FnCtxt < ' a , ' tcx > ) {
167
- let t_1 = self . cast_ty ;
168
- let t_e = self . expr_ty ;
169
- if ty:: type_is_numeric ( t_1 ) && ty:: type_is_numeric ( t_e ) {
173
+ let t_cast = self . cast_ty ;
174
+ let t_expr = self . expr_ty ;
175
+ if ty:: type_is_numeric ( t_cast ) && ty:: type_is_numeric ( t_expr ) {
170
176
fcx. tcx ( ) . sess . add_lint ( lint:: builtin:: TRIVIAL_NUMERIC_CASTS ,
171
177
self . expr . id ,
172
178
self . span ,
173
179
format ! ( "trivial numeric cast: `{}` as `{}`. Cast can be \
174
180
replaced by coercion, this might require type \
175
181
ascription or a temporary variable",
176
- fcx. infcx( ) . ty_to_string( t_e ) ,
177
- fcx. infcx( ) . ty_to_string( t_1 ) ) ) ;
182
+ fcx. infcx( ) . ty_to_string( t_expr ) ,
183
+ fcx. infcx( ) . ty_to_string( t_cast ) ) ) ;
178
184
} else {
179
185
fcx. tcx ( ) . sess . add_lint ( lint:: builtin:: TRIVIAL_CASTS ,
180
186
self . expr . id ,
181
187
self . span ,
182
188
format ! ( "trivial cast: `{}` as `{}`. Cast can be \
183
189
replaced by coercion, this might require type \
184
190
ascription or a temporary variable",
185
- fcx. infcx( ) . ty_to_string( t_e ) ,
186
- fcx. infcx( ) . ty_to_string( t_1 ) ) ) ;
191
+ fcx. infcx( ) . ty_to_string( t_expr ) ,
192
+ fcx. infcx( ) . ty_to_string( t_cast ) ) ) ;
187
193
}
188
194
189
195
}
@@ -211,24 +217,24 @@ impl<'tcx> CastCheck<'tcx> {
211
217
} ; }
212
218
}
213
219
214
- /// Check a cast, and report an error if one exists. In some cases,
215
- /// this can return Ok and create type errors rather than returning
220
+ /// Check a cast, and report an error if one exists. In some cases, this
221
+ /// can return Ok and create type errors in the fcx rather than returning
216
222
/// directly. coercion-cast is handled in check instead of here.
217
223
fn do_check < ' a > ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> Result < CastKind , CastError > {
218
224
use middle:: cast:: IntTy :: * ;
219
225
use middle:: cast:: CastTy :: * ;
220
226
221
- let ( t_e , t_1 ) = match ( CastTy :: recognize ( fcx. tcx ( ) , self . expr_ty ) ,
222
- CastTy :: recognize ( fcx. tcx ( ) , self . cast_ty ) ) {
223
- ( Some ( t_e ) , Some ( t_1 ) ) => ( t_e , t_1 ) ,
227
+ let ( t_from , t_cast ) = match ( CastTy :: from_ty ( fcx. tcx ( ) , self . expr_ty ) ,
228
+ CastTy :: from_ty ( fcx. tcx ( ) , self . cast_ty ) ) {
229
+ ( Some ( t_from ) , Some ( t_cast ) ) => ( t_from , t_cast ) ,
224
230
_ => {
225
231
return Err ( CastError :: NonScalar )
226
232
}
227
233
} ;
228
234
229
- match ( t_e , t_1 ) {
235
+ match ( t_from , t_cast ) {
230
236
// These types have invariants! can't cast into them.
231
- ( _, RPtr ( _) ) | ( _, Int ( CEnum ) ) | ( _, FPtr ) => Err ( CastError :: NonScalar ) ,
237
+ ( _, RPtr ( _) ) | ( _, Int ( CEnum ) ) | ( _, FnPtr ) => Err ( CastError :: NonScalar ) ,
232
238
233
239
// * -> Bool
234
240
( _, Int ( Bool ) ) => Err ( CastError :: CastToBool ) ,
@@ -244,14 +250,14 @@ impl<'tcx> CastCheck<'tcx> {
244
250
=> Err ( CastError :: NeedViaUsize ) ,
245
251
246
252
// ptr -> *
247
- ( Ptr ( m1 ) , Ptr ( m2 ) ) => self . check_ptr_ptr_cast ( fcx, m1 , m2 ) , // ptr-ptr-cast
248
- ( Ptr ( m_e ) , Int ( _) ) => self . check_ptr_addr_cast ( fcx, m_e ) , // ptr-addr-cast
249
- ( Ptr ( _) , Float ) | ( FPtr , Float ) => Err ( CastError :: NeedViaUsize ) ,
250
- ( FPtr , Int ( _) ) => Ok ( CastKind :: FPtrAddrCast ) ,
253
+ ( Ptr ( m_e ) , Ptr ( m_c ) ) => self . check_ptr_ptr_cast ( fcx, m_e , m_c ) , // ptr-ptr-cast
254
+ ( Ptr ( m_expr ) , Int ( _) ) => self . check_ptr_addr_cast ( fcx, m_expr ) , // ptr-addr-cast
255
+ ( Ptr ( _) , Float ) | ( FnPtr , Float ) => Err ( CastError :: NeedViaUsize ) ,
256
+ ( FnPtr , Int ( _) ) => Ok ( CastKind :: FnPtrAddrCast ) ,
251
257
( RPtr ( _) , Int ( _) ) | ( RPtr ( _) , Float ) => Err ( CastError :: NeedViaPtr ) ,
252
258
// * -> ptr
253
259
( Int ( _) , Ptr ( mt) ) => self . check_addr_ptr_cast ( fcx, mt) , // addr-ptr-cast
254
- ( FPtr , Ptr ( mt) ) => self . check_fptr_ptr_cast ( fcx, mt) ,
260
+ ( FnPtr , Ptr ( mt) ) => self . check_fptr_ptr_cast ( fcx, mt) ,
255
261
( Float , Ptr ( _) ) => Err ( CastError :: NeedViaUsize ) ,
256
262
( RPtr ( rmt) , Ptr ( mt) ) => self . check_ref_cast ( fcx, rmt, mt) , // array-ptr-cast
257
263
@@ -269,53 +275,53 @@ impl<'tcx> CastCheck<'tcx> {
269
275
270
276
fn check_ptr_ptr_cast < ' a > ( & self ,
271
277
fcx : & FnCtxt < ' a , ' tcx > ,
272
- m_e : & ' tcx ty:: mt < ' tcx > ,
273
- m_1 : & ' tcx ty:: mt < ' tcx > )
278
+ m_expr : & ' tcx ty:: mt < ' tcx > ,
279
+ m_cast : & ' tcx ty:: mt < ' tcx > )
274
280
-> Result < CastKind , CastError >
275
281
{
276
- debug ! ( "check_ptr_ptr_cast m_e ={} m_1 ={}" ,
277
- m_e . repr( fcx. tcx( ) ) , m_1 . repr( fcx. tcx( ) ) ) ;
282
+ debug ! ( "check_ptr_ptr_cast m_expr ={} m_cast ={}" ,
283
+ m_expr . repr( fcx. tcx( ) ) , m_cast . repr( fcx. tcx( ) ) ) ;
278
284
// ptr-ptr cast. vtables must match.
279
285
280
286
// Cast to sized is OK
281
- if fcx. type_is_known_to_be_sized ( m_1 . ty , self . span ) {
287
+ if fcx. type_is_known_to_be_sized ( m_cast . ty , self . span ) {
282
288
return Ok ( CastKind :: PtrPtrCast ) ;
283
289
}
284
290
285
291
// sized -> unsized? report illegal cast (don't complain about vtable kinds)
286
- if fcx. type_is_known_to_be_sized ( m_e . ty , self . span ) {
292
+ if fcx. type_is_known_to_be_sized ( m_expr . ty , self . span ) {
287
293
return Err ( CastError :: IllegalCast ) ;
288
294
}
289
295
290
296
// vtable kinds must match
291
- match ( unsize_kind ( fcx, m_1 . ty ) , unsize_kind ( fcx, m_e . ty ) ) {
297
+ match ( unsize_kind ( fcx, m_cast . ty ) , unsize_kind ( fcx, m_expr . ty ) ) {
292
298
( Some ( a) , Some ( b) ) if a == b => Ok ( CastKind :: PtrPtrCast ) ,
293
299
_ => Err ( CastError :: DifferingKinds )
294
300
}
295
301
}
296
302
297
303
fn check_fptr_ptr_cast < ' a > ( & self ,
298
304
fcx : & FnCtxt < ' a , ' tcx > ,
299
- m_1 : & ' tcx ty:: mt < ' tcx > )
305
+ m_cast : & ' tcx ty:: mt < ' tcx > )
300
306
-> Result < CastKind , CastError >
301
307
{
302
308
// fptr-ptr cast. must be to sized ptr
303
309
304
- if fcx. type_is_known_to_be_sized ( m_1 . ty , self . span ) {
305
- Ok ( CastKind :: FPtrPtrCast )
310
+ if fcx. type_is_known_to_be_sized ( m_cast . ty , self . span ) {
311
+ Ok ( CastKind :: FnPtrPtrCast )
306
312
} else {
307
313
Err ( CastError :: IllegalCast )
308
314
}
309
315
}
310
316
311
317
fn check_ptr_addr_cast < ' a > ( & self ,
312
318
fcx : & FnCtxt < ' a , ' tcx > ,
313
- m_e : & ' tcx ty:: mt < ' tcx > )
319
+ m_expr : & ' tcx ty:: mt < ' tcx > )
314
320
-> Result < CastKind , CastError >
315
321
{
316
322
// ptr-addr cast. must be from sized ptr
317
323
318
- if fcx. type_is_known_to_be_sized ( m_e . ty , self . span ) {
324
+ if fcx. type_is_known_to_be_sized ( m_expr . ty , self . span ) {
319
325
Ok ( CastKind :: PtrAddrCast )
320
326
} else {
321
327
Err ( CastError :: NeedViaPtr )
@@ -324,14 +330,14 @@ impl<'tcx> CastCheck<'tcx> {
324
330
325
331
fn check_ref_cast < ' a > ( & self ,
326
332
fcx : & FnCtxt < ' a , ' tcx > ,
327
- m_e : & ' tcx ty:: mt < ' tcx > ,
328
- m_1 : & ' tcx ty:: mt < ' tcx > )
333
+ m_expr : & ' tcx ty:: mt < ' tcx > ,
334
+ m_cast : & ' tcx ty:: mt < ' tcx > )
329
335
-> Result < CastKind , CastError >
330
336
{
331
337
// array-ptr-cast.
332
338
333
- if m_e . mutbl == ast:: MutImmutable && m_1 . mutbl == ast:: MutImmutable {
334
- if let ty:: ty_vec( ety, Some ( _) ) = m_e . ty . sty {
339
+ if m_expr . mutbl == ast:: MutImmutable && m_cast . mutbl == ast:: MutImmutable {
340
+ if let ty:: ty_vec( ety, Some ( _) ) = m_expr . ty . sty {
335
341
// Due to the limitations of LLVM global constants,
336
342
// region pointers end up pointing at copies of
337
343
// vector elements instead of the original values.
@@ -340,7 +346,7 @@ impl<'tcx> CastCheck<'tcx> {
340
346
// from a region pointer to a vector.
341
347
342
348
// this will report a type mismatch if needed
343
- demand:: eqtype ( fcx, self . span , ety, m_1 . ty ) ;
349
+ demand:: eqtype ( fcx, self . span , ety, m_cast . ty ) ;
344
350
return Ok ( CastKind :: ArrayPtrCast ) ;
345
351
}
346
352
}
@@ -350,11 +356,11 @@ impl<'tcx> CastCheck<'tcx> {
350
356
351
357
fn check_addr_ptr_cast < ' a > ( & self ,
352
358
fcx : & FnCtxt < ' a , ' tcx > ,
353
- m_1 : & ' tcx ty:: mt < ' tcx > )
359
+ m_cast : & ' tcx ty:: mt < ' tcx > )
354
360
-> Result < CastKind , CastError >
355
361
{
356
362
// ptr-addr cast. pointer must be thin.
357
- if fcx. type_is_known_to_be_sized ( m_1 . ty , self . span ) {
363
+ if fcx. type_is_known_to_be_sized ( m_cast . ty , self . span ) {
358
364
Ok ( CastKind :: AddrPtrCast )
359
365
} else {
360
366
Err ( CastError :: IllegalCast )
0 commit comments