@@ -48,6 +48,7 @@ use rustc::session::Session;
48
48
use rustc:: traits;
49
49
use rustc:: ty:: { self , Ty , TypeFoldable } ;
50
50
use rustc:: ty:: cast:: { CastKind , CastTy } ;
51
+ use rustc:: ty:: subst:: Substs ;
51
52
use rustc:: middle:: lang_items;
52
53
use syntax:: ast;
53
54
use syntax_pos:: Span ;
@@ -77,43 +78,74 @@ enum PointerKind<'tcx> {
77
78
Length ,
78
79
/// The unsize info of this projection
79
80
OfProjection ( & ' tcx ty:: ProjectionTy < ' tcx > ) ,
81
+ /// The unsize info of this anon ty
82
+ OfAnon ( DefId , & ' tcx Substs < ' tcx > ) ,
80
83
/// The unsize info of this parameter
81
84
OfParam ( & ' tcx ty:: ParamTy ) ,
82
85
}
83
86
84
87
impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
85
88
/// Returns the kind of unsize information of t, or None
86
89
/// 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
+
88
101
if self . type_is_known_to_be_sized ( t, span) {
89
- return Some ( PointerKind :: Thin ) ;
102
+ return Ok ( Some ( PointerKind :: Thin ) ) ;
90
103
}
91
104
92
- match t. sty {
105
+ Ok ( match t. sty {
93
106
ty:: TySlice ( _) | ty:: TyStr => Some ( PointerKind :: Length ) ,
94
107
ty:: TyDynamic ( ref tty, ..) =>
95
108
Some ( PointerKind :: Vtable ( tty. principal ( ) . map ( |p| p. def_id ( ) ) ) ) ,
96
109
ty:: TyAdt ( def, substs) if def. is_struct ( ) => {
97
- // FIXME(arielb1): do some kind of normalization
98
110
match def. struct_variant ( ) . fields . last ( ) {
99
111
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
+ }
101
116
}
102
117
}
118
+ ty:: TyTuple ( fields, _) => match fields. last ( ) {
119
+ None => Some ( PointerKind :: Thin ) ,
120
+ Some ( f) => self . pointer_kind ( f, span) ?
121
+ } ,
122
+
103
123
// Pointers to foreign types are thin, despite being unsized
104
124
ty:: TyForeign ( ..) => Some ( PointerKind :: Thin ) ,
105
125
// We should really try to normalize here.
106
126
ty:: TyProjection ( ref pi) => Some ( PointerKind :: OfProjection ( pi) ) ,
127
+ ty:: TyAnon ( def_id, substs) => Some ( PointerKind :: OfAnon ( def_id, substs) ) ,
107
128
ty:: TyParam ( ref p) => Some ( PointerKind :: OfParam ( p) ) ,
108
129
// Insufficient type information.
109
130
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
+ } )
112
142
}
113
143
}
114
144
115
145
#[ derive( Copy , Clone ) ]
116
146
enum CastError {
147
+ ErrorReported ,
148
+
117
149
CastToBool ,
118
150
CastToChar ,
119
151
DifferingKinds ,
@@ -129,6 +161,12 @@ enum CastError {
129
161
UnknownCastPtrKind ,
130
162
}
131
163
164
+ impl From < ErrorReported > for CastError {
165
+ fn from ( ErrorReported : ErrorReported ) -> Self {
166
+ CastError :: ErrorReported
167
+ }
168
+ }
169
+
132
170
fn make_invalid_casting_error < ' a , ' gcx , ' tcx > ( sess : & ' a Session ,
133
171
span : Span ,
134
172
expr_ty : Ty < ' tcx > ,
@@ -173,6 +211,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
173
211
174
212
fn report_cast_error ( & self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > , e : CastError ) {
175
213
match e {
214
+ CastError :: ErrorReported => {
215
+ // an error has already been reported
216
+ }
176
217
CastError :: NeedDeref => {
177
218
let error_span = self . span ;
178
219
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> {
480
521
debug ! ( "check_ptr_ptr_cast m_expr={:?} m_cast={:?}" , m_expr, m_cast) ;
481
522
// ptr-ptr cast. vtables must match.
482
523
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 ) ? ;
485
526
486
527
let cast_kind = match cast_kind {
487
528
// We can't cast if target pointer kind is unknown
@@ -519,7 +560,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
519
560
-> Result < CastKind , CastError > {
520
561
// fptr-ptr cast. must be to thin ptr
521
562
522
- match fcx. pointer_kind ( m_cast. ty , self . span ) {
563
+ match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
523
564
None => Err ( CastError :: UnknownCastPtrKind ) ,
524
565
Some ( PointerKind :: Thin ) => Ok ( CastKind :: FnPtrPtrCast ) ,
525
566
_ => Err ( CastError :: IllegalCast ) ,
@@ -532,7 +573,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
532
573
-> Result < CastKind , CastError > {
533
574
// ptr-addr cast. must be from thin ptr
534
575
535
- match fcx. pointer_kind ( m_expr. ty , self . span ) {
576
+ match fcx. pointer_kind ( m_expr. ty , self . span ) ? {
536
577
None => Err ( CastError :: UnknownExprPtrKind ) ,
537
578
Some ( PointerKind :: Thin ) => Ok ( CastKind :: PtrAddrCast ) ,
538
579
_ => Err ( CastError :: NeedViaThinPtr ) ,
@@ -569,7 +610,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
569
610
m_cast : & ' tcx ty:: TypeAndMut < ' tcx > )
570
611
-> Result < CastKind , CastError > {
571
612
// 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 ) ? {
573
614
None => Err ( CastError :: UnknownCastPtrKind ) ,
574
615
Some ( PointerKind :: Thin ) => Ok ( CastKind :: AddrPtrCast ) ,
575
616
_ => Err ( CastError :: IllegalCast ) ,
0 commit comments