@@ -83,28 +83,30 @@ enum PointerKind<'tcx> {
8383
8484impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
8585 /// 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 > > {
8888 if self . type_is_known_to_be_sized ( t, span) {
89- return PointerKind :: Thin ;
89+ return Some ( PointerKind :: Thin ) ;
9090 }
9191
9292 match t. sty {
93- ty:: TySlice ( _) | ty:: TyStr => PointerKind :: Length ,
93+ ty:: TySlice ( _) | ty:: TyStr => Some ( PointerKind :: Length ) ,
9494 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 ( ) ) ) ) ,
9696 ty:: TyAdt ( def, substs) if def. is_struct ( ) => {
9797 // FIXME(arielb1): do some kind of normalization
9898 match def. struct_variant ( ) . fields . last ( ) {
99- None => PointerKind :: Thin ,
99+ None => Some ( PointerKind :: Thin ) ,
100100 Some ( f) => self . pointer_kind ( f. ty ( self . tcx , substs) , span) ,
101101 }
102102 }
103103 // Pointers to foreign types are thin, despite being unsized
104- ty:: TyForeign ( ..) => PointerKind :: Thin ,
104+ ty:: TyForeign ( ..) => Some ( PointerKind :: Thin ) ,
105105 // 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 ,
108110 _ => panic ! ( ) ,
109111 }
110112 }
@@ -123,6 +125,8 @@ enum CastError {
123125 NeedViaThinPtr ,
124126 NeedViaInt ,
125127 NonScalar ,
128+ UnknownExprPtrKind ,
129+ UnknownCastPtrKind ,
126130}
127131
128132fn make_invalid_casting_error < ' a , ' gcx , ' tcx > ( sess : & ' a Session ,
@@ -241,6 +245,25 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
241245 self . expr_ty,
242246 fcx. ty_to_string( self . cast_ty) ) . emit ( ) ;
243247 }
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+ }
244267 }
245268 }
246269
@@ -457,14 +480,27 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
457480 debug ! ( "check_ptr_ptr_cast m_expr={:?} m_cast={:?}" , m_expr, m_cast) ;
458481 // ptr-ptr cast. vtables must match.
459482
460- // Cast to thin pointer is OK
483+ let expr_kind = fcx . pointer_kind ( m_expr . ty , self . span ) ;
461484 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
462493 if cast_kind == PointerKind :: Thin {
463494 return Ok ( CastKind :: PtrPtrCast ) ;
464495 }
465496
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+
466503 // thin -> fat? report invalid cast (don't complain about vtable kinds)
467- let expr_kind = fcx. pointer_kind ( m_expr. ty , self . span ) ;
468504 if expr_kind == PointerKind :: Thin {
469505 return Err ( CastError :: SizedUnsizedCast ) ;
470506 }
@@ -483,10 +519,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
483519 -> Result < CastKind , CastError > {
484520 // fptr-ptr cast. must be to thin ptr
485521
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 ) ,
490526 }
491527 }
492528
@@ -496,10 +532,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
496532 -> Result < CastKind , CastError > {
497533 // ptr-addr cast. must be from thin ptr
498534
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 ) ,
503539 }
504540 }
505541
@@ -533,10 +569,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
533569 m_cast : & ' tcx ty:: TypeAndMut < ' tcx > )
534570 -> Result < CastKind , CastError > {
535571 // 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 ) ,
540576 }
541577 }
542578
0 commit comments