@@ -309,15 +309,11 @@ fn fn_abi_of_fn_ptr<'tcx>(
309309 query : ty:: PseudoCanonicalInput < ' tcx , ( ty:: PolyFnSig < ' tcx > , & ' tcx ty:: List < Ty < ' tcx > > ) > ,
310310) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
311311 let ty:: PseudoCanonicalInput { typing_env, value : ( sig, extra_args) } = query;
312-
313- let cx = LayoutCx :: new ( tcx, typing_env) ;
314312 fn_abi_new_uncached (
315- & cx ,
313+ & LayoutCx :: new ( tcx , typing_env ) ,
316314 tcx. instantiate_bound_regions_with_erased ( sig) ,
317315 extra_args,
318316 None ,
319- None ,
320- false ,
321317 )
322318}
323319
@@ -326,19 +322,11 @@ fn fn_abi_of_instance<'tcx>(
326322 query : ty:: PseudoCanonicalInput < ' tcx , ( ty:: Instance < ' tcx > , & ' tcx ty:: List < Ty < ' tcx > > ) > ,
327323) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
328324 let ty:: PseudoCanonicalInput { typing_env, value : ( instance, extra_args) } = query;
329-
330- let sig = fn_sig_for_fn_abi ( tcx, instance, typing_env) ;
331-
332- let caller_location =
333- instance. def . requires_caller_location ( tcx) . then ( || tcx. caller_location_ty ( ) ) ;
334-
335325 fn_abi_new_uncached (
336326 & LayoutCx :: new ( tcx, typing_env) ,
337- sig ,
327+ fn_sig_for_fn_abi ( tcx , instance , typing_env ) ,
338328 extra_args,
339- caller_location,
340- Some ( instance. def_id ( ) ) ,
341- matches ! ( instance. def, ty:: InstanceKind :: Virtual ( ..) ) ,
329+ Some ( instance) ,
342330 )
343331}
344332
@@ -549,19 +537,25 @@ fn fn_abi_sanity_check<'tcx>(
549537 fn_arg_sanity_check ( cx, fn_abi, spec_abi, & fn_abi. ret ) ;
550538}
551539
552- // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
553- // arguments of this method, into a separate `struct`.
554- #[ tracing:: instrument( level = "debug" , skip( cx, caller_location, fn_def_id, force_thin_self_ptr) ) ]
540+ #[ tracing:: instrument( level = "debug" , skip( cx, instance) ) ]
555541fn fn_abi_new_uncached < ' tcx > (
556542 cx : & LayoutCx < ' tcx > ,
557543 sig : ty:: FnSig < ' tcx > ,
558544 extra_args : & [ Ty < ' tcx > ] ,
559- caller_location : Option < Ty < ' tcx > > ,
560- fn_def_id : Option < DefId > ,
561- // FIXME(eddyb) replace this with something typed, like an `enum`.
562- force_thin_self_ptr : bool ,
545+ instance : Option < ty:: Instance < ' tcx > > ,
563546) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
564547 let tcx = cx. tcx ( ) ;
548+ let ( caller_location, determined_fn_def_id, is_virtual_call) = if let Some ( instance) = instance
549+ {
550+ let is_virtual_call = matches ! ( instance. def, ty:: InstanceKind :: Virtual ( ..) ) ;
551+ (
552+ instance. def . requires_caller_location ( tcx) . then ( || tcx. caller_location_ty ( ) ) ,
553+ if is_virtual_call { None } else { Some ( instance. def_id ( ) ) } ,
554+ is_virtual_call,
555+ )
556+ } else {
557+ ( None , None , false )
558+ } ;
565559 let sig = tcx. normalize_erasing_regions ( cx. typing_env , sig) ;
566560
567561 let conv = conv_from_spec_abi ( cx. tcx ( ) , sig. abi , sig. c_variadic ) ;
@@ -570,16 +564,11 @@ fn fn_abi_new_uncached<'tcx>(
570564 let extra_args = if sig. abi == ExternAbi :: RustCall {
571565 assert ! ( !sig. c_variadic && extra_args. is_empty( ) ) ;
572566
573- if let Some ( input) = sig. inputs ( ) . last ( ) {
574- if let ty:: Tuple ( tupled_arguments) = input. kind ( ) {
575- inputs = & sig. inputs ( ) [ 0 ..sig. inputs ( ) . len ( ) - 1 ] ;
576- tupled_arguments
577- } else {
578- bug ! (
579- "argument to function with \" rust-call\" ABI \
580- is not a tuple"
581- ) ;
582- }
567+ if let Some ( input) = sig. inputs ( ) . last ( )
568+ && let ty:: Tuple ( tupled_arguments) = input. kind ( )
569+ {
570+ inputs = & sig. inputs ( ) [ 0 ..sig. inputs ( ) . len ( ) - 1 ] ;
571+ tupled_arguments
583572 } else {
584573 bug ! (
585574 "argument to function with \" rust-call\" ABI \
@@ -592,7 +581,7 @@ fn fn_abi_new_uncached<'tcx>(
592581 } ;
593582
594583 let is_drop_in_place =
595- fn_def_id . is_some_and ( |def_id| tcx. is_lang_item ( def_id, LangItem :: DropInPlace ) ) ;
584+ determined_fn_def_id . is_some_and ( |def_id| tcx. is_lang_item ( def_id, LangItem :: DropInPlace ) ) ;
596585
597586 let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | -> Result < _ , & ' tcx FnAbiError < ' tcx > > {
598587 let span = tracing:: debug_span!( "arg_of" ) ;
@@ -605,7 +594,7 @@ fn fn_abi_new_uncached<'tcx>(
605594 } ) ;
606595
607596 let layout = cx. layout_of ( ty) . map_err ( |err| & * tcx. arena . alloc ( FnAbiError :: Layout ( * err) ) ) ?;
608- let layout = if force_thin_self_ptr && arg_idx == Some ( 0 ) {
597+ let layout = if is_virtual_call && arg_idx == Some ( 0 ) {
609598 // Don't pass the vtable, it's not an argument of the virtual fn.
610599 // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
611600 // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
@@ -648,9 +637,22 @@ fn fn_abi_new_uncached<'tcx>(
648637 c_variadic : sig. c_variadic ,
649638 fixed_count : inputs. len ( ) as u32 ,
650639 conv,
651- can_unwind : fn_can_unwind ( cx. tcx ( ) , fn_def_id, sig. abi ) ,
640+ can_unwind : fn_can_unwind (
641+ tcx,
642+ // Since `#[rustc_nounwind]` can change unwinding, we cannot infer unwinding by `fn_def_id` for a virtual call.
643+ determined_fn_def_id,
644+ sig. abi ,
645+ ) ,
652646 } ;
653- fn_abi_adjust_for_abi ( cx, & mut fn_abi, sig. abi , fn_def_id) ;
647+ fn_abi_adjust_for_abi (
648+ cx,
649+ & mut fn_abi,
650+ sig. abi ,
651+ // If this is a virtual call, we cannot pass the `fn_def_id`, as it might call other
652+ // functions from vtable. Internally, `deduced_param_attrs` attempts to infer attributes by
653+ // visit the function body.
654+ determined_fn_def_id,
655+ ) ;
654656 debug ! ( "fn_abi_new_uncached = {:?}" , fn_abi) ;
655657 fn_abi_sanity_check ( cx, & fn_abi, sig. abi ) ;
656658 Ok ( tcx. arena . alloc ( fn_abi) )
0 commit comments