@@ -27,7 +27,7 @@ pub use self::pointer::{Pointer, PointerArithmetic};
2727use std:: fmt;
2828use crate :: mir;
2929use crate :: hir:: def_id:: DefId ;
30- use crate :: ty:: { self , TyCtxt , Instance } ;
30+ use crate :: ty:: { self , TyCtxt , Instance , subst :: UnpackedKind } ;
3131use crate :: ty:: layout:: { self , Size } ;
3232use std:: io;
3333use crate :: rustc_serialize:: { Encoder , Decodable , Encodable } ;
@@ -318,14 +318,29 @@ impl<'tcx> AllocMap<'tcx> {
318318 id
319319 }
320320
321- /// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
322- /// by the linker and functions can be duplicated across crates.
323- /// We thus generate a new `AllocId` for every mention of a function. This means that
324- /// `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true.
325321 pub fn create_fn_alloc ( & mut self , instance : Instance < ' tcx > ) -> AllocId {
326- let id = self . reserve ( ) ;
327- self . id_to_kind . insert ( id, AllocKind :: Function ( instance) ) ;
328- id
322+ // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
323+ // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be
324+ // duplicated across crates.
325+ // We thus generate a new `AllocId` for every mention of a function. This means that
326+ // `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true.
327+ // However, formatting code relies on function identity (see #58320), so we only do
328+ // this for generic functions. Lifetime parameters are ignored.
329+ let is_generic = instance. substs . into_iter ( ) . any ( |kind| {
330+ match kind. unpack ( ) {
331+ UnpackedKind :: Lifetime ( _) => false ,
332+ _ => true ,
333+ }
334+ } ) ;
335+ if is_generic {
336+ // Get a fresh ID
337+ let id = self . reserve ( ) ;
338+ self . id_to_kind . insert ( id, AllocKind :: Function ( instance) ) ;
339+ id
340+ } else {
341+ // Deduplicate
342+ self . intern ( AllocKind :: Function ( instance) )
343+ }
329344 }
330345
331346 /// Returns `None` in case the `AllocId` is dangling. An `EvalContext` can still have a
0 commit comments