@@ -511,25 +511,23 @@ impl CodeGenerator for CompInfo {
511
511
}
512
512
}
513
513
514
- if !is_union {
515
- let ty = field. ty ( ) . to_rust_ty ( ctx) ;
516
-
517
- let ty = if is_union {
518
- quote_ty ! ( ctx. ext_cx( ) , __BindgenUnionField<$ty>)
519
- } else {
520
- ty
521
- } ;
522
-
523
- let mut attrs = vec ! [ ] ;
524
- if let Some ( comment) = field. comment ( ) {
525
- attrs. push ( doc ! ( comment) ) ;
526
- }
514
+ let ty = field. ty ( ) . to_rust_ty ( ctx) ;
515
+
516
+ let ty = if is_union {
517
+ quote_ty ! ( ctx. ext_cx( ) , __BindgenUnionField<$ty>)
518
+ } else {
519
+ ty
520
+ } ;
527
521
528
- let field = StructFieldBuilder :: named ( field. name ( ) ) . pub_ ( )
529
- . with_attrs ( attrs)
530
- . build_ty ( ty) ;
531
- fields. push ( field) ;
522
+ let mut attrs = vec ! [ ] ;
523
+ if let Some ( comment) = field. comment ( ) {
524
+ attrs. push ( doc ! ( comment) ) ;
532
525
}
526
+
527
+ let field = StructFieldBuilder :: named ( field. name ( ) ) . pub_ ( )
528
+ . with_attrs ( attrs)
529
+ . build_ty ( ty) ;
530
+ fields. push ( field) ;
533
531
}
534
532
535
533
if is_union {
@@ -945,14 +943,80 @@ impl CodeGenerator for Function {
945
943
946
944
pub fn codegen ( context : & mut BindgenContext ) -> Vec < P < ast:: Item > > {
947
945
context. gen ( |context| {
948
- let mut result = vec ! [ ] ;
946
+ let mut result = CodegenResult :: new ( ) ;
949
947
for ( item_id, item) in context. items ( ) {
950
948
// Non-toplevel item parents are the responsible one for generating
951
949
// them.
952
950
if item. is_toplevel ( context) {
953
951
item. codegen ( context, & mut result, & ( ) ) ;
954
952
}
955
953
}
954
+ let saw_union = result. saw_union ;
955
+ let mut result = result. items ;
956
+ if saw_union {
957
+ utils:: prepend_union_types ( context, & mut result) ;
958
+ }
956
959
result
957
960
} )
958
961
}
962
+
963
+ mod utils {
964
+ use ir:: context:: BindgenContext ;
965
+ use syntax:: ast;
966
+ use syntax:: ptr:: P ;
967
+ use std:: mem;
968
+
969
+ pub fn prepend_union_types ( ctx : & BindgenContext , result : & mut Vec < P < ast:: Item > > ) {
970
+ use std:: mem;
971
+ let union_field_decl = quote_item ! ( ctx. ext_cx( ) ,
972
+ #[ derive( Copy , Debug ) ]
973
+ #[ repr( C ) ]
974
+ pub struct __BindgenUnionField<T >( :: std:: marker:: PhantomData <T >) ;
975
+ ) . unwrap ( ) ;
976
+
977
+ let union_field_impl = quote_item ! ( & ctx. ext_cx( ) ,
978
+ impl <T > __BindgenUnionField<T > {
979
+ #[ inline]
980
+ pub fn new( ) -> Self {
981
+ __BindgenUnionField( :: std:: marker:: PhantomData )
982
+ }
983
+
984
+ #[ inline]
985
+ pub unsafe fn as_ref( & self ) -> & T {
986
+ :: std:: mem:: transmute( self )
987
+ }
988
+
989
+ #[ inline]
990
+ pub unsafe fn as_mut( & mut self ) -> & mut T {
991
+ :: std:: mem:: transmute( self )
992
+ }
993
+ }
994
+ ) . unwrap ( ) ;
995
+
996
+ let union_field_default_impl = quote_item ! ( & ctx. ext_cx( ) ,
997
+ impl <T > :: std:: default :: Default for __BindgenUnionField<T > {
998
+ #[ inline]
999
+ fn default ( ) -> Self {
1000
+ Self :: new( )
1001
+ }
1002
+ }
1003
+ ) . unwrap ( ) ;
1004
+
1005
+ let union_field_clone_impl = quote_item ! ( & ctx. ext_cx( ) ,
1006
+ impl <T > :: std:: clone:: Clone for __BindgenUnionField<T > {
1007
+ #[ inline]
1008
+ fn clone( & self ) -> Self {
1009
+ Self :: new( )
1010
+ }
1011
+ }
1012
+ ) . unwrap ( ) ;
1013
+
1014
+ let items = vec ! [
1015
+ union_field_decl, union_field_impl,
1016
+ union_field_default_impl, union_field_clone_impl
1017
+ ] ;
1018
+
1019
+ let old_items = mem:: replace ( result, items) ;
1020
+ result. extend ( old_items. into_iter ( ) ) ;
1021
+ }
1022
+ }
0 commit comments