@@ -481,7 +481,7 @@ pub struct t { inner: *const t_opaque }
481
481
482
482
impl fmt:: Show for t {
483
483
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
484
- "*t_opaque" . fmt ( f )
484
+ write ! ( f , "{}" , get ( * self ) )
485
485
}
486
486
}
487
487
@@ -1962,7 +1962,8 @@ def_type_content_sets!(
1962
1962
// ReachesManaged /* see [1] below */ = 0b0000_0100__0000_0000__0000,
1963
1963
ReachesMutable = 0b0000_1000__0000_0000__0000 ,
1964
1964
ReachesNoSync = 0b0001_0000__0000_0000__0000 ,
1965
- ReachesAll = 0b0001_1111__0000_0000__0000 ,
1965
+ ReachesFfiUnsafe = 0b0010_0000__0000_0000__0000 ,
1966
+ ReachesAll = 0b0011_1111__0000_0000__0000 ,
1966
1967
1967
1968
// Things that cause values to *move* rather than *copy*
1968
1969
Moves = 0b0000_0000__0000_1011__0000 ,
@@ -2199,38 +2200,44 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
2199
2200
cache. insert ( ty_id, TC :: None ) ;
2200
2201
2201
2202
let result = match get ( ty) . sty {
2203
+ // uint and int are ffi-unsafe
2204
+ ty_uint( ast:: TyU ) | ty_int( ast:: TyI ) => {
2205
+ TC :: ReachesFfiUnsafe
2206
+ }
2207
+
2202
2208
// Scalar and unique types are sendable, and durable
2203
2209
ty_nil | ty_bot | ty_bool | ty_int( _) | ty_uint( _) | ty_float( _) |
2204
2210
ty_bare_fn( _) | ty:: ty_char | ty_str => {
2205
2211
TC :: None
2206
2212
}
2207
2213
2208
2214
ty_closure( ref c) => {
2209
- closure_contents ( cx, & * * c)
2215
+ closure_contents ( cx, & * * c) | TC :: ReachesFfiUnsafe
2210
2216
}
2211
2217
2212
2218
ty_box( typ) => {
2213
- tc_ty ( cx, typ, cache) . managed_pointer ( )
2219
+ tc_ty ( cx, typ, cache) . managed_pointer ( ) | TC :: ReachesFfiUnsafe
2214
2220
}
2215
2221
2216
2222
ty_uniq( typ) => {
2217
- match get ( typ) . sty {
2223
+ TC :: ReachesFfiUnsafe | match get ( typ) . sty {
2218
2224
ty_str => TC :: OwnsOwned ,
2219
2225
_ => tc_ty ( cx, typ, cache) . owned_pointer ( ) ,
2220
2226
}
2221
2227
}
2222
2228
2223
2229
ty_trait( box ty:: TyTrait { bounds, .. } ) => {
2224
- object_contents ( cx, bounds)
2230
+ object_contents ( cx, bounds) | TC :: ReachesFfiUnsafe
2225
2231
}
2226
2232
2227
2233
ty_ptr( ref mt) => {
2228
2234
tc_ty ( cx, mt. ty , cache) . unsafe_pointer ( )
2229
2235
}
2230
2236
2231
2237
ty_rptr( r, ref mt) => {
2232
- match get ( mt. ty ) . sty {
2238
+ TC :: ReachesFfiUnsafe | match get ( mt. ty ) . sty {
2233
2239
ty_str => borrowed_contents ( r, ast:: MutImmutable ) ,
2240
+ ty_vec( ..) => tc_ty ( cx, mt. ty , cache) . reference ( borrowed_contents ( r, mt. mutbl ) ) ,
2234
2241
_ => tc_ty ( cx, mt. ty , cache) . reference ( borrowed_contents ( r, mt. mutbl ) ) ,
2235
2242
}
2236
2243
}
@@ -2244,6 +2251,11 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
2244
2251
let mut res =
2245
2252
TypeContents :: union ( flds. as_slice ( ) ,
2246
2253
|f| tc_mt ( cx, f. mt , cache) ) ;
2254
+
2255
+ if !lookup_repr_hints ( cx, did) . contains ( & attr:: ReprExtern ) {
2256
+ res = res | TC :: ReachesFfiUnsafe ;
2257
+ }
2258
+
2247
2259
if ty:: has_dtor ( cx, did) {
2248
2260
res = res | TC :: OwnsDtor ;
2249
2261
}
@@ -2273,9 +2285,49 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
2273
2285
tc_ty ( cx, * arg_ty, cache)
2274
2286
} )
2275
2287
} ) ;
2288
+
2276
2289
if ty:: has_dtor ( cx, did) {
2277
2290
res = res | TC :: OwnsDtor ;
2278
2291
}
2292
+
2293
+ if variants. len ( ) != 0 {
2294
+ let repr_hints = lookup_repr_hints ( cx, did) ;
2295
+ if repr_hints. len ( ) > 1 {
2296
+ // this is an error later on, but this type isn't safe
2297
+ res = res | TC :: ReachesFfiUnsafe ;
2298
+ }
2299
+
2300
+ match repr_hints. as_slice ( ) . get ( 0 ) {
2301
+ Some ( h) => if !h. is_ffi_safe ( ) {
2302
+ res = res | TC :: ReachesFfiUnsafe ;
2303
+ } ,
2304
+ // ReprAny
2305
+ None => {
2306
+ res = res | TC :: ReachesFfiUnsafe ;
2307
+
2308
+ // We allow ReprAny enums if they are eligible for
2309
+ // the nullable pointer optimization and the
2310
+ // contained type is an `extern fn`
2311
+
2312
+ if variants. len ( ) == 2 {
2313
+ let mut data_idx = 0 ;
2314
+
2315
+ if variants. get ( 0 ) . args . len ( ) == 0 {
2316
+ data_idx = 1 ;
2317
+ }
2318
+
2319
+ if variants. get ( data_idx) . args . len ( ) == 1 {
2320
+ match get ( * variants. get ( data_idx) . args . get ( 0 ) ) . sty {
2321
+ ty_bare_fn( ..) => { res = res - TC :: ReachesFfiUnsafe ; }
2322
+ _ => { }
2323
+ }
2324
+ }
2325
+ }
2326
+ }
2327
+ }
2328
+ }
2329
+
2330
+
2279
2331
apply_lang_items ( cx, did, res)
2280
2332
}
2281
2333
@@ -2427,6 +2479,10 @@ pub fn type_moves_by_default(cx: &ctxt, ty: t) -> bool {
2427
2479
type_contents ( cx, ty) . moves_by_default ( cx)
2428
2480
}
2429
2481
2482
+ pub fn is_ffi_safe ( cx : & ctxt , ty : t ) -> bool {
2483
+ !type_contents ( cx, ty) . intersects ( TC :: ReachesFfiUnsafe )
2484
+ }
2485
+
2430
2486
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2431
2487
pub fn is_instantiable ( cx : & ctxt , r_ty : t ) -> bool {
2432
2488
fn type_requires ( cx : & ctxt , seen : & mut Vec < DefId > ,
@@ -3945,7 +4001,7 @@ pub fn substd_enum_variants(cx: &ctxt,
3945
4001
-> Vec < Rc < VariantInfo > > {
3946
4002
enum_variants ( cx, id) . iter ( ) . map ( |variant_info| {
3947
4003
let substd_args = variant_info. args . iter ( )
3948
- . map ( |aty| aty. subst ( cx, substs) ) . collect ( ) ;
4004
+ . map ( |aty| aty. subst ( cx, substs) ) . collect :: < Vec < _ > > ( ) ;
3949
4005
3950
4006
let substd_ctor_ty = variant_info. ctor_ty . subst ( cx, substs) ;
3951
4007
@@ -4168,24 +4224,26 @@ pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
4168
4224
found
4169
4225
}
4170
4226
4171
- /// Determine whether an item is annotated with `#[packed]`
4227
+ /// Determine whether an item is annotated with `#[repr( packed) ]`
4172
4228
pub fn lookup_packed ( tcx : & ctxt , did : DefId ) -> bool {
4173
- has_attr ( tcx, did, "packed" )
4229
+ lookup_repr_hints ( tcx, did) . contains ( & attr :: ReprPacked )
4174
4230
}
4175
4231
4176
4232
/// Determine whether an item is annotated with `#[simd]`
4177
4233
pub fn lookup_simd ( tcx : & ctxt , did : DefId ) -> bool {
4178
4234
has_attr ( tcx, did, "simd" )
4179
4235
}
4180
4236
4181
- // Obtain the representation annotation for a definition.
4182
- pub fn lookup_repr_hint ( tcx : & ctxt , did : DefId ) -> attr:: ReprAttr {
4183
- let mut acc = attr:: ReprAny ;
4237
+ /// Obtain the representation annotation for a struct definition.
4238
+ pub fn lookup_repr_hints ( tcx : & ctxt , did : DefId ) -> Vec < attr:: ReprAttr > {
4239
+ let mut acc = Vec :: new ( ) ;
4240
+
4184
4241
ty:: each_attr ( tcx, did, |meta| {
4185
- acc = attr:: find_repr_attr ( tcx. sess . diagnostic ( ) , meta, acc ) ;
4242
+ acc. extend ( attr:: find_repr_attrs ( tcx. sess . diagnostic ( ) , meta) . move_iter ( ) ) ;
4186
4243
true
4187
4244
} ) ;
4188
- return acc;
4245
+
4246
+ acc
4189
4247
}
4190
4248
4191
4249
// Look up a field ID, whether or not it's local
0 commit comments