Skip to content

Commit 66adf52

Browse files
committed
miri: give non-generic functions a stable address
1 parent 312f382 commit 66adf52

File tree

1 file changed

+23
-8
lines changed
  • src/librustc/mir/interpret

1 file changed

+23
-8
lines changed

src/librustc/mir/interpret/mod.rs

+23-8
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use self::pointer::{Pointer, PointerArithmetic};
2727
use std::fmt;
2828
use crate::mir;
2929
use crate::hir::def_id::DefId;
30-
use crate::ty::{self, TyCtxt, Instance};
30+
use crate::ty::{self, TyCtxt, Instance, subst::UnpackedKind};
3131
use crate::ty::layout::{self, Size};
3232
use std::io;
3333
use 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

Comments
 (0)