@@ -48,6 +48,7 @@ use rustc::session::Session;
4848use rustc:: traits;
4949use rustc:: ty:: { self , Ty , TypeFoldable } ;
5050use rustc:: ty:: cast:: { CastKind , CastTy } ;
51+ use rustc:: ty:: subst:: Substs ;
5152use rustc:: middle:: lang_items;
5253use syntax:: ast;
5354use syntax_pos:: Span ;
@@ -77,43 +78,74 @@ enum PointerKind<'tcx> {
7778 Length ,
7879 /// The unsize info of this projection
7980 OfProjection ( & ' tcx ty:: ProjectionTy < ' tcx > ) ,
81+ /// The unsize info of this anon ty
82+ OfAnon ( DefId , & ' tcx Substs < ' tcx > ) ,
8083 /// The unsize info of this parameter
8184 OfParam ( & ' tcx ty:: ParamTy ) ,
8285}
8386
8487impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
8588 /// Returns the kind of unsize information of t, or None
8689 /// if t is unknown.
87- fn pointer_kind ( & self , t : Ty < ' tcx > , span : Span ) -> Option < PointerKind < ' tcx > > {
90+ fn pointer_kind ( & self , t : Ty < ' tcx > , span : Span ) ->
91+ Result < Option < PointerKind < ' tcx > > , ErrorReported >
92+ {
93+ debug ! ( "pointer_kind({:?}, {:?})" , t, span) ;
94+
95+ let t = self . resolve_type_vars_if_possible ( & t) ;
96+
97+ if t. references_error ( ) {
98+ return Err ( ErrorReported ) ;
99+ }
100+
88101 if self . type_is_known_to_be_sized ( t, span) {
89- return Some ( PointerKind :: Thin ) ;
102+ return Ok ( Some ( PointerKind :: Thin ) ) ;
90103 }
91104
92- match t. sty {
105+ Ok ( match t. sty {
93106 ty:: TySlice ( _) | ty:: TyStr => Some ( PointerKind :: Length ) ,
94107 ty:: TyDynamic ( ref tty, ..) =>
95108 Some ( PointerKind :: Vtable ( tty. principal ( ) . map ( |p| p. def_id ( ) ) ) ) ,
96109 ty:: TyAdt ( def, substs) if def. is_struct ( ) => {
97- // FIXME(arielb1): do some kind of normalization
98110 match def. struct_variant ( ) . fields . last ( ) {
99111 None => Some ( PointerKind :: Thin ) ,
100- Some ( f) => self . pointer_kind ( f. ty ( self . tcx , substs) , span) ,
112+ Some ( f) => {
113+ let field_ty = self . field_ty ( span, f, substs) ;
114+ self . pointer_kind ( field_ty, span) ?
115+ }
101116 }
102117 }
118+ ty:: TyTuple ( fields, _) => match fields. last ( ) {
119+ None => Some ( PointerKind :: Thin ) ,
120+ Some ( f) => self . pointer_kind ( f, span) ?
121+ } ,
122+
103123 // Pointers to foreign types are thin, despite being unsized
104124 ty:: TyForeign ( ..) => Some ( PointerKind :: Thin ) ,
105125 // We should really try to normalize here.
106126 ty:: TyProjection ( ref pi) => Some ( PointerKind :: OfProjection ( pi) ) ,
127+ ty:: TyAnon ( def_id, substs) => Some ( PointerKind :: OfAnon ( def_id, substs) ) ,
107128 ty:: TyParam ( ref p) => Some ( PointerKind :: OfParam ( p) ) ,
108129 // Insufficient type information.
109130 ty:: TyInfer ( _) => None ,
110- _ => panic ! ( ) ,
111- }
131+
132+ ty:: TyBool | ty:: TyChar | ty:: TyInt ( ..) | ty:: TyUint ( ..) |
133+ ty:: TyFloat ( _) | ty:: TyArray ( ..) |
134+ ty:: TyRawPtr ( _) | ty:: TyRef ( ..) | ty:: TyFnDef ( ..) |
135+ ty:: TyFnPtr ( ..) | ty:: TyClosure ( ..) | ty:: TyGenerator ( ..) |
136+ ty:: TyAdt ( ..) | ty:: TyNever | ty:: TyError => {
137+ self . tcx . sess . delay_span_bug (
138+ span, & format ! ( "`{:?}` should be sized but is not?" , t) ) ;
139+ return Err ( ErrorReported ) ;
140+ }
141+ } )
112142 }
113143}
114144
115145#[ derive( Copy , Clone ) ]
116146enum CastError {
147+ ErrorReported ,
148+
117149 CastToBool ,
118150 CastToChar ,
119151 DifferingKinds ,
@@ -129,6 +161,12 @@ enum CastError {
129161 UnknownCastPtrKind ,
130162}
131163
164+ impl From < ErrorReported > for CastError {
165+ fn from ( ErrorReported : ErrorReported ) -> Self {
166+ CastError :: ErrorReported
167+ }
168+ }
169+
132170fn make_invalid_casting_error < ' a , ' gcx , ' tcx > ( sess : & ' a Session ,
133171 span : Span ,
134172 expr_ty : Ty < ' tcx > ,
@@ -173,6 +211,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
173211
174212 fn report_cast_error ( & self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > , e : CastError ) {
175213 match e {
214+ CastError :: ErrorReported => {
215+ // an error has already been reported
216+ }
176217 CastError :: NeedDeref => {
177218 let error_span = self . span ;
178219 let mut err = make_invalid_casting_error ( fcx. tcx . sess , self . span , self . expr_ty ,
@@ -480,8 +521,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
480521 debug ! ( "check_ptr_ptr_cast m_expr={:?} m_cast={:?}" , m_expr, m_cast) ;
481522 // ptr-ptr cast. vtables must match.
482523
483- let expr_kind = fcx. pointer_kind ( m_expr. ty , self . span ) ;
484- let cast_kind = fcx. pointer_kind ( m_cast. ty , self . span ) ;
524+ let expr_kind = fcx. pointer_kind ( m_expr. ty , self . span ) ? ;
525+ let cast_kind = fcx. pointer_kind ( m_cast. ty , self . span ) ? ;
485526
486527 let cast_kind = match cast_kind {
487528 // We can't cast if target pointer kind is unknown
@@ -519,7 +560,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
519560 -> Result < CastKind , CastError > {
520561 // fptr-ptr cast. must be to thin ptr
521562
522- match fcx. pointer_kind ( m_cast. ty , self . span ) {
563+ match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
523564 None => Err ( CastError :: UnknownCastPtrKind ) ,
524565 Some ( PointerKind :: Thin ) => Ok ( CastKind :: FnPtrPtrCast ) ,
525566 _ => Err ( CastError :: IllegalCast ) ,
@@ -532,7 +573,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
532573 -> Result < CastKind , CastError > {
533574 // ptr-addr cast. must be from thin ptr
534575
535- match fcx. pointer_kind ( m_expr. ty , self . span ) {
576+ match fcx. pointer_kind ( m_expr. ty , self . span ) ? {
536577 None => Err ( CastError :: UnknownExprPtrKind ) ,
537578 Some ( PointerKind :: Thin ) => Ok ( CastKind :: PtrAddrCast ) ,
538579 _ => Err ( CastError :: NeedViaThinPtr ) ,
@@ -569,7 +610,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
569610 m_cast : & ' tcx ty:: TypeAndMut < ' tcx > )
570611 -> Result < CastKind , CastError > {
571612 // ptr-addr cast. pointer must be thin.
572- match fcx. pointer_kind ( m_cast. ty , self . span ) {
613+ match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
573614 None => Err ( CastError :: UnknownCastPtrKind ) ,
574615 Some ( PointerKind :: Thin ) => Ok ( CastKind :: AddrPtrCast ) ,
575616 _ => Err ( CastError :: IllegalCast ) ,
0 commit comments