@@ -1454,10 +1454,13 @@ impl<'a> FieldCodegen<'a> for FieldData {
1454
1454
wrap_union_field_if_needed ( ctx, struct_layout, ty, result)
1455
1455
} else if let Some ( item) = field_ty. is_incomplete_array ( ctx) {
1456
1456
result. saw_incomplete_array ( ) ;
1457
+ struct_layout. saw_flexible_array ( ) ;
1457
1458
1458
1459
let inner = item. to_rust_ty_or_opaque ( ctx, & ( ) ) ;
1459
1460
1460
- if ctx. options ( ) . enable_cxx_namespaces {
1461
+ if ctx. options ( ) . flexarray_dst {
1462
+ syn:: parse_quote! { FAM }
1463
+ } else if ctx. options ( ) . enable_cxx_namespaces {
1461
1464
syn:: parse_quote! { root:: __IncompleteArrayField<#inner> }
1462
1465
} else {
1463
1466
syn:: parse_quote! { __IncompleteArrayField<#inner> }
@@ -2208,20 +2211,60 @@ impl CodeGenerator for CompInfo {
2208
2211
} ) ;
2209
2212
}
2210
2213
2211
- let generics = if !generic_param_names. is_empty ( ) {
2212
- let generic_param_names = generic_param_names. clone ( ) ;
2213
- quote ! {
2214
- < #( #generic_param_names ) , * >
2214
+ let ( flex_array_generic, flex_inner_ty) = if ctx. options ( ) . flexarray_dst
2215
+ {
2216
+ match self . flex_array_member ( ctx) {
2217
+ Some ( ty) => {
2218
+ let inner = ty. to_rust_ty_or_opaque ( ctx, & ( ) ) ;
2219
+ (
2220
+ Some ( quote ! { FAM : ?Sized = [ #inner; 0 ] } ) ,
2221
+ Some ( quote ! { #inner } ) ,
2222
+ )
2223
+ }
2224
+ None => ( None , None ) ,
2215
2225
}
2216
2226
} else {
2217
- quote ! { }
2227
+ ( None , None )
2218
2228
} ;
2219
2229
2230
+ // Generics, including the flexible array member.
2231
+ //
2232
+ // generics - generic parameters for the struct declaration
2233
+ // impl_generics_labels - generic parameters for `impl<...>`
2234
+ // impl_generics_params - generic parameters for `impl structname<...>`
2235
+ //
2236
+ // `impl` blocks are for non-FAM related impls like Default, etc
2237
+ let ( generics, impl_generics_labels, impl_generics_params) =
2238
+ if !generic_param_names. is_empty ( ) || flex_array_generic. is_some ( ) {
2239
+ let ( flex_sized, flex_fam) = match flex_inner_ty. as_ref ( ) {
2240
+ None => ( None , None ) ,
2241
+ Some ( ty) => (
2242
+ Some ( quote ! { [ #ty; 0 ] } ) ,
2243
+ Some ( quote ! { FAM : ?Sized = [ #ty; 0 ] } ) ,
2244
+ ) ,
2245
+ } ;
2246
+
2247
+ (
2248
+ quote ! {
2249
+ < #( #generic_param_names , ) * #flex_fam >
2250
+ } ,
2251
+ quote ! {
2252
+ < #( #generic_param_names , ) * >
2253
+ } ,
2254
+ quote ! {
2255
+ < #( #generic_param_names , ) * #flex_sized >
2256
+ } ,
2257
+ )
2258
+ } else {
2259
+ ( quote ! { } , quote ! { } , quote ! { } )
2260
+ } ;
2261
+
2220
2262
let mut attributes = vec ! [ ] ;
2221
2263
let mut needs_clone_impl = false ;
2222
2264
let mut needs_default_impl = false ;
2223
2265
let mut needs_debug_impl = false ;
2224
2266
let mut needs_partialeq_impl = false ;
2267
+ let needs_flexarray_impl = flex_array_generic. is_some ( ) ;
2225
2268
if let Some ( comment) = item. comment ( ctx) {
2226
2269
attributes. push ( attributes:: doc ( comment) ) ;
2227
2270
}
@@ -2525,17 +2568,112 @@ impl CodeGenerator for CompInfo {
2525
2568
// NB: We can't use to_rust_ty here since for opaque types this tries to
2526
2569
// use the specialization knowledge to generate a blob field.
2527
2570
let ty_for_impl = quote ! {
2528
- #canonical_ident #generics
2571
+ #canonical_ident #impl_generics_params
2529
2572
} ;
2530
2573
2531
2574
if needs_clone_impl {
2532
2575
result. push ( quote ! {
2533
- impl #generics Clone for #ty_for_impl {
2576
+ impl #impl_generics_labels Clone for #ty_for_impl {
2534
2577
fn clone( & self ) -> Self { * self }
2535
2578
}
2536
2579
} ) ;
2537
2580
}
2538
2581
2582
+ if needs_flexarray_impl {
2583
+ let prefix = ctx. trait_prefix ( ) ;
2584
+
2585
+ let flex_array =
2586
+ flex_inner_ty. as_ref ( ) . map ( |ty| quote ! { [ #ty ] } ) ;
2587
+
2588
+ let dst_ty_for_impl = quote ! {
2589
+ #canonical_ident < #( #generic_param_names , ) * #flex_array >
2590
+
2591
+ } ;
2592
+ let sized_ty_for_impl = quote ! {
2593
+ #canonical_ident < #( #generic_param_names , ) * [ #flex_inner_ty; 0 ] >
2594
+ } ;
2595
+
2596
+ let turbo_dst_ty = quote ! {
2597
+ #canonical_ident :: < #( #generic_param_names , ) * [ #flex_inner_ty ] >
2598
+ } ;
2599
+
2600
+ let layout = if ctx. options ( ) . rust_features ( ) . layout_for_ptr {
2601
+ quote ! {
2602
+ pub fn layout( len: usize ) -> :: #prefix:: alloc:: Layout {
2603
+ // SAFETY: Null pointers are OK if we don't deref them
2604
+ unsafe {
2605
+ let p: * const Self = :: #prefix:: ptr:: from_raw_parts( :: #prefix:: ptr:: null( ) , len) ;
2606
+ :: #prefix:: alloc:: Layout :: for_value_raw( p)
2607
+ }
2608
+ }
2609
+ }
2610
+ } else {
2611
+ quote ! ( )
2612
+ } ;
2613
+
2614
+ let ( from_ptr_dst, from_ptr_sized) = if ctx
2615
+ . options ( )
2616
+ . rust_features ( )
2617
+ . ptr_metadata
2618
+ {
2619
+ (
2620
+ quote ! {
2621
+ /// Construct a DST for `#canonical_ident` from a thin
2622
+ /// pointer.
2623
+ ///
2624
+ /// SAFETY: the `len` must be <= the underlying storage.
2625
+ /// Note: returned lifetime is unbounded.
2626
+ pub unsafe fn from_ptr<' a>( ptr: * const #sized_ty_for_impl, len: usize ) -> & ' a Self {
2627
+ let ptr: * const Self = :: #prefix:: ptr:: from_raw_parts( ptr as * const ( ) , len) ;
2628
+ & * ptr
2629
+ }
2630
+
2631
+ /// Construct a mutable DST for `#canonical_ident` from
2632
+ /// a thin pointer. This is `MaybeUninit` to allow for
2633
+ /// initialization.
2634
+ ///
2635
+ /// SAFETY: the `len` must be <= the underlying storage.
2636
+ /// Note: returned lifetime is unbounded.
2637
+ pub unsafe fn from_ptr_mut<' a>( ptr: * mut #sized_ty_for_impl, len: usize ) -> :: #prefix:: mem:: MaybeUninit <& ' a mut Self > {
2638
+ let ptr: * mut Self = :: #prefix:: ptr:: from_raw_parts_mut( ptr as * mut ( ) , len) ;
2639
+ :: #prefix:: mem:: MaybeUninit :: new( & mut * ptr)
2640
+ }
2641
+ } ,
2642
+ quote ! {
2643
+ /// Turn a sized reference for `#canonical_ident` into
2644
+ /// DST with the given `len`.
2645
+ ///
2646
+ /// SAFETY: the `len` must be <= the underlying storage.
2647
+ pub unsafe fn from_ref( & self , len: usize ) -> & #dst_ty_for_impl {
2648
+ // SAFETY: caller guarantees `len` is good
2649
+ unsafe { #turbo_dst_ty :: from_ptr( self , len) }
2650
+ }
2651
+
2652
+ /// Turn a mutable sized reference for
2653
+ /// `#canonical_ident` into DST with the given `len`.
2654
+ ///
2655
+ /// SAFETY: the `len` must be <= the underlying storage.
2656
+ pub unsafe fn from_ref_mut( & mut self , len: usize ) -> & mut #dst_ty_for_impl {
2657
+ unsafe { #turbo_dst_ty :: from_ptr_mut( self , len) . assume_init( ) }
2658
+ }
2659
+ } ,
2660
+ )
2661
+ } else {
2662
+ ( quote ! ( ) , quote ! ( ) )
2663
+ } ;
2664
+
2665
+ result. push ( quote ! {
2666
+ impl #impl_generics_labels #dst_ty_for_impl {
2667
+ #layout
2668
+ #from_ptr_dst
2669
+ }
2670
+
2671
+ impl #impl_generics_labels #sized_ty_for_impl {
2672
+ #from_ptr_sized
2673
+ }
2674
+ } ) ;
2675
+ }
2676
+
2539
2677
if needs_default_impl {
2540
2678
let prefix = ctx. trait_prefix ( ) ;
2541
2679
let body = if ctx. options ( ) . rust_features ( ) . maybe_uninit {
@@ -2560,7 +2698,7 @@ impl CodeGenerator for CompInfo {
2560
2698
// non-zero padding bytes, especially when forwards/backwards compatibility is
2561
2699
// involved.
2562
2700
result. push ( quote ! {
2563
- impl #generics Default for #ty_for_impl {
2701
+ impl #impl_generics_labels Default for #ty_for_impl {
2564
2702
fn default ( ) -> Self {
2565
2703
#body
2566
2704
}
@@ -2579,7 +2717,7 @@ impl CodeGenerator for CompInfo {
2579
2717
let prefix = ctx. trait_prefix ( ) ;
2580
2718
2581
2719
result. push ( quote ! {
2582
- impl #generics :: #prefix:: fmt:: Debug for #ty_for_impl {
2720
+ impl #impl_generics_labels :: #prefix:: fmt:: Debug for #ty_for_impl {
2583
2721
#impl_
2584
2722
}
2585
2723
} ) ;
@@ -2603,7 +2741,7 @@ impl CodeGenerator for CompInfo {
2603
2741
2604
2742
let prefix = ctx. trait_prefix ( ) ;
2605
2743
result. push ( quote ! {
2606
- impl #generics :: #prefix:: cmp:: PartialEq for #ty_for_impl #partialeq_bounds {
2744
+ impl #impl_generics_labels :: #prefix:: cmp:: PartialEq for #ty_for_impl #partialeq_bounds {
2607
2745
#impl_
2608
2746
}
2609
2747
} ) ;
@@ -2612,7 +2750,7 @@ impl CodeGenerator for CompInfo {
2612
2750
2613
2751
if !methods. is_empty ( ) {
2614
2752
result. push ( quote ! {
2615
- impl #generics #ty_for_impl {
2753
+ impl #impl_generics_labels #ty_for_impl {
2616
2754
#( #methods ) *
2617
2755
}
2618
2756
} ) ;
@@ -5130,6 +5268,9 @@ pub(crate) mod utils {
5130
5268
ctx : & BindgenContext ,
5131
5269
result : & mut Vec < proc_macro2:: TokenStream > ,
5132
5270
) {
5271
+ if ctx. options ( ) . flexarray_dst {
5272
+ return ;
5273
+ }
5133
5274
let prefix = ctx. trait_prefix ( ) ;
5134
5275
5135
5276
// If the target supports `const fn`, declare eligible functions
0 commit comments