@@ -145,22 +145,8 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
145
145
return Univariant ( mk_struct ( cx, ftys, packed) , dtor)
146
146
}
147
147
ty:: ty_enum( def_id, ref substs) => {
148
- struct Case { discr : Disr , tys : ~[ ty:: t ] } ;
149
- impl Case {
150
- fn is_zerolen ( & self , cx : & mut CrateContext ) -> bool {
151
- mk_struct ( cx, self . tys , false ) . size == 0
152
- }
153
- fn find_ptr ( & self ) -> Option < uint > {
154
- self . tys . iter ( ) . position ( |& ty| mono_data_classify ( ty) == MonoNonNull )
155
- }
156
- }
157
-
158
- let cases = do ty:: enum_variants ( cx. tcx , def_id) . map |vi| {
159
- let arg_tys = do vi. args . map |& raw_ty| {
160
- ty:: subst ( cx. tcx , substs, raw_ty)
161
- } ;
162
- Case { discr : vi. disr_val , tys : arg_tys }
163
- } ;
148
+ let cases = get_cases ( cx. tcx , def_id, substs) ;
149
+ let hint = ty:: lookup_repr_hint ( cx. tcx , def_id) ;
164
150
165
151
if cases. len ( ) == 0 {
166
152
// Uninhabitable; represent as unit
@@ -170,7 +156,6 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
170
156
if cases. iter ( ) . all ( |c| c. tys . len ( ) == 0 ) {
171
157
// All bodies empty -> intlike
172
158
let discrs = cases. map ( |c| c. discr ) ;
173
- let hint = ty:: lookup_repr_hint ( cx. tcx , def_id) ;
174
159
let bounds = IntBounds {
175
160
ulo : * discrs. iter ( ) . min ( ) . unwrap ( ) ,
176
161
uhi : * discrs. iter ( ) . max ( ) . unwrap ( ) ,
@@ -232,6 +217,56 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
232
217
}
233
218
}
234
219
220
+ /// Determine, without doing translation, whether an ADT must be FFI-safe.
221
+ /// For use in lint or similar, where being sound but slightly incomplete is acceptable.
222
+ pub fn is_ffi_safe ( tcx : ty:: ctxt , def_id : ast:: DefId ) -> bool {
223
+ match ty:: get ( ty:: lookup_item_type ( tcx, def_id) . ty ) . sty {
224
+ ty:: ty_enum( def_id, ref substs) => {
225
+ let cases = get_cases ( tcx, def_id, substs) ;
226
+ // Univariant => like struct/tuple.
227
+ if cases. len ( ) <= 2 {
228
+ return true ;
229
+ }
230
+ let hint = ty:: lookup_repr_hint ( tcx, def_id) ;
231
+ // Appropriate representation explicitly selected?
232
+ if hint. is_ffi_safe ( ) {
233
+ return true ;
234
+ }
235
+ // Conservative approximation of nullable pointers, for Option<~T> etc.
236
+ if cases. len ( ) == 2 && hint == attr:: ReprAny &&
237
+ ( cases[ 0 ] . tys . is_empty ( ) && cases[ 1 ] . find_ptr ( ) . is_some ( ) ||
238
+ cases[ 1 ] . tys . is_empty ( ) && cases[ 0 ] . find_ptr ( ) . is_some ( ) ) {
239
+ return true ;
240
+ }
241
+ false
242
+ }
243
+ // struct, tuple, etc.
244
+ // (is this right in the present of typedefs?)
245
+ _ => true
246
+ }
247
+ }
248
+
249
+ // NOTE this should probably all be in ty
250
+ struct Case { discr : Disr , tys : ~[ ty:: t ] }
251
+ impl Case {
252
+ fn is_zerolen ( & self , cx : & mut CrateContext ) -> bool {
253
+ mk_struct ( cx, self . tys , false ) . size == 0
254
+ }
255
+ fn find_ptr ( & self ) -> Option < uint > {
256
+ self . tys . iter ( ) . position ( |& ty| mono_data_classify ( ty) == MonoNonNull )
257
+ }
258
+ }
259
+
260
+ fn get_cases ( tcx : ty:: ctxt , def_id : ast:: DefId , substs : & ty:: substs ) -> ~[ Case ] {
261
+ do ty:: enum_variants ( tcx, def_id) . map |vi| {
262
+ let arg_tys = do vi. args . map |& raw_ty| {
263
+ ty:: subst ( tcx, substs, raw_ty)
264
+ } ;
265
+ Case { discr : vi. disr_val , tys : arg_tys }
266
+ }
267
+ }
268
+
269
+
235
270
fn mk_struct ( cx : & mut CrateContext , tys : & [ ty:: t ] , packed : bool ) -> Struct {
236
271
let lltys = tys. map ( |& ty| type_of:: sizing_type_of ( cx, ty) ) ;
237
272
let llty_rec = Type :: struct_ ( lltys, packed) ;
0 commit comments