@@ -18,7 +18,7 @@ use syn::{
1818 ForeignItemStatic , ForeignItemType , Ident , Item , ItemConst , ItemEnum , ItemExternCrate , ItemFn ,
1919 ItemForeignMod , ItemImpl , ItemMacro , ItemMod , ItemStatic , ItemStruct , ItemTrait ,
2020 ItemTraitAlias , ItemType , ItemUnion , ItemUse , Lit , MacroDelimiter , PathSegment , ReturnType ,
21- Stmt , Type , TypeTuple , Visibility ,
21+ Stmt , Type , TypeTuple , UseTree , Visibility ,
2222} ;
2323use syn:: { BinOp , UnOp } ; // To override `c_ast::{BinOp,UnOp}` from glob import.
2424
@@ -630,7 +630,7 @@ pub fn translate(
630630 }
631631
632632 {
633- let convert_type = |decl_id : CDeclId , decl : & CDecl | {
633+ let export_type = |decl_id : CDeclId , decl : & CDecl | {
634634 let decl_file_id = t. ast_context . file_id ( decl) ;
635635 if t. tcfg . reorganize_definitions {
636636 t. cur_file . set ( decl_file_id) ;
@@ -664,6 +664,14 @@ pub fn translate(
664664 if t. tcfg . reorganize_definitions
665665 && decl_file_id. map_or ( false , |id| id != t. main_file )
666666 {
667+ let name = t
668+ . ast_context
669+ . get_decl ( & decl_id)
670+ . and_then ( |x| x. kind . get_name ( ) ) ;
671+ log:: debug!(
672+ "emitting submodule imports for exported type {}" ,
673+ name. unwrap_or( & "unknown" . to_owned( ) )
674+ ) ;
667675 t. generate_submodule_imports ( decl_id, decl_file_id) ;
668676 }
669677 } ;
@@ -684,7 +692,7 @@ pub fn translate(
684692 _ => false ,
685693 } ;
686694 if needs_export {
687- convert_type ( decl_id, decl) ;
695+ export_type ( decl_id, decl) ;
688696 }
689697 }
690698 }
@@ -771,6 +779,7 @@ pub fn translate(
771779 } ;
772780
773781 if t. tcfg . reorganize_definitions && decl_file_id. map_or ( false , |id| id != t. main_file ) {
782+ log:: debug!( "emitting any imports needed by {:?}" , decl. kind. get_name( ) ) ;
774783 t. generate_submodule_imports ( * top_id, decl_file_id) ;
775784 }
776785 }
@@ -870,14 +879,17 @@ pub fn translate(
870879
871880 all_items. extend ( mod_items) ;
872881
882+ // Before consuming `uses`, remove them from the uses from submodules to avoid duplicates.
883+ let ( _, _, mut new_uses) = new_uses. drain ( ) ;
884+ new_uses. remove ( & uses) ;
885+
873886 // This could have been merged in with items below; however, it's more idiomatic to have
874887 // imports near the top of the file than randomly scattered about. Also, there is probably
875888 // no reason to have comments associated with imports so it doesn't need to go through
876889 // the above comment store process
877890 all_items. extend ( uses. into_items ( ) ) ;
878891
879892 // Print new uses from submodules
880- let ( _, _, new_uses) = new_uses. drain ( ) ;
881893 all_items. extend ( new_uses. into_items ( ) ) ;
882894
883895 if !foreign_items. is_empty ( ) {
@@ -907,6 +919,43 @@ pub fn translate(
907919 }
908920}
909921
922+ /// Represent the set of names made visible by a `use`: either a set of specific names, or a glob.
923+ enum IdentsOrGlob < ' a > {
924+ Idents ( Vec < & ' a Ident > ) ,
925+ Glob ,
926+ }
927+
928+ impl < ' a > IdentsOrGlob < ' a > {
929+ fn join ( self , other : Self ) -> Self {
930+ use IdentsOrGlob :: * ;
931+ match ( self , other) {
932+ ( Glob , _) => Glob ,
933+ ( _, Glob ) => Glob ,
934+ ( Idents ( mut own) , Idents ( other) ) => Idents ( {
935+ own. extend ( other. into_iter ( ) ) ;
936+ own
937+ } ) ,
938+ }
939+ }
940+ }
941+
942+ /// Extract the set of names made visible by a `use`.
943+ fn use_idents < ' a > ( i : & ' a UseTree ) -> IdentsOrGlob < ' a > {
944+ use UseTree :: * ;
945+ match i {
946+ Path ( up) => use_idents ( & up. tree ) ,
947+ Name ( un) => IdentsOrGlob :: Idents ( vec ! [ & un. ident] ) ,
948+ Rename ( ur) => IdentsOrGlob :: Idents ( vec ! [ & ur. rename] ) ,
949+ Glob ( _ugl) => IdentsOrGlob :: Glob ,
950+ Group ( ugr) => ugr
951+ . items
952+ . iter ( )
953+ . map ( |tree| use_idents ( tree) )
954+ . reduce ( IdentsOrGlob :: join)
955+ . unwrap_or ( IdentsOrGlob :: Idents ( vec ! [ ] ) ) ,
956+ }
957+ }
958+
910959fn item_ident ( i : & Item ) -> Option < & Ident > {
911960 use Item :: * ;
912961 Some ( match i {
@@ -986,6 +1035,8 @@ fn foreign_item_ident_vis(fi: &ForeignItem) -> Option<(&Ident, Visibility)> {
9861035 } )
9871036}
9881037
1038+ /// Create a submodule containing the items in `item_store`. Populates `use_item_store` with the set
1039+ /// of `use`s to import the submodule's exports.
9891040fn make_submodule (
9901041 ast_context : & TypedAstContext ,
9911042 item_store : & mut ItemStore ,
@@ -1000,34 +1051,67 @@ fn make_submodule(
10001051 . get_file_include_line_number ( file_id)
10011052 . unwrap_or ( 0 ) ;
10021053 let mod_name = clean_path ( mod_names, file_path) ;
1054+ let use_path = || vec ! [ "self" . into( ) , mod_name. clone( ) ] ;
10031055
10041056 for item in items. iter ( ) {
10051057 let ident_name = match item_ident ( item) {
10061058 Some ( i) => i. to_string ( ) ,
10071059 None => continue ,
10081060 } ;
1009- let use_path = vec ! [ "self" . into( ) , mod_name. clone( ) ] ;
10101061
10111062 let vis = match item_vis ( item) {
10121063 Some ( Visibility :: Public ( _) ) => mk ( ) . pub_ ( ) ,
10131064 Some ( _) => mk ( ) ,
10141065 None => continue ,
10151066 } ;
10161067
1017- use_item_store. add_use_with_attr ( false , use_path, & ident_name, vis) ;
1068+ use_item_store. add_use_with_attr ( false , use_path ( ) , & ident_name, vis) ;
10181069 }
10191070
10201071 for foreign_item in foreign_items. iter ( ) {
10211072 let ident_name = match foreign_item_ident_vis ( foreign_item) {
10221073 Some ( ( ident, _vis) ) => ident. to_string ( ) ,
10231074 None => continue ,
10241075 } ;
1025- let use_path = vec ! [ "self" . into( ) , mod_name. clone( ) ] ;
10261076
1027- use_item_store. add_use ( false , use_path, & ident_name) ;
1077+ use_item_store. add_use ( false , use_path ( ) , & ident_name) ;
10281078 }
10291079
1080+ // Consumers will `use` reexported items at their exported locations.
10301081 for item in uses. into_items ( ) {
1082+ if let Item :: Use ( ItemUse {
1083+ vis : Visibility :: Public ( _) ,
1084+ tree,
1085+ ..
1086+ } ) = & * item
1087+ {
1088+ match use_idents ( tree) {
1089+ IdentsOrGlob :: Idents ( idents) => {
1090+ for ident in idents {
1091+ fn is_simd_type_name ( name : & str ) -> bool {
1092+ const SIMD_TYPE_NAMES : & [ & str ] = & [
1093+ "__m128i" , "__m128" , "__m128d" , "__m64" , "__m256" , "__m256d" ,
1094+ "__m256i" ,
1095+ ] ;
1096+ SIMD_TYPE_NAMES . contains ( & name) || name. starts_with ( "_mm_" )
1097+ }
1098+ let name = & * ident. to_string ( ) ;
1099+ if is_simd_type_name ( name) {
1100+ // Import vector type/operation names from the stdlib, as we also generate
1101+ // other uses for them from that location and can't easily reason about
1102+ // the ultimate target of reexported names when avoiding duplicate imports
1103+ // (which are verboten).
1104+ simd:: add_arch_use ( use_item_store, "x86" , name) ;
1105+ simd:: add_arch_use ( use_item_store, "x86_64" , name) ;
1106+ } else {
1107+ // Add a `use` for `self::this_module::exported_name`.
1108+ use_item_store. add_use ( false , use_path ( ) , name) ;
1109+ }
1110+ }
1111+ }
1112+ IdentsOrGlob :: Glob => { }
1113+ }
1114+ }
10311115 items. push ( item) ;
10321116 }
10331117
0 commit comments