@@ -86,6 +86,7 @@ pub fn generate_thunk_decl<'tcx>(
8686 thunk_name : & Ident ,
8787 has_self_param : bool ,
8888) -> Result < CcSnippet > {
89+ let tcx = db. tcx ( ) ;
8990 let mut prereqs = CcPrerequisites :: default ( ) ;
9091 let main_api_ret_type = format_ret_ty_for_cc ( db, sig_mid, sig_hir) ?. into_tokens ( & mut prereqs) ;
9192
@@ -110,7 +111,7 @@ pub fn generate_thunk_decl<'tcx>(
110111 }
111112 BridgedType :: Composable ( _) => Ok ( quote ! { unsigned char * } ) ,
112113 }
113- } else if is_c_abi_compatible_by_value ( ty) {
114+ } else if is_c_abi_compatible_by_value ( tcx , ty) {
114115 Ok ( quote ! { #cpp_type } )
115116 } else if let Some ( tuple_abi) = tuple_c_abi_c_type ( ty) {
116117 Ok ( tuple_abi)
@@ -130,22 +131,32 @@ pub fn generate_thunk_decl<'tcx>(
130131 } ;
131132
132133 // Types which are not C-ABI compatible by-value are returned via out-pointer parameters.
133- let thunk_ret_type: TokenStream ;
134- if is_c_abi_compatible_by_value ( sig_mid. output ( ) ) {
135- thunk_ret_type = main_api_ret_type;
134+ // TODO: b/ 459482188 - The order of this check must align with the order in `cc_return_value_from_c_abi`.
135+ // We should centralize this logic so that the order exists in a singular location used by both
136+ // places.
137+ let thunk_ret_type = if let Some ( briging) = is_bridged_type ( db, sig_mid. output ( ) ) ? {
138+ match briging {
139+ BridgedType :: Legacy { .. } => {
140+ thunk_params. push ( quote ! { #main_api_ret_type* __ret_ptr } ) ;
141+ quote ! { void }
142+ }
143+ BridgedType :: Composable ( _) => {
144+ thunk_params. push ( quote ! { unsigned char * __ret_ptr } ) ;
145+ quote ! { void }
146+ }
147+ }
148+ } else if is_c_abi_compatible_by_value ( tcx, sig_mid. output ( ) ) {
149+ main_api_ret_type
136150 } else if let Some ( tuple_abi) = tuple_c_abi_c_type ( sig_mid. output ( ) ) {
137- thunk_ret_type = quote ! { void } ;
138151 thunk_params. push ( quote ! { #tuple_abi __ret_ptr } ) ;
152+ quote ! { void }
139153 } else if let ty:: TyKind :: Array ( inner_ty, _) = sig_mid. output ( ) . kind ( ) {
140154 let c_type = array_c_abi_c_type ( db. tcx ( ) , * inner_ty) ?;
141- thunk_ret_type = quote ! { void } ;
142155 thunk_params. push ( quote ! { #c_type __ret_ptr } ) ;
143- } else if let Some ( BridgedType :: Composable ( _) ) = is_bridged_type ( db, sig_mid. output ( ) ) ? {
144- thunk_ret_type = quote ! { void } ;
145- thunk_params. push ( quote ! { unsigned char * __ret_ptr } ) ;
156+ quote ! { void }
146157 } else {
147- thunk_ret_type = quote ! { void } ;
148158 thunk_params. push ( quote ! { #main_api_ret_type* __ret_ptr } ) ;
159+ quote ! { void }
149160 } ;
150161
151162 let mut attributes = vec ! [ ] ;
@@ -266,7 +277,8 @@ fn convert_value_from_c_abi_to_rust<'tcx>(
266277 extern_c_decls,
267278 ) ;
268279 }
269- if is_c_abi_compatible_by_value ( ty) {
280+ let tcx = db. tcx ( ) ;
281+ if is_c_abi_compatible_by_value ( tcx, ty) {
270282 return Ok ( quote ! { } ) ;
271283 }
272284 if let ty:: TyKind :: Tuple ( tuple_tys) = ty. kind ( ) {
@@ -281,12 +293,13 @@ fn c_abi_for_param_type<'tcx>(
281293 db : & dyn BindingsGenerator < ' tcx > ,
282294 ty : ty:: Ty < ' tcx > ,
283295) -> Result < TokenStream > {
296+ let tcx = db. tcx ( ) ;
284297 if let Some ( bridged) = is_bridged_type ( db, ty) ? {
285298 match bridged {
286299 BridgedType :: Legacy { .. } => Ok ( quote ! { * const core:: ffi:: c_void } ) ,
287300 BridgedType :: Composable ( _) => Ok ( quote ! { * const core:: ffi:: c_uchar } ) ,
288301 }
289- } else if is_c_abi_compatible_by_value ( ty) {
302+ } else if is_c_abi_compatible_by_value ( tcx , ty) {
290303 let rs_type = db. format_ty_for_rs ( ty) ?;
291304 Ok ( quote ! { #rs_type } )
292305 } else if let Some ( tuple_abi) = tuple_c_abi_rs_type ( ty) {
@@ -375,6 +388,7 @@ fn write_rs_value_to_c_abi_ptr<'tcx>(
375388 let rs_type_tokens = db. format_ty_for_rs ( rs_type) ?;
376389 Ok ( quote ! { ( #c_ptr as * mut #rs_type_tokens) . write( #rs_value) ; } )
377390 } ;
391+ let tcx = db. tcx ( ) ;
378392 Ok ( if let Some ( bridged_type) = is_bridged_type ( db, rs_type) ? {
379393 match bridged_type {
380394 BridgedType :: Legacy { conversion_info, .. } => match conversion_info {
@@ -412,7 +426,7 @@ fn write_rs_value_to_c_abi_ptr<'tcx>(
412426 }
413427 }
414428 }
415- } else if is_c_abi_compatible_by_value ( rs_type) {
429+ } else if is_c_abi_compatible_by_value ( tcx , rs_type) {
416430 write_directly ( ) ?
417431 } else if let ty:: TyKind :: Tuple ( tuple_tys) = rs_type. kind ( ) {
418432 let num_elements = tuple_tys. len ( ) ;
@@ -525,7 +539,7 @@ pub fn generate_thunk_impl<'tcx>(
525539
526540 let thunk_return_type;
527541 let thunk_return_expression;
528- if output_is_bridged. is_none ( ) && is_c_abi_compatible_by_value ( sig. output ( ) ) {
542+ if output_is_bridged. is_none ( ) && is_c_abi_compatible_by_value ( tcx , sig. output ( ) ) {
529543 // The output is not bridged and is C ABI compatible by-value, so we can just return
530544 // the result directly, and no out-param is needed.
531545 thunk_return_type = db. format_ty_for_rs ( sig. output ( ) ) ?;
@@ -576,7 +590,7 @@ pub fn generate_thunk_impl<'tcx>(
576590
577591/// Returns `Ok(())` if no thunk is required.
578592/// Otherwise returns an error the describes why the thunk is needed.
579- pub fn is_thunk_required ( sig : & ty:: FnSig ) -> Result < ( ) > {
593+ pub fn is_thunk_required ( tcx : TyCtxt < ' _ > , sig : & ty:: FnSig ) -> Result < ( ) > {
580594 match sig. abi {
581595 // "C" ABI is okay: since https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html has been
582596 // accepted, a Rust panic that "escapes" a "C" ABI function is a defined crash. See
@@ -594,9 +608,12 @@ pub fn is_thunk_required(sig: &ty::FnSig) -> Result<()> {
594608 _ => bail ! ( "Any calling convention other than `extern \" C\" ` requires a thunk" ) ,
595609 } ;
596610
597- ensure ! ( is_c_abi_compatible_by_value( sig. output( ) ) , "Return type requires a thunk" ) ;
611+ ensure ! ( is_c_abi_compatible_by_value( tcx , sig. output( ) ) , "Return type requires a thunk" ) ;
598612 for ( i, param_ty) in sig. inputs ( ) . iter ( ) . enumerate ( ) {
599- ensure ! ( is_c_abi_compatible_by_value( * param_ty) , "Type of parameter #{i} requires a thunk" ) ;
613+ ensure ! (
614+ is_c_abi_compatible_by_value( tcx, * param_ty) ,
615+ "Type of parameter #{i} requires a thunk"
616+ ) ;
600617 }
601618
602619 Ok ( ( ) )
0 commit comments