@@ -83,28 +83,30 @@ enum PointerKind<'tcx> {
83
83
84
84
impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
85
85
/// Returns the kind of unsize information of t, or None
86
- /// if t is sized or it is unknown.
87
- fn pointer_kind ( & self , t : Ty < ' tcx > , span : Span ) -> PointerKind < ' tcx > {
86
+ /// if t is unknown.
87
+ fn pointer_kind ( & self , t : Ty < ' tcx > , span : Span ) -> Option < PointerKind < ' tcx > > {
88
88
if self . type_is_known_to_be_sized ( t, span) {
89
- return PointerKind :: Thin ;
89
+ return Some ( PointerKind :: Thin ) ;
90
90
}
91
91
92
92
match t. sty {
93
- ty:: TySlice ( _) | ty:: TyStr => PointerKind :: Length ,
93
+ ty:: TySlice ( _) | ty:: TyStr => Some ( PointerKind :: Length ) ,
94
94
ty:: TyDynamic ( ref tty, ..) =>
95
- PointerKind :: Vtable ( tty. principal ( ) . map ( |p| p. def_id ( ) ) ) ,
95
+ Some ( PointerKind :: Vtable ( tty. principal ( ) . map ( |p| p. def_id ( ) ) ) ) ,
96
96
ty:: TyAdt ( def, substs) if def. is_struct ( ) => {
97
97
// FIXME(arielb1): do some kind of normalization
98
98
match def. struct_variant ( ) . fields . last ( ) {
99
- None => PointerKind :: Thin ,
99
+ None => Some ( PointerKind :: Thin ) ,
100
100
Some ( f) => self . pointer_kind ( f. ty ( self . tcx , substs) , span) ,
101
101
}
102
102
}
103
103
// Pointers to foreign types are thin, despite being unsized
104
- ty:: TyForeign ( ..) => PointerKind :: Thin ,
104
+ ty:: TyForeign ( ..) => Some ( PointerKind :: Thin ) ,
105
105
// We should really try to normalize here.
106
- ty:: TyProjection ( ref pi) => PointerKind :: OfProjection ( pi) ,
107
- ty:: TyParam ( ref p) => PointerKind :: OfParam ( p) ,
106
+ ty:: TyProjection ( ref pi) => Some ( PointerKind :: OfProjection ( pi) ) ,
107
+ ty:: TyParam ( ref p) => Some ( PointerKind :: OfParam ( p) ) ,
108
+ // Insufficient type information.
109
+ ty:: TyInfer ( _) => None ,
108
110
_ => panic ! ( ) ,
109
111
}
110
112
}
@@ -123,6 +125,8 @@ enum CastError {
123
125
NeedViaThinPtr ,
124
126
NeedViaInt ,
125
127
NonScalar ,
128
+ UnknownExprPtrKind ,
129
+ UnknownCastPtrKind ,
126
130
}
127
131
128
132
fn make_invalid_casting_error < ' a , ' gcx , ' tcx > ( sess : & ' a Session ,
@@ -241,6 +245,25 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
241
245
self . expr_ty,
242
246
fcx. ty_to_string( self . cast_ty) ) . emit ( ) ;
243
247
}
248
+ CastError :: UnknownCastPtrKind |
249
+ CastError :: UnknownExprPtrKind => {
250
+ let unknown_cast_to = match e {
251
+ CastError :: UnknownCastPtrKind => true ,
252
+ CastError :: UnknownExprPtrKind => false ,
253
+ _ => bug ! ( ) ,
254
+ } ;
255
+ let mut err = struct_span_err ! ( fcx. tcx. sess, self . span, E0641 ,
256
+ "cannot cast {} a pointer of an unknown kind" ,
257
+ if unknown_cast_to { "to" } else { "from" } ) ;
258
+ err. note ( "The type information given here is insufficient to check whether \
259
+ the pointer cast is valid") ;
260
+ if unknown_cast_to {
261
+ err. span_suggestion_short ( self . cast_span ,
262
+ "consider giving more type information" ,
263
+ String :: new ( ) ) ;
264
+ }
265
+ err. emit ( ) ;
266
+ }
244
267
}
245
268
}
246
269
@@ -457,14 +480,27 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
457
480
debug ! ( "check_ptr_ptr_cast m_expr={:?} m_cast={:?}" , m_expr, m_cast) ;
458
481
// ptr-ptr cast. vtables must match.
459
482
460
- // Cast to thin pointer is OK
483
+ let expr_kind = fcx . pointer_kind ( m_expr . ty , self . span ) ;
461
484
let cast_kind = fcx. pointer_kind ( m_cast. ty , self . span ) ;
485
+
486
+ let cast_kind = match cast_kind {
487
+ // We can't cast if target pointer kind is unknown
488
+ None => return Err ( CastError :: UnknownCastPtrKind ) ,
489
+ Some ( cast_kind) => cast_kind,
490
+ } ;
491
+
492
+ // Cast to thin pointer is OK
462
493
if cast_kind == PointerKind :: Thin {
463
494
return Ok ( CastKind :: PtrPtrCast ) ;
464
495
}
465
496
497
+ let expr_kind = match expr_kind {
498
+ // We can't cast to fat pointer if source pointer kind is unknown
499
+ None => return Err ( CastError :: UnknownExprPtrKind ) ,
500
+ Some ( expr_kind) => expr_kind,
501
+ } ;
502
+
466
503
// thin -> fat? report invalid cast (don't complain about vtable kinds)
467
- let expr_kind = fcx. pointer_kind ( m_expr. ty , self . span ) ;
468
504
if expr_kind == PointerKind :: Thin {
469
505
return Err ( CastError :: SizedUnsizedCast ) ;
470
506
}
@@ -483,10 +519,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
483
519
-> Result < CastKind , CastError > {
484
520
// fptr-ptr cast. must be to thin ptr
485
521
486
- if fcx. pointer_kind ( m_cast. ty , self . span ) == PointerKind :: Thin {
487
- Ok ( CastKind :: FnPtrPtrCast )
488
- } else {
489
- Err ( CastError :: IllegalCast )
522
+ match fcx. pointer_kind ( m_cast. ty , self . span ) {
523
+ None => Err ( CastError :: UnknownCastPtrKind ) ,
524
+ Some ( PointerKind :: Thin ) => Ok ( CastKind :: FnPtrPtrCast ) ,
525
+ _ => Err ( CastError :: IllegalCast ) ,
490
526
}
491
527
}
492
528
@@ -496,10 +532,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
496
532
-> Result < CastKind , CastError > {
497
533
// ptr-addr cast. must be from thin ptr
498
534
499
- if fcx. pointer_kind ( m_expr. ty , self . span ) == PointerKind :: Thin {
500
- Ok ( CastKind :: PtrAddrCast )
501
- } else {
502
- Err ( CastError :: NeedViaThinPtr )
535
+ match fcx. pointer_kind ( m_expr. ty , self . span ) {
536
+ None => Err ( CastError :: UnknownExprPtrKind ) ,
537
+ Some ( PointerKind :: Thin ) => Ok ( CastKind :: PtrAddrCast ) ,
538
+ _ => Err ( CastError :: NeedViaThinPtr ) ,
503
539
}
504
540
}
505
541
@@ -533,10 +569,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
533
569
m_cast : & ' tcx ty:: TypeAndMut < ' tcx > )
534
570
-> Result < CastKind , CastError > {
535
571
// ptr-addr cast. pointer must be thin.
536
- if fcx. pointer_kind ( m_cast. ty , self . span ) == PointerKind :: Thin {
537
- Ok ( CastKind :: AddrPtrCast )
538
- } else {
539
- Err ( CastError :: IllegalCast )
572
+ match fcx. pointer_kind ( m_cast. ty , self . span ) {
573
+ None => Err ( CastError :: UnknownCastPtrKind ) ,
574
+ Some ( PointerKind :: Thin ) => Ok ( CastKind :: AddrPtrCast ) ,
575
+ _ => Err ( CastError :: IllegalCast ) ,
540
576
}
541
577
}
542
578
0 commit comments