diff options
| author | Ralf Jung <post@ralfj.de> | 2019-02-09 15:44:54 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2019-02-09 15:44:54 +0100 |
| commit | 66adf52e7dfd68f04e60744ea9bf130c45befe5e (patch) | |
| tree | ec29c4358d1921a13a4de039178ad5b5c3f1070f /src | |
| parent | 312f3827faa8dc3b8e1dc8c1ad685a6222f16f03 (diff) | |
| download | rust-66adf52e7dfd68f04e60744ea9bf130c45befe5e.tar.gz rust-66adf52e7dfd68f04e60744ea9bf130c45befe5e.zip | |
miri: give non-generic functions a stable address
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/mir/interpret/mod.rs | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index efd233f1f38..bb25d1b4209 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -27,7 +27,7 @@ pub use self::pointer::{Pointer, PointerArithmetic}; use std::fmt; use crate::mir; use crate::hir::def_id::DefId; -use crate::ty::{self, TyCtxt, Instance}; +use crate::ty::{self, TyCtxt, Instance, subst::UnpackedKind}; use crate::ty::layout::{self, Size}; use std::io; use crate::rustc_serialize::{Encoder, Decodable, Encodable}; @@ -318,14 +318,29 @@ impl<'tcx> AllocMap<'tcx> { id } - /// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated - /// by the linker and functions can be duplicated across crates. - /// We thus generate a new `AllocId` for every mention of a function. This means that - /// `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true. pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> AllocId { - let id = self.reserve(); - self.id_to_kind.insert(id, AllocKind::Function(instance)); - id + // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated + // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be + // duplicated across crates. + // We thus generate a new `AllocId` for every mention of a function. This means that + // `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true. + // However, formatting code relies on function identity (see #58320), so we only do + // this for generic functions. Lifetime parameters are ignored. + let is_generic = instance.substs.into_iter().any(|kind| { + match kind.unpack() { + UnpackedKind::Lifetime(_) => false, + _ => true, + } + }); + if is_generic { + // Get a fresh ID + let id = self.reserve(); + self.id_to_kind.insert(id, AllocKind::Function(instance)); + id + } else { + // Deduplicate + self.intern(AllocKind::Function(instance)) + } } /// Returns `None` in case the `AllocId` is dangling. An `EvalContext` can still have a |
