@@ -1231,7 +1231,7 @@ trait FieldCodegen<'a> {
1231
1231
}
1232
1232
1233
1233
impl < ' a > FieldCodegen < ' a > for Field {
1234
- type Extra = ( ) ;
1234
+ type Extra = & ' a str ;
1235
1235
1236
1236
fn codegen < F , M > (
1237
1237
& self ,
@@ -1244,7 +1244,7 @@ impl<'a> FieldCodegen<'a> for Field {
1244
1244
struct_layout : & mut StructLayoutTracker ,
1245
1245
fields : & mut F ,
1246
1246
methods : & mut M ,
1247
- _ : ( ) ,
1247
+ parent_canonical_name : Self :: Extra ,
1248
1248
) where
1249
1249
F : Extend < proc_macro2:: TokenStream > ,
1250
1250
M : Extend < proc_macro2:: TokenStream > ,
@@ -1261,7 +1261,7 @@ impl<'a> FieldCodegen<'a> for Field {
1261
1261
struct_layout,
1262
1262
fields,
1263
1263
methods,
1264
- ( ) ,
1264
+ parent_canonical_name ,
1265
1265
) ;
1266
1266
}
1267
1267
Field :: Bitfields ( ref unit) => {
@@ -1275,15 +1275,15 @@ impl<'a> FieldCodegen<'a> for Field {
1275
1275
struct_layout,
1276
1276
fields,
1277
1277
methods,
1278
- ( ) ,
1278
+ parent_canonical_name ,
1279
1279
) ;
1280
1280
}
1281
1281
}
1282
1282
}
1283
1283
}
1284
1284
1285
1285
impl < ' a > FieldCodegen < ' a > for FieldData {
1286
- type Extra = ( ) ;
1286
+ type Extra = & ' a str ;
1287
1287
1288
1288
fn codegen < F , M > (
1289
1289
& self ,
@@ -1296,7 +1296,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
1296
1296
struct_layout : & mut StructLayoutTracker ,
1297
1297
fields : & mut F ,
1298
1298
methods : & mut M ,
1299
- _ : ( ) ,
1299
+ parent_canonical_name : Self :: Extra ,
1300
1300
) where
1301
1301
F : Extend < proc_macro2:: TokenStream > ,
1302
1302
M : Extend < proc_macro2:: TokenStream > ,
@@ -1313,16 +1313,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
1313
1313
1314
1314
// NB: If supported, we use proper `union` types.
1315
1315
let ty = if parent. is_union ( ) && !struct_layout. is_rust_union ( ) {
1316
- result. saw_bindgen_union ( ) ;
1317
- if ctx. options ( ) . enable_cxx_namespaces {
1318
- quote ! {
1319
- root:: __BindgenUnionField<#ty>
1320
- }
1321
- } else {
1322
- quote ! {
1323
- __BindgenUnionField<#ty>
1324
- }
1325
- }
1316
+ wrap_non_copy_type_for_union ( ctx, parent_canonical_name, result, ty)
1326
1317
} else if let Some ( item) = field_ty. is_incomplete_array ( ctx) {
1327
1318
result. saw_incomplete_array ( ) ;
1328
1319
@@ -1433,6 +1424,54 @@ impl<'a> FieldCodegen<'a> for FieldData {
1433
1424
}
1434
1425
}
1435
1426
1427
+ fn wrap_non_copy_type_for_union (
1428
+ ctx : & BindgenContext ,
1429
+ parent_canonical_name : & str ,
1430
+ result : & mut CodegenResult ,
1431
+ field_ty : proc_macro2:: TokenStream ,
1432
+ ) -> proc_macro2:: TokenStream {
1433
+ let union_style = union_style_from_ctx_and_name ( ctx, parent_canonical_name) ;
1434
+
1435
+ match union_style {
1436
+ NonCopyUnionStyle :: ManuallyDrop => {
1437
+ if ctx. options ( ) . use_core {
1438
+ quote ! {
1439
+ :: core:: mem:: ManuallyDrop <#field_ty>
1440
+ }
1441
+ } else {
1442
+ quote ! {
1443
+ :: std:: mem:: ManuallyDrop <#field_ty>
1444
+ }
1445
+ }
1446
+ }
1447
+ NonCopyUnionStyle :: BindgenWrapper => {
1448
+ result. saw_bindgen_union ( ) ;
1449
+ if ctx. options ( ) . enable_cxx_namespaces {
1450
+ quote ! {
1451
+ root:: __BindgenUnionField<#field_ty>
1452
+ }
1453
+ } else {
1454
+ quote ! {
1455
+ __BindgenUnionField<#field_ty>
1456
+ }
1457
+ }
1458
+ }
1459
+ }
1460
+ }
1461
+
1462
+ fn union_style_from_ctx_and_name (
1463
+ ctx : & BindgenContext ,
1464
+ canonical_name : & str ,
1465
+ ) -> NonCopyUnionStyle {
1466
+ if ctx. options ( ) . bindgen_wrapper_union . matches ( canonical_name) {
1467
+ NonCopyUnionStyle :: BindgenWrapper
1468
+ } else if ctx. options ( ) . manually_drop_union . matches ( canonical_name) {
1469
+ NonCopyUnionStyle :: ManuallyDrop
1470
+ } else {
1471
+ ctx. options ( ) . default_non_copy_union_style
1472
+ }
1473
+ }
1474
+
1436
1475
impl BitfieldUnit {
1437
1476
/// Get the constructor name for this bitfield unit.
1438
1477
fn ctor_name ( & self ) -> proc_macro2:: TokenStream {
@@ -1499,7 +1538,7 @@ fn access_specifier(
1499
1538
}
1500
1539
1501
1540
impl < ' a > FieldCodegen < ' a > for BitfieldUnit {
1502
- type Extra = ( ) ;
1541
+ type Extra = & ' a str ;
1503
1542
1504
1543
fn codegen < F , M > (
1505
1544
& self ,
@@ -1512,7 +1551,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
1512
1551
struct_layout : & mut StructLayoutTracker ,
1513
1552
fields : & mut F ,
1514
1553
methods : & mut M ,
1515
- _ : ( ) ,
1554
+ parent_canonical_name : Self :: Extra ,
1516
1555
) where
1517
1556
F : Extend < proc_macro2:: TokenStream > ,
1518
1557
M : Extend < proc_macro2:: TokenStream > ,
@@ -1525,16 +1564,12 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
1525
1564
let unit_field_ty = helpers:: bitfield_unit ( ctx, layout) ;
1526
1565
let field_ty = {
1527
1566
if parent. is_union ( ) && !struct_layout. is_rust_union ( ) {
1528
- result. saw_bindgen_union ( ) ;
1529
- if ctx. options ( ) . enable_cxx_namespaces {
1530
- quote ! {
1531
- root:: __BindgenUnionField<#unit_field_ty>
1532
- }
1533
- } else {
1534
- quote ! {
1535
- __BindgenUnionField<#unit_field_ty>
1536
- }
1537
- }
1567
+ wrap_non_copy_type_for_union (
1568
+ ctx,
1569
+ parent_canonical_name,
1570
+ result,
1571
+ unit_field_ty. clone ( ) ,
1572
+ )
1538
1573
} else {
1539
1574
unit_field_ty. clone ( )
1540
1575
}
@@ -1859,7 +1894,7 @@ impl CodeGenerator for CompInfo {
1859
1894
& mut struct_layout,
1860
1895
& mut fields,
1861
1896
& mut methods,
1862
- ( ) ,
1897
+ & canonical_name ,
1863
1898
) ;
1864
1899
}
1865
1900
// Check whether an explicit padding field is needed
@@ -1965,7 +2000,10 @@ impl CodeGenerator for CompInfo {
1965
2000
explicit_align = Some ( layout. align ) ;
1966
2001
}
1967
2002
1968
- if !struct_layout. is_rust_union ( ) {
2003
+ if !struct_layout. is_rust_union ( ) &&
2004
+ union_style_from_ctx_and_name ( ctx, & canonical_name) ==
2005
+ NonCopyUnionStyle :: BindgenWrapper
2006
+ {
1969
2007
let ty = helpers:: blob ( ctx, layout) ;
1970
2008
fields. push ( quote ! {
1971
2009
pub bindgen_union_field: #ty ,
@@ -2092,6 +2130,15 @@ impl CodeGenerator for CompInfo {
2092
2130
#( #attributes ) *
2093
2131
pub union #canonical_ident
2094
2132
}
2133
+ } else if is_union &&
2134
+ !struct_layout. is_rust_union ( ) &&
2135
+ union_style_from_ctx_and_name ( ctx, & canonical_name) ==
2136
+ NonCopyUnionStyle :: ManuallyDrop
2137
+ {
2138
+ quote ! {
2139
+ #( #attributes ) *
2140
+ pub union #canonical_ident
2141
+ }
2095
2142
} else {
2096
2143
quote ! {
2097
2144
#( #attributes ) *
@@ -3398,6 +3445,52 @@ impl std::str::FromStr for AliasVariation {
3398
3445
}
3399
3446
}
3400
3447
3448
+ /// Enum for how non-Copy unions should be translated.
3449
+ #[ derive( Copy , Clone , PartialEq , Debug ) ]
3450
+ pub enum NonCopyUnionStyle {
3451
+ /// Wrap members in a type generated by bindgen.
3452
+ BindgenWrapper ,
3453
+ /// Wrap members in [`::core::mem::ManuallyDrop`].
3454
+ ///
3455
+ /// Note: `ManuallyDrop` was stabilized in Rust 1.20.0, do not use it if your
3456
+ /// MSRV is lower.
3457
+ ManuallyDrop ,
3458
+ }
3459
+
3460
+ impl NonCopyUnionStyle {
3461
+ /// Convert an `NonCopyUnionStyle` to its str representation.
3462
+ pub fn as_str ( & self ) -> & ' static str {
3463
+ match self {
3464
+ Self :: BindgenWrapper => "bindgen_wrapper" ,
3465
+ Self :: ManuallyDrop => "manually_drop" ,
3466
+ }
3467
+ }
3468
+ }
3469
+
3470
+ impl Default for NonCopyUnionStyle {
3471
+ fn default ( ) -> Self {
3472
+ Self :: BindgenWrapper
3473
+ }
3474
+ }
3475
+
3476
+ impl std:: str:: FromStr for NonCopyUnionStyle {
3477
+ type Err = std:: io:: Error ;
3478
+
3479
+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
3480
+ match s {
3481
+ "bindgen_wrapper" => Ok ( Self :: BindgenWrapper ) ,
3482
+ "manually_drop" => Ok ( Self :: ManuallyDrop ) ,
3483
+ _ => Err ( std:: io:: Error :: new (
3484
+ std:: io:: ErrorKind :: InvalidInput ,
3485
+ concat ! (
3486
+ "Got an invalid NonCopyUnionStyle. Accepted values " ,
3487
+ "are 'bindgen_wrapper' and 'manually_drop'"
3488
+ ) ,
3489
+ ) ) ,
3490
+ }
3491
+ }
3492
+ }
3493
+
3401
3494
/// Fallible conversion to an opaque blob.
3402
3495
///
3403
3496
/// Implementors of this trait should provide the `try_get_layout` method to
0 commit comments