@@ -22,18 +22,17 @@ use crate::{
22
22
types:: Namespace ,
23
23
types:: TypeName ,
24
24
} ;
25
- use proc_macro2:: { TokenStream as TokenStream2 , TokenTree } ;
25
+ use proc_macro2:: TokenStream as TokenStream2 ;
26
26
use quote:: quote;
27
- use syn:: {
28
- parse:: Parser , parse_quote, Field , Fields , ForeignItem , GenericParam , Item , ItemStruct , Type ,
29
- } ;
27
+ use syn:: { parse_quote, Fields , ForeignItem , Item , ItemStruct , Type } ;
30
28
31
29
use super :: {
32
30
super :: {
33
31
api:: { Api , Use } ,
34
32
utilities:: generate_utilities,
35
33
} ,
36
34
bridge_name_tracker:: BridgeNameTracker ,
35
+ non_pod_struct:: make_non_pod,
37
36
rust_name_tracker:: RustNameTracker ,
38
37
type_converter:: TypeConverter ,
39
38
} ;
@@ -49,7 +48,7 @@ enum TypeKind {
49
48
50
49
/// Parses a bindgen mod in order to understand the APIs within it.
51
50
pub ( crate ) struct ParseBindgen < ' a > {
52
- type_converter : TypeConverter ,
51
+ type_converter : TypeConverter < ' a > ,
53
52
byvalue_checker : ByValueChecker ,
54
53
type_database : & ' a TypeDatabase ,
55
54
bridge_name_tracker : BridgeNameTracker ,
@@ -61,7 +60,7 @@ pub(crate) struct ParseBindgen<'a> {
61
60
impl < ' a > ParseBindgen < ' a > {
62
61
pub ( crate ) fn new ( byvalue_checker : ByValueChecker , type_database : & ' a TypeDatabase ) -> Self {
63
62
ParseBindgen {
64
- type_converter : TypeConverter :: new ( ) ,
63
+ type_converter : TypeConverter :: new ( type_database ) ,
65
64
byvalue_checker,
66
65
bridge_name_tracker : BridgeNameTracker :: new ( ) ,
67
66
rust_name_tracker : RustNameTracker :: new ( ) ,
@@ -138,7 +137,7 @@ impl<'a> ParseBindgen<'a> {
138
137
let field_types = match type_kind {
139
138
TypeKind :: POD => self . get_struct_field_types ( & ns, & s) ?,
140
139
_ => {
141
- Self :: make_non_pod ( & mut s) ;
140
+ make_non_pod ( & mut s) ;
142
141
HashSet :: new ( )
143
142
}
144
143
} ;
@@ -234,13 +233,14 @@ impl<'a> ParseBindgen<'a> {
234
233
}
235
234
236
235
fn get_struct_field_types (
237
- & self ,
236
+ & mut self ,
238
237
ns : & Namespace ,
239
238
s : & ItemStruct ,
240
239
) -> Result < HashSet < TypeName > , ConvertError > {
241
240
let mut results = HashSet :: new ( ) ;
242
241
for f in & s. fields {
243
242
let annotated = self . type_converter . convert_type ( f. ty . clone ( ) , ns) ?;
243
+ self . results . apis . extend ( annotated. extra_apis ) ;
244
244
results. extend ( annotated. types_encountered ) ;
245
245
}
246
246
Ok ( results)
@@ -252,47 +252,6 @@ impl<'a> ParseBindgen<'a> {
252
252
. any ( |id| id == "_unused" )
253
253
}
254
254
255
- fn make_non_pod ( s : & mut ItemStruct ) {
256
- // Thanks to dtolnay@ for this explanation of why the following
257
- // is needed:
258
- // If the real alignment of the C++ type is smaller and a reference
259
- // is returned from C++ to Rust, mere existence of an insufficiently
260
- // aligned reference in Rust causes UB even if never dereferenced
261
- // by Rust code
262
- // (see https://doc.rust-lang.org/1.47.0/reference/behavior-considered-undefined.html).
263
- // Rustc can use least-significant bits of the reference for other storage.
264
- s. attrs = vec ! [ parse_quote!(
265
- #[ repr( C , packed) ]
266
- ) ] ;
267
- // Now fill in fields. Usually, we just want a single field
268
- // but if this is a generic type we need to faff a bit.
269
- let generic_type_fields =
270
- s. generics
271
- . params
272
- . iter ( )
273
- . enumerate ( )
274
- . filter_map ( |( counter, gp) | match gp {
275
- GenericParam :: Type ( gpt) => {
276
- let id = & gpt. ident ;
277
- let field_name = make_ident ( & format ! ( "_phantom_{}" , counter) ) ;
278
- let toks = quote ! {
279
- #field_name: :: std:: marker:: PhantomData <:: std:: cell:: UnsafeCell < #id >>
280
- } ;
281
- let parser = Field :: parse_named;
282
- Some ( parser. parse2 ( toks) . unwrap ( ) )
283
- }
284
- _ => None ,
285
- } ) ;
286
- // See cxx's opaque::Opaque for rationale for this type... in
287
- // short, it's to avoid being Send/Sync.
288
- s. fields = syn:: Fields :: Named ( parse_quote ! {
289
- {
290
- do_not_attempt_to_allocate_nonpod_types: [ * const u8 ; 0 ] ,
291
- #( #generic_type_fields) , *
292
- }
293
- } ) ;
294
- }
295
-
296
255
/// Record the Api for a type, e.g. enum or struct.
297
256
/// Code generated includes the bindgen entry itself,
298
257
/// various entries for the cxx::bridge to ensure cxx
@@ -333,42 +292,20 @@ impl<'a> ParseBindgen<'a> {
333
292
TokenStream2 :: new ( )
334
293
} ;
335
294
336
- let mut fulltypath = Vec :: new ( ) ;
337
- // We can't use parse_quote! here because it doesn't support type aliases
338
- // at the moment.
339
- let colon = TokenTree :: Punct ( proc_macro2:: Punct :: new ( ':' , proc_macro2:: Spacing :: Joint ) ) ;
340
- for_extern_c_ts. extend (
341
- [
342
- TokenTree :: Ident ( make_ident ( "type" ) ) ,
343
- TokenTree :: Ident ( final_ident. clone ( ) ) ,
344
- TokenTree :: Punct ( proc_macro2:: Punct :: new ( '=' , proc_macro2:: Spacing :: Alone ) ) ,
345
- TokenTree :: Ident ( make_ident ( "super" ) ) ,
346
- colon. clone ( ) ,
347
- colon. clone ( ) ,
348
- TokenTree :: Ident ( make_ident ( "bindgen" ) ) ,
349
- colon. clone ( ) ,
350
- colon. clone ( ) ,
351
- TokenTree :: Ident ( make_ident ( "root" ) ) ,
352
- colon. clone ( ) ,
353
- colon. clone ( ) ,
354
- ]
355
- . to_vec ( ) ,
356
- ) ;
357
- fulltypath. push ( make_ident ( "bindgen" ) ) ;
358
- fulltypath. push ( make_ident ( "root" ) ) ;
295
+ let mut fulltypath: Vec < _ > = [ "bindgen" , "root" ] . iter ( ) . map ( |x| make_ident ( x) ) . collect ( ) ;
296
+ for_extern_c_ts. extend ( quote ! {
297
+ type #final_ident = super :: bindgen:: root::
298
+ } ) ;
359
299
for segment in tyname. ns_segment_iter ( ) {
360
300
let id = make_ident ( segment) ;
361
- for_extern_c_ts
362
- . extend ( [ TokenTree :: Ident ( id. clone ( ) ) , colon. clone ( ) , colon. clone ( ) ] . to_vec ( ) ) ;
301
+ for_extern_c_ts. extend ( quote ! {
302
+ #id::
303
+ } ) ;
363
304
fulltypath. push ( id) ;
364
305
}
365
- for_extern_c_ts. extend (
366
- [
367
- TokenTree :: Ident ( final_ident. clone ( ) ) ,
368
- TokenTree :: Punct ( proc_macro2:: Punct :: new ( ';' , proc_macro2:: Spacing :: Alone ) ) ,
369
- ]
370
- . to_vec ( ) ,
371
- ) ;
306
+ for_extern_c_ts. extend ( quote ! {
307
+ #final_ident;
308
+ } ) ;
372
309
let bridge_item = match type_nature {
373
310
TypeKind :: ForwardDeclaration => None ,
374
311
_ => Some ( Item :: Impl ( parse_quote ! {
@@ -402,11 +339,12 @@ impl<'a> ParseBindgen<'a> {
402
339
403
340
impl < ' a > ForeignModParseCallbacks for ParseBindgen < ' a > {
404
341
fn convert_boxed_type (
405
- & self ,
342
+ & mut self ,
406
343
ty : Box < Type > ,
407
344
ns : & Namespace ,
408
345
) -> Result < ( Box < Type > , HashSet < TypeName > ) , ConvertError > {
409
346
let annotated = self . type_converter . convert_boxed_type ( ty, ns) ?;
347
+ self . results . apis . extend ( annotated. extra_apis ) ;
410
348
Ok ( ( annotated. ty , annotated. types_encountered ) )
411
349
}
412
350
0 commit comments