@@ -309,15 +309,11 @@ fn fn_abi_of_fn_ptr<'tcx>(
309
309
query : ty:: PseudoCanonicalInput < ' tcx , ( ty:: PolyFnSig < ' tcx > , & ' tcx ty:: List < Ty < ' tcx > > ) > ,
310
310
) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
311
311
let ty:: PseudoCanonicalInput { typing_env, value : ( sig, extra_args) } = query;
312
-
313
- let cx = LayoutCx :: new ( tcx, typing_env) ;
314
312
fn_abi_new_uncached (
315
- & cx ,
313
+ & LayoutCx :: new ( tcx , typing_env ) ,
316
314
tcx. instantiate_bound_regions_with_erased ( sig) ,
317
315
extra_args,
318
316
None ,
319
- None ,
320
- false ,
321
317
)
322
318
}
323
319
@@ -326,19 +322,11 @@ fn fn_abi_of_instance<'tcx>(
326
322
query : ty:: PseudoCanonicalInput < ' tcx , ( ty:: Instance < ' tcx > , & ' tcx ty:: List < Ty < ' tcx > > ) > ,
327
323
) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
328
324
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
-
335
325
fn_abi_new_uncached (
336
326
& LayoutCx :: new ( tcx, typing_env) ,
337
- sig ,
327
+ fn_sig_for_fn_abi ( tcx , instance , typing_env ) ,
338
328
extra_args,
339
- caller_location,
340
- Some ( instance. def_id ( ) ) ,
341
- matches ! ( instance. def, ty:: InstanceKind :: Virtual ( ..) ) ,
329
+ Some ( instance) ,
342
330
)
343
331
}
344
332
@@ -547,19 +535,25 @@ fn fn_abi_sanity_check<'tcx>(
547
535
fn_arg_sanity_check ( cx, fn_abi, spec_abi, & fn_abi. ret ) ;
548
536
}
549
537
550
- // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
551
- // arguments of this method, into a separate `struct`.
552
- #[ tracing:: instrument( level = "debug" , skip( cx, caller_location, fn_def_id, force_thin_self_ptr) ) ]
538
+ #[ tracing:: instrument( level = "debug" , skip( cx, instance) ) ]
553
539
fn fn_abi_new_uncached < ' tcx > (
554
540
cx : & LayoutCx < ' tcx > ,
555
541
sig : ty:: FnSig < ' tcx > ,
556
542
extra_args : & [ Ty < ' tcx > ] ,
557
- caller_location : Option < Ty < ' tcx > > ,
558
- fn_def_id : Option < DefId > ,
559
- // FIXME(eddyb) replace this with something typed, like an `enum`.
560
- force_thin_self_ptr : bool ,
543
+ instance : Option < ty:: Instance < ' tcx > > ,
561
544
) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
562
545
let tcx = cx. tcx ( ) ;
546
+ let ( caller_location, determined_fn_def_id, is_virtual_call) = if let Some ( instance) = instance
547
+ {
548
+ let is_virtual_call = matches ! ( instance. def, ty:: InstanceKind :: Virtual ( ..) ) ;
549
+ (
550
+ instance. def . requires_caller_location ( tcx) . then ( || tcx. caller_location_ty ( ) ) ,
551
+ if is_virtual_call { None } else { Some ( instance. def_id ( ) ) } ,
552
+ is_virtual_call,
553
+ )
554
+ } else {
555
+ ( None , None , false )
556
+ } ;
563
557
let sig = tcx. normalize_erasing_regions ( cx. typing_env , sig) ;
564
558
565
559
let conv = conv_from_spec_abi ( cx. tcx ( ) , sig. abi , sig. c_variadic ) ;
@@ -568,16 +562,11 @@ fn fn_abi_new_uncached<'tcx>(
568
562
let extra_args = if sig. abi == ExternAbi :: RustCall {
569
563
assert ! ( !sig. c_variadic && extra_args. is_empty( ) ) ;
570
564
571
- if let Some ( input) = sig. inputs ( ) . last ( ) {
572
- if let ty:: Tuple ( tupled_arguments) = input. kind ( ) {
573
- inputs = & sig. inputs ( ) [ 0 ..sig. inputs ( ) . len ( ) - 1 ] ;
574
- tupled_arguments
575
- } else {
576
- bug ! (
577
- "argument to function with \" rust-call\" ABI \
578
- is not a tuple"
579
- ) ;
580
- }
565
+ if let Some ( input) = sig. inputs ( ) . last ( )
566
+ && let ty:: Tuple ( tupled_arguments) = input. kind ( )
567
+ {
568
+ inputs = & sig. inputs ( ) [ 0 ..sig. inputs ( ) . len ( ) - 1 ] ;
569
+ tupled_arguments
581
570
} else {
582
571
bug ! (
583
572
"argument to function with \" rust-call\" ABI \
@@ -590,7 +579,7 @@ fn fn_abi_new_uncached<'tcx>(
590
579
} ;
591
580
592
581
let is_drop_in_place =
593
- fn_def_id . is_some_and ( |def_id| tcx. is_lang_item ( def_id, LangItem :: DropInPlace ) ) ;
582
+ determined_fn_def_id . is_some_and ( |def_id| tcx. is_lang_item ( def_id, LangItem :: DropInPlace ) ) ;
594
583
595
584
let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | -> Result < _ , & ' tcx FnAbiError < ' tcx > > {
596
585
let span = tracing:: debug_span!( "arg_of" ) ;
@@ -603,7 +592,7 @@ fn fn_abi_new_uncached<'tcx>(
603
592
} ) ;
604
593
605
594
let layout = cx. layout_of ( ty) . map_err ( |err| & * tcx. arena . alloc ( FnAbiError :: Layout ( * err) ) ) ?;
606
- let layout = if force_thin_self_ptr && arg_idx == Some ( 0 ) {
595
+ let layout = if is_virtual_call && arg_idx == Some ( 0 ) {
607
596
// Don't pass the vtable, it's not an argument of the virtual fn.
608
597
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
609
598
// or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
@@ -646,9 +635,22 @@ fn fn_abi_new_uncached<'tcx>(
646
635
c_variadic : sig. c_variadic ,
647
636
fixed_count : inputs. len ( ) as u32 ,
648
637
conv,
649
- can_unwind : fn_can_unwind ( cx. tcx ( ) , fn_def_id, sig. abi ) ,
638
+ can_unwind : fn_can_unwind (
639
+ tcx,
640
+ // Since `#[rustc_nounwind]` can change unwinding, we cannot infer unwinding by `fn_def_id` for a virtual call.
641
+ determined_fn_def_id,
642
+ sig. abi ,
643
+ ) ,
650
644
} ;
651
- fn_abi_adjust_for_abi ( cx, & mut fn_abi, sig. abi , fn_def_id) ;
645
+ fn_abi_adjust_for_abi (
646
+ cx,
647
+ & mut fn_abi,
648
+ sig. abi ,
649
+ // If this is a virtual call, we cannot pass the `fn_def_id`, as it might call other
650
+ // functions from vtable. Internally, `deduced_param_attrs` attempts to infer attributes by
651
+ // visit the function body.
652
+ determined_fn_def_id,
653
+ ) ;
652
654
debug ! ( "fn_abi_new_uncached = {:?}" , fn_abi) ;
653
655
fn_abi_sanity_check ( cx, & fn_abi, sig. abi ) ;
654
656
Ok ( tcx. arena . alloc ( fn_abi) )
0 commit comments