@@ -126,6 +126,7 @@ use std::num::NonZero;
126
126
use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
127
127
128
128
use rustc_ast:: LitKind ;
129
+ use rustc_attr:: InlineAttr ;
129
130
use rustc_data_structures:: fx:: FxHashMap ;
130
131
use rustc_data_structures:: sync:: { HashMapExt , Lock } ;
131
132
use rustc_data_structures:: tiny_list:: TinyList ;
@@ -555,16 +556,24 @@ impl<'tcx> TyCtxt<'tcx> {
555
556
pub fn reserve_and_set_fn_alloc ( self , instance : Instance < ' tcx > ) -> AllocId {
556
557
// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
557
558
// by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be
558
- // duplicated across crates.
559
- // We thus generate a new `AllocId` for every mention of a function. This means that
560
- // `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true.
561
- // However, formatting code relies on function identity (see #58320), so we only do
562
- // this for generic functions. Lifetime parameters are ignored.
559
+ // duplicated across crates. We thus generate a new `AllocId` for every mention of a
560
+ // function. This means that `main as fn() == main as fn()` is false, while `let x = main as
561
+ // fn(); x == x` is true. However, as a quality-of-life feature it can be useful to identify
562
+ // certain functions uniquely, e.g. for backtraces. So we identify whether codegen will
563
+ // actually emit duplicate functions. It does that when they have non-lifetime generics, or
564
+ // when they can be inlined. All other functions are given a unique address.
565
+ // This is not a stable guarantee! The `inline` attribute is a hint and cannot be relied
566
+ // upon for anything. But if we don't do this, backtraces look terrible and we risk breaking
567
+ // the `USIZE_MARKER` hack in the formatting machinery.
563
568
let is_generic = instance
564
569
. args
565
570
. into_iter ( )
566
571
. any ( |kind| !matches ! ( kind. unpack( ) , GenericArgKind :: Lifetime ( _) ) ) ;
567
- if is_generic {
572
+ let can_be_inlined = match self . codegen_fn_attrs ( instance. def_id ( ) ) . inline {
573
+ InlineAttr :: Never => false ,
574
+ _ => true ,
575
+ } ;
576
+ if is_generic || can_be_inlined {
568
577
// Get a fresh ID.
569
578
let mut alloc_map = self . alloc_map . lock ( ) ;
570
579
let id = alloc_map. reserve ( ) ;
0 commit comments