2
2
3
3
use super :: derive:: { CanDeriveCopy , CanDeriveDebug , CanDeriveDefault } ;
4
4
use super :: int:: IntKind ;
5
- use super :: item:: { Item , ItemCanonicalPath , ItemSet } ;
5
+ use super :: item:: { Item , ItemAncestors , ItemCanonicalPath , ItemSet } ;
6
6
use super :: item_kind:: ItemKind ;
7
7
use super :: module:: { Module , ModuleKind } ;
8
8
use super :: named:: { UsedTemplateParameters , analyze} ;
@@ -348,14 +348,8 @@ impl<'ctx> BindgenContext<'ctx> {
348
348
let is_template_instantiation =
349
349
is_type && item. expect_type ( ) . is_template_instantiation ( ) ;
350
350
351
- // Be sure to track all the generated children under namespace, even
352
- // those generated after resolving typerefs, etc.
353
- if item. id ( ) != item. parent_id ( ) {
354
- if let Some ( mut parent) = self . items . get_mut ( & item. parent_id ( ) ) {
355
- if let Some ( mut module) = parent. as_module_mut ( ) {
356
- module. children_mut ( ) . push ( item. id ( ) ) ;
357
- }
358
- }
351
+ if item. id ( ) != self . root_module {
352
+ self . add_item_to_module ( & item) ;
359
353
}
360
354
361
355
if is_type && item. expect_type ( ) . is_comp ( ) {
@@ -407,6 +401,38 @@ impl<'ctx> BindgenContext<'ctx> {
407
401
}
408
402
}
409
403
404
+ /// Ensure that every item (other than the root module) is in a module's
405
+ /// children list. This is to make sure that every whitelisted item get's
406
+ /// codegen'd, even if its parent is not whitelisted. See issue #769 for
407
+ /// details.
408
+ fn add_item_to_module ( & mut self , item : & Item ) {
409
+ assert ! ( item. id( ) != self . root_module) ;
410
+ assert ! ( !self . items. contains_key( & item. id( ) ) ) ;
411
+
412
+ if let Some ( mut parent) = self . items . get_mut ( & item. parent_id ( ) ) {
413
+ if let Some ( mut module) = parent. as_module_mut ( ) {
414
+ debug ! ( "add_item_to_module: adding {:?} as child of parent module {:?}" ,
415
+ item. id( ) ,
416
+ item. parent_id( ) ) ;
417
+
418
+ module. children_mut ( ) . insert ( item. id ( ) ) ;
419
+ return ;
420
+ }
421
+ }
422
+
423
+ debug ! ( "add_item_to_module: adding {:?} as child of current module {:?}" ,
424
+ item. id( ) ,
425
+ self . current_module) ;
426
+
427
+ self . items
428
+ . get_mut ( & self . current_module )
429
+ . expect ( "Should always have an item for self.current_module" )
430
+ . as_module_mut ( )
431
+ . expect ( "self.current_module should always be a module" )
432
+ . children_mut ( )
433
+ . insert ( item. id ( ) ) ;
434
+ }
435
+
410
436
/// Add a new named template type parameter to this context's item set.
411
437
pub fn add_named_type ( & mut self , item : Item , definition : clang:: Cursor ) {
412
438
debug ! ( "BindgenContext::add_named_type: item = {:?}; definition = {:?}" ,
@@ -418,6 +444,8 @@ impl<'ctx> BindgenContext<'ctx> {
418
444
assert_eq ! ( definition. kind( ) ,
419
445
clang_sys:: CXCursor_TemplateTypeParameter ) ;
420
446
447
+ self . add_item_to_module ( & item) ;
448
+
421
449
let id = item. id ( ) ;
422
450
let old_item = self . items . insert ( id, item) ;
423
451
assert ! ( old_item. is_none( ) ,
@@ -620,41 +648,65 @@ impl<'ctx> BindgenContext<'ctx> {
620
648
item. parent_id ( )
621
649
} ;
622
650
651
+ // Relocate the replacement item from where it was declared, to
652
+ // where the thing it is replacing was declared.
653
+ //
654
+ // First, we'll make sure that its parent id is correct.
623
655
624
- // Reparent the item.
625
656
let old_parent = self . resolve_item ( replacement) . parent_id ( ) ;
626
-
627
657
if new_parent == old_parent {
658
+ // Same parent and therefore also same containing
659
+ // module. Nothing to do here.
628
660
continue ;
629
661
}
630
662
631
- if let Some ( mut module ) = self . items
632
- . get_mut ( & old_parent )
663
+ self . items
664
+ . get_mut ( & replacement )
633
665
. unwrap ( )
634
- . as_module_mut ( ) {
635
- // Deparent the replacement.
636
- let position = module. children ( )
637
- . iter ( )
638
- . position ( |id| * id == replacement)
639
- . unwrap ( ) ;
640
- module. children_mut ( ) . remove ( position) ;
641
- }
666
+ . set_parent_for_replacement ( new_parent) ;
642
667
643
- if let Some ( mut module) = self . items
644
- . get_mut ( & new_parent)
645
- . unwrap ( )
646
- . as_module_mut ( ) {
647
- module. children_mut ( ) . push ( replacement) ;
668
+ // Second, make sure that it is in the correct module's children
669
+ // set.
670
+
671
+ let old_module = {
672
+ let immut_self = & * self ;
673
+ old_parent. ancestors ( immut_self)
674
+ . chain ( Some ( immut_self. root_module ) )
675
+ . find ( |id| {
676
+ let item = immut_self. resolve_item ( * id) ;
677
+ item. as_module ( ) . map_or ( false , |m| m. children ( ) . contains ( & replacement) )
678
+ } )
679
+ } ;
680
+ let old_module = old_module. expect ( "Every replacement item should be in a module" ) ;
681
+
682
+ let new_module = {
683
+ let immut_self = & * self ;
684
+ new_parent. ancestors ( immut_self) . find ( |id| {
685
+ immut_self. resolve_item ( * id) . is_module ( )
686
+ } )
687
+ } ;
688
+ let new_module = new_module. unwrap_or ( self . root_module ) ;
689
+
690
+ if new_module == old_module {
691
+ // Already in the correct module.
692
+ continue ;
648
693
}
649
694
650
695
self . items
651
- . get_mut ( & replacement )
696
+ . get_mut ( & old_module )
652
697
. unwrap ( )
653
- . set_parent_for_replacement ( new_parent) ;
698
+ . as_module_mut ( )
699
+ . unwrap ( )
700
+ . children_mut ( )
701
+ . remove ( & replacement) ;
702
+
654
703
self . items
655
- . get_mut ( & id)
704
+ . get_mut ( & new_module)
705
+ . unwrap ( )
706
+ . as_module_mut ( )
656
707
. unwrap ( )
657
- . set_parent_for_replacement ( old_parent) ;
708
+ . children_mut ( )
709
+ . insert ( replacement) ;
658
710
}
659
711
}
660
712
@@ -783,6 +835,21 @@ impl<'ctx> BindgenContext<'ctx> {
783
835
. map_or ( false , |items_used_params| items_used_params. contains ( & template_param) )
784
836
}
785
837
838
+ /// Return `true` if `item` uses any unbound, generic template parameters,
839
+ /// `false` otherwise.
840
+ ///
841
+ /// Has the same restrictions that `uses_template_parameter` has.
842
+ pub fn uses_any_template_parameters ( & self , item : ItemId ) -> bool {
843
+ assert ! ( self . in_codegen_phase( ) ,
844
+ "We only compute template parameter usage as we enter codegen" ) ;
845
+
846
+ self . used_template_parameters
847
+ . as_ref ( )
848
+ . expect ( "should have template parameter usage info in codegen phase" )
849
+ . get ( & item)
850
+ . map_or ( false , |used| !used. is_empty ( ) )
851
+ }
852
+
786
853
// This deserves a comment. Builtin types don't get a valid declaration, so
787
854
// we can't add it to the cursor->type map.
788
855
//
@@ -794,6 +861,7 @@ impl<'ctx> BindgenContext<'ctx> {
794
861
fn add_builtin_item ( & mut self , item : Item ) {
795
862
debug ! ( "add_builtin_item: item = {:?}" , item) ;
796
863
debug_assert ! ( item. kind( ) . is_type( ) ) ;
864
+ self . add_item_to_module ( & item) ;
797
865
let id = item. id ( ) ;
798
866
let old_item = self . items . insert ( id, item) ;
799
867
assert ! ( old_item. is_none( ) , "Inserted type twice?" ) ;
@@ -932,7 +1000,6 @@ impl<'ctx> BindgenContext<'ctx> {
932
1000
fn instantiate_template ( & mut self ,
933
1001
with_id : ItemId ,
934
1002
template : ItemId ,
935
- parent_id : ItemId ,
936
1003
ty : & clang:: Type ,
937
1004
location : clang:: Cursor )
938
1005
-> Option < ItemId > {
@@ -1038,13 +1105,14 @@ impl<'ctx> BindgenContext<'ctx> {
1038
1105
let sub_item = Item :: new ( sub_id,
1039
1106
None ,
1040
1107
None ,
1041
- template_decl_id ,
1108
+ self . current_module ,
1042
1109
ItemKind :: Type ( sub_ty) ) ;
1043
1110
1044
1111
// Bypass all the validations in add_item explicitly.
1045
1112
debug ! ( "instantiate_template: inserting nested \
1046
1113
instantiation item: {:?}",
1047
1114
sub_item) ;
1115
+ self . add_item_to_module ( & sub_item) ;
1048
1116
debug_assert ! ( sub_id == sub_item. id( ) ) ;
1049
1117
self . items . insert ( sub_id, sub_item) ;
1050
1118
args. push ( sub_id) ;
@@ -1086,10 +1154,11 @@ impl<'ctx> BindgenContext<'ctx> {
1086
1154
type_kind,
1087
1155
ty. is_const ( ) ) ;
1088
1156
let item =
1089
- Item :: new ( with_id, None , None , parent_id , ItemKind :: Type ( ty) ) ;
1157
+ Item :: new ( with_id, None , None , self . current_module , ItemKind :: Type ( ty) ) ;
1090
1158
1091
1159
// Bypass all the validations in add_item explicitly.
1092
1160
debug ! ( "instantiate_template: inserting item: {:?}" , item) ;
1161
+ self . add_item_to_module ( & item) ;
1093
1162
debug_assert ! ( with_id == item. id( ) ) ;
1094
1163
self . items . insert ( with_id, item) ;
1095
1164
Some ( with_id)
@@ -1143,11 +1212,6 @@ impl<'ctx> BindgenContext<'ctx> {
1143
1212
location. is_some ( ) {
1144
1213
let location = location. unwrap ( ) ;
1145
1214
1146
- // It is always safe to hang instantiations off of the root
1147
- // module. They use their template definition for naming,
1148
- // and don't need the parent for anything else.
1149
- let parent_id = self . root_module ( ) ;
1150
-
1151
1215
// For specialized type aliases, there's no way to get the
1152
1216
// template parameters as of this writing (for a struct
1153
1217
// specialization we wouldn't be in this branch anyway).
@@ -1166,7 +1230,6 @@ impl<'ctx> BindgenContext<'ctx> {
1166
1230
1167
1231
return self . instantiate_template ( with_id,
1168
1232
id,
1169
- parent_id,
1170
1233
ty,
1171
1234
location)
1172
1235
. or_else ( || Some ( id) ) ;
0 commit comments