@@ -23,7 +23,8 @@ use itertools::Itertools;
23
23
use proc_macro2:: { Ident , Literal , TokenStream } ;
24
24
use quote:: { format_ident, quote, ToTokens } ;
25
25
use rustc_attr:: find_deprecation;
26
- use rustc_hir:: { AssocItemKind , Item , ItemKind , Node , Safety } ;
26
+ use rustc_hir:: def:: { DefKind , Res } ;
27
+ use rustc_hir:: { AssocItemKind , Item , ItemKind , Node , Safety , UseKind , UsePath } ;
27
28
use rustc_infer:: infer:: TyCtxtInferExt ;
28
29
use rustc_middle:: dep_graph:: DepContext ;
29
30
use rustc_middle:: mir:: Mutability ;
@@ -1078,26 +1079,115 @@ fn format_deprecated_tag(tcx: TyCtxt, def_id: DefId) -> Option<TokenStream> {
1078
1079
None
1079
1080
}
1080
1081
1082
+ fn format_use (
1083
+ db : & dyn BindingsGenerator < ' _ > ,
1084
+ using_name : & str ,
1085
+ use_path : & UsePath ,
1086
+ use_kind : & UseKind ,
1087
+ ) -> Result < ApiSnippets > {
1088
+ let tcx = db. tcx ( ) ;
1089
+
1090
+ // TODO(b/350772554): Support multiple items with the same name in `use`
1091
+ // statements.`
1092
+ if use_path. res . len ( ) != 1 {
1093
+ bail ! (
1094
+ "use statements which resolve to multiple items with the same name are not supported yet"
1095
+ ) ;
1096
+ }
1097
+
1098
+ match use_kind {
1099
+ UseKind :: Single => { }
1100
+ // TODO(b/350772554): Implement `pub use foo::{x,y}` and `pub use foo::*`
1101
+ UseKind :: Glob | UseKind :: ListStem => {
1102
+ bail ! ( "Unsupported use kind: {use_kind:?}" ) ;
1103
+ }
1104
+ } ;
1105
+ let ( def_kind, def_id) = match use_path. res [ 0 ] {
1106
+ // TODO(b/350772554): Support PrimTy.
1107
+ Res :: Def ( def_kind, def_id) => ( def_kind, def_id) ,
1108
+ _ => {
1109
+ bail ! (
1110
+ "Unsupported use statement that refers to this type of the entity: {:#?}" ,
1111
+ use_path. res[ 0 ]
1112
+ ) ;
1113
+ }
1114
+ } ;
1115
+ ensure ! (
1116
+ is_directly_public( tcx, def_id) ,
1117
+ "Not directly public type (re-exports are not supported yet - b/262052635)"
1118
+ ) ;
1119
+
1120
+ match def_kind {
1121
+ DefKind :: Fn => {
1122
+ let mut prereqs;
1123
+ // TODO(b/350772554): Support exporting private functions.
1124
+ if let Some ( local_id) = def_id. as_local ( ) {
1125
+ if let Ok ( snippet) = db. format_fn ( local_id) {
1126
+ prereqs = snippet. main_api . prereqs ;
1127
+ } else {
1128
+ bail ! ( "Ignoring the use because the bindings for the target is not generated" ) ;
1129
+ }
1130
+ } else {
1131
+ bail ! ( "Unsupported checking for external function" ) ;
1132
+ }
1133
+ let fully_qualified_fn_name = FullyQualifiedName :: new ( tcx, def_id) ;
1134
+ let unqualified_rust_fn_name =
1135
+ fully_qualified_fn_name. name . expect ( "Functions are assumed to always have a name" ) ;
1136
+ let formatted_fully_qualified_fn_name = fully_qualified_fn_name. format_for_cc ( ) ?;
1137
+ let cpp_name = crubit_attr:: get ( tcx, def_id) . unwrap ( ) . cpp_name ;
1138
+ let main_api_fn_name =
1139
+ format_cc_ident ( cpp_name. unwrap_or ( unqualified_rust_fn_name) . as_str ( ) )
1140
+ . context ( "Error formatting function name" ) ?;
1141
+ let using_name = format_cc_ident ( using_name) . context ( "Error formatting using name" ) ?;
1142
+
1143
+ prereqs. defs . insert ( def_id. expect_local ( ) ) ;
1144
+ let tokens = if format ! ( "{}" , using_name) == format ! ( "{}" , main_api_fn_name) {
1145
+ quote ! { using #formatted_fully_qualified_fn_name; }
1146
+ } else {
1147
+ // TODO(b/350772554): Support function alias.
1148
+ bail ! ( "Unsupported function alias" ) ;
1149
+ } ;
1150
+ Ok ( ApiSnippets {
1151
+ main_api : CcSnippet { prereqs, tokens } ,
1152
+ cc_details : CcSnippet :: default ( ) ,
1153
+ rs_details : quote ! { } ,
1154
+ } )
1155
+ }
1156
+ DefKind :: Struct | DefKind :: Enum => {
1157
+ let use_type = tcx. type_of ( def_id) . instantiate_identity ( ) ;
1158
+ create_type_alias ( db, using_name, use_type)
1159
+ }
1160
+ _ => bail ! (
1161
+ "Unsupported use statement that refers to this type of the entity: {:#?}" ,
1162
+ use_path. res
1163
+ ) ,
1164
+ }
1165
+ }
1166
+
1081
1167
fn format_type_alias (
1082
1168
db : & dyn BindingsGenerator < ' _ > ,
1083
1169
local_def_id : LocalDefId ,
1084
1170
) -> Result < ApiSnippets > {
1085
1171
let tcx = db. tcx ( ) ;
1086
1172
let def_id: DefId = local_def_id. to_def_id ( ) ;
1087
1173
let alias_type = tcx. type_of ( def_id) . instantiate_identity ( ) ;
1088
- let alias_name = format_cc_ident ( tcx. item_name ( def_id) . as_str ( ) )
1089
- . context ( "Error formatting type alias name" ) ?;
1174
+ create_type_alias ( db, tcx. item_name ( def_id) . as_str ( ) , alias_type)
1175
+ }
1176
+
1177
+ fn create_type_alias < ' tcx > (
1178
+ db : & dyn BindingsGenerator < ' tcx > ,
1179
+ alias_name : & str ,
1180
+ alias_type : Ty < ' tcx > ,
1181
+ ) -> Result < ApiSnippets > {
1090
1182
let cc_bindings = format_ty_for_cc ( db, alias_type, TypeLocation :: Other ) ?;
1091
1183
let mut main_api_prereqs = CcPrerequisites :: default ( ) ;
1092
1184
let actual_type_name = cc_bindings. into_tokens ( & mut main_api_prereqs) ;
1093
1185
1186
+ let alias_name = format_cc_ident ( alias_name) . context ( "Error formatting type alias name" ) ?;
1187
+ let tokens = quote ! { using #alias_name = #actual_type_name; } ;
1188
+
1094
1189
Ok ( ApiSnippets {
1095
- main_api : CcSnippet {
1096
- prereqs : main_api_prereqs,
1097
- tokens : quote ! {
1098
- using #alias_name = #actual_type_name;
1099
- } ,
1100
- } ,
1190
+ main_api : CcSnippet { prereqs : main_api_prereqs, tokens } ,
1101
1191
cc_details : CcSnippet :: default ( ) ,
1102
1192
rs_details : quote ! { } ,
1103
1193
} )
@@ -2526,6 +2616,9 @@ fn format_item(db: &dyn BindingsGenerator<'_>, def_id: LocalDefId) -> Result<Opt
2526
2616
db. format_adt_core ( def_id. to_def_id ( ) )
2527
2617
. map ( |core| Some ( format_adt ( db, core) ) ) ,
2528
2618
Item { kind : ItemKind :: TyAlias ( ..) , ..} => format_type_alias ( db, def_id) . map ( Some ) ,
2619
+ Item { ident, kind : ItemKind :: Use ( use_path, use_kind) , ..} => {
2620
+ format_use ( db, ident. as_str ( ) , use_path, use_kind) . map ( Some )
2621
+ } ,
2529
2622
Item { kind : ItemKind :: Impl ( _) , .. } | // Handled by `format_adt`
2530
2623
Item { kind : ItemKind :: Mod ( _) , .. } => // Handled by `format_crate`
2531
2624
Ok ( None ) ,
@@ -3420,12 +3513,12 @@ pub mod tests {
3420
3513
test_generated_bindings ( test_src, |bindings| {
3421
3514
let bindings = bindings. unwrap ( ) ;
3422
3515
3423
- let failures = vec ! [ ( 1 , 15 ) , ( 3 , 21 ) , ( 4 , 24 ) ] ;
3516
+ let failures = vec ! [ ( 1 , 15 ) , ( 3 , 21 ) ] ;
3424
3517
for ( use_number, line_number) in failures. into_iter ( ) {
3425
3518
let expected_comment_txt = format ! (
3426
3519
"Error generating bindings for `{{use#{use_number}}}` defined at \
3427
3520
<crubit_unittests.rs>;l={line_number}: \
3428
- Unsupported rustc_hir::hir::ItemKind: `use` import "
3521
+ Not directly public type (re-exports are not supported yet - b/262052635) "
3429
3522
) ;
3430
3523
assert_cc_matches ! (
3431
3524
bindings. h_body,
@@ -6850,6 +6943,30 @@ pub mod tests {
6850
6943
} ) ;
6851
6944
}
6852
6945
6946
+ #[ test]
6947
+ fn test_format_item_use_normal_type ( ) {
6948
+ let test_src = r#"
6949
+ pub mod test_mod {
6950
+ pub struct S{
6951
+ pub field: i32
6952
+ }
6953
+ }
6954
+
6955
+ pub use test_mod::S as G;
6956
+ "# ;
6957
+ test_format_item ( test_src, "G" , |result| {
6958
+ let result = result. unwrap ( ) . unwrap ( ) ;
6959
+ let main_api = & result. main_api ;
6960
+ assert ! ( !main_api. prereqs. is_empty( ) ) ;
6961
+ assert_cc_matches ! (
6962
+ main_api. tokens,
6963
+ quote! {
6964
+ using G = :: rust_out:: test_mod:: S ;
6965
+ }
6966
+ ) ;
6967
+ } ) ;
6968
+ }
6969
+
6853
6970
#[ test]
6854
6971
fn test_format_item_type_alias ( ) {
6855
6972
let test_src = r#"
0 commit comments