@@ -425,7 +425,7 @@ pub struct t { inner: *const t_opaque }
425
425
426
426
impl fmt:: Show for t {
427
427
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
428
- "*t_opaque" . fmt ( f )
428
+ write ! ( f , "{}" , get ( * self ) )
429
429
}
430
430
}
431
431
@@ -1811,7 +1811,8 @@ def_type_content_sets!(
1811
1811
// ReachesManaged /* see [1] below */ = 0b0000_0100__0000_0000__0000,
1812
1812
ReachesMutable = 0b0000_1000__0000_0000__0000 ,
1813
1813
ReachesNoSync = 0b0001_0000__0000_0000__0000 ,
1814
- ReachesAll = 0b0001_1111__0000_0000__0000 ,
1814
+ ReachesFfiUnsafe = 0b0010_0000__0000_0000__0000 ,
1815
+ ReachesAll = 0b0011_1111__0000_0000__0000 ,
1815
1816
1816
1817
// Things that cause values to *move* rather than *copy*
1817
1818
Moves = 0b0000_0000__0000_1011__0000 ,
@@ -2048,38 +2049,44 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
2048
2049
cache. insert ( ty_id, TC :: None ) ;
2049
2050
2050
2051
let result = match get ( ty) . sty {
2052
+ // uint and int are ffi-unsafe
2053
+ ty_uint( ast:: TyU ) | ty_int( ast:: TyI ) => {
2054
+ TC :: ReachesFfiUnsafe
2055
+ }
2056
+
2051
2057
// Scalar and unique types are sendable, and durable
2052
2058
ty_nil | ty_bot | ty_bool | ty_int( _) | ty_uint( _) | ty_float( _) |
2053
2059
ty_bare_fn( _) | ty:: ty_char | ty_str => {
2054
2060
TC :: None
2055
2061
}
2056
2062
2057
2063
ty_closure( ref c) => {
2058
- closure_contents ( cx, & * * c)
2064
+ closure_contents ( cx, & * * c) | TC :: ReachesFfiUnsafe
2059
2065
}
2060
2066
2061
2067
ty_box( typ) => {
2062
- tc_ty ( cx, typ, cache) . managed_pointer ( )
2068
+ tc_ty ( cx, typ, cache) . managed_pointer ( ) | TC :: ReachesFfiUnsafe
2063
2069
}
2064
2070
2065
2071
ty_uniq( typ) => {
2066
- match get ( typ) . sty {
2072
+ TC :: ReachesFfiUnsafe | match get ( typ) . sty {
2067
2073
ty_str => TC :: OwnsOwned ,
2068
2074
_ => tc_ty ( cx, typ, cache) . owned_pointer ( ) ,
2069
2075
}
2070
2076
}
2071
2077
2072
2078
ty_trait( box ty:: TyTrait { bounds, .. } ) => {
2073
- object_contents ( cx, bounds)
2079
+ object_contents ( cx, bounds) | TC :: ReachesFfiUnsafe
2074
2080
}
2075
2081
2076
2082
ty_ptr( ref mt) => {
2077
2083
tc_ty ( cx, mt. ty , cache) . unsafe_pointer ( )
2078
2084
}
2079
2085
2080
2086
ty_rptr( r, ref mt) => {
2081
- match get ( mt. ty ) . sty {
2087
+ TC :: ReachesFfiUnsafe | match get ( mt. ty ) . sty {
2082
2088
ty_str => borrowed_contents ( r, ast:: MutImmutable ) ,
2089
+ ty_vec( ..) => tc_ty ( cx, mt. ty , cache) . reference ( borrowed_contents ( r, mt. mutbl ) ) ,
2083
2090
_ => tc_ty ( cx, mt. ty , cache) . reference ( borrowed_contents ( r, mt. mutbl ) ) ,
2084
2091
}
2085
2092
}
@@ -2093,6 +2100,11 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
2093
2100
let mut res =
2094
2101
TypeContents :: union ( flds. as_slice ( ) ,
2095
2102
|f| tc_mt ( cx, f. mt , cache) ) ;
2103
+
2104
+ if !lookup_repr_hints ( cx, did) . contains ( & attr:: ReprExtern ) {
2105
+ res = res | TC :: ReachesFfiUnsafe ;
2106
+ }
2107
+
2096
2108
if ty:: has_dtor ( cx, did) {
2097
2109
res = res | TC :: OwnsDtor ;
2098
2110
}
@@ -2119,9 +2131,49 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
2119
2131
tc_ty ( cx, * arg_ty, cache)
2120
2132
} )
2121
2133
} ) ;
2134
+
2122
2135
if ty:: has_dtor ( cx, did) {
2123
2136
res = res | TC :: OwnsDtor ;
2124
2137
}
2138
+
2139
+ if variants. len ( ) != 0 {
2140
+ let repr_hints = lookup_repr_hints ( cx, did) ;
2141
+ if repr_hints. len ( ) > 1 {
2142
+ // this is an error later on, but this type isn't safe
2143
+ res = res | TC :: ReachesFfiUnsafe ;
2144
+ }
2145
+
2146
+ match repr_hints. as_slice ( ) . get ( 0 ) {
2147
+ Some ( h) => if !h. is_ffi_safe ( ) {
2148
+ res = res | TC :: ReachesFfiUnsafe ;
2149
+ } ,
2150
+ // ReprAny
2151
+ None => {
2152
+ res = res | TC :: ReachesFfiUnsafe ;
2153
+
2154
+ // We allow ReprAny enums if they are eligible for
2155
+ // the nullable pointer optimization and the
2156
+ // contained type is an `extern fn`
2157
+
2158
+ if variants. len ( ) == 2 {
2159
+ let mut data_idx = 0 ;
2160
+
2161
+ if variants. get ( 0 ) . args . len ( ) == 0 {
2162
+ data_idx = 1 ;
2163
+ }
2164
+
2165
+ if variants. get ( data_idx) . args . len ( ) == 1 {
2166
+ match get ( * variants. get ( data_idx) . args . get ( 0 ) ) . sty {
2167
+ ty_bare_fn( ..) => { res = res - TC :: ReachesFfiUnsafe ; }
2168
+ _ => { }
2169
+ }
2170
+ }
2171
+ }
2172
+ }
2173
+ }
2174
+ }
2175
+
2176
+
2125
2177
apply_lang_items ( cx, did, res)
2126
2178
}
2127
2179
@@ -2273,6 +2325,10 @@ pub fn type_moves_by_default(cx: &ctxt, ty: t) -> bool {
2273
2325
type_contents ( cx, ty) . moves_by_default ( cx)
2274
2326
}
2275
2327
2328
+ pub fn is_ffi_safe ( cx : & ctxt , ty : t ) -> bool {
2329
+ !type_contents ( cx, ty) . intersects ( TC :: ReachesFfiUnsafe )
2330
+ }
2331
+
2276
2332
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2277
2333
pub fn is_instantiable ( cx : & ctxt , r_ty : t ) -> bool {
2278
2334
fn type_requires ( cx : & ctxt , seen : & mut Vec < DefId > ,
@@ -3767,7 +3823,7 @@ pub fn substd_enum_variants(cx: &ctxt,
3767
3823
-> Vec < Rc < VariantInfo > > {
3768
3824
enum_variants ( cx, id) . iter ( ) . map ( |variant_info| {
3769
3825
let substd_args = variant_info. args . iter ( )
3770
- . map ( |aty| aty. subst ( cx, substs) ) . collect ( ) ;
3826
+ . map ( |aty| aty. subst ( cx, substs) ) . collect :: < Vec < _ > > ( ) ;
3771
3827
3772
3828
let substd_ctor_ty = variant_info. ctor_ty . subst ( cx, substs) ;
3773
3829
@@ -3990,24 +4046,26 @@ pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
3990
4046
found
3991
4047
}
3992
4048
3993
- /// Determine whether an item is annotated with `#[packed]`
4049
+ /// Determine whether an item is annotated with `#[repr( packed) ]`
3994
4050
pub fn lookup_packed ( tcx : & ctxt , did : DefId ) -> bool {
3995
- has_attr ( tcx, did, "packed" )
4051
+ lookup_repr_hints ( tcx, did) . contains ( & attr :: ReprPacked )
3996
4052
}
3997
4053
3998
4054
/// Determine whether an item is annotated with `#[simd]`
3999
4055
pub fn lookup_simd ( tcx : & ctxt , did : DefId ) -> bool {
4000
4056
has_attr ( tcx, did, "simd" )
4001
4057
}
4002
4058
4003
- // Obtain the representation annotation for a definition.
4004
- pub fn lookup_repr_hint ( tcx : & ctxt , did : DefId ) -> attr:: ReprAttr {
4005
- let mut acc = attr:: ReprAny ;
4059
+ /// Obtain the representation annotation for a struct definition.
4060
+ pub fn lookup_repr_hints ( tcx : & ctxt , did : DefId ) -> Vec < attr:: ReprAttr > {
4061
+ let mut acc = Vec :: new ( ) ;
4062
+
4006
4063
ty:: each_attr ( tcx, did, |meta| {
4007
- acc = attr:: find_repr_attr ( tcx. sess . diagnostic ( ) , meta, acc ) ;
4064
+ acc. extend ( attr:: find_repr_attrs ( tcx. sess . diagnostic ( ) , meta) . move_iter ( ) ) ;
4008
4065
true
4009
4066
} ) ;
4010
- return acc;
4067
+
4068
+ acc
4011
4069
}
4012
4070
4013
4071
// Look up a field ID, whether or not it's local
0 commit comments