Description
The way that incremental compilation works breaks code that uses private symbols. For example, the following code will fail to compile when using incremental compilation (e.g. the default cargo build
), but will build successfully when incremental compilation is disabled (e.g. the default cargo build --release
):
// I have reproduced this issue for the following targets:
// mips-unknown-linux-gnu
// x86_64-unknown-linux-gnu
// x86_64-apple-darwin
// aarch64-apple-ios
fn foo<T>() {
// See m:<mangling> at https://llvm.org/docs/LangRef.html#data-layout
// This is only reproducible when using ELF, Mips, or Mach-O mangling.
#[cfg_attr(all(target_os = "linux", not(target_arch = "mips")),
export_name = "\x01.L_this_is_a_private_symbol")]
#[cfg_attr(any(target_os = "macos", target_os = "ios"),
export_name = "\x01L_this_is_a_private_symbol")]
#[cfg_attr(target_arch = "mips", export_name = "\x01$_this_is_a_private_symbol")]
static X: usize = 0;
// Use the static symbol in a way that prevents the optimizer from
// optimizing it away.
unsafe { std::ptr::read_volatile(&X as *const _); }
}
fn main() {
foo::<usize>();
}
Output (for both cargo build
and cargo build --release
):
$ cargo build
Compiling zzz v0.1.0 (file:///private/tmp/zzz)
LLVM ERROR: unsupported relocation of undefined symbol 'L_this_is_a_private_symbol'
error: Could not compile `zzz`.
To learn more, run the command again with --verbose.
$ cargo build --release
Compiling zzz v0.1.0 (file:///private/tmp/zzz)
Finished release [optimized] target(s) in 0.26s
I have reproduced this issue for the following targets:
mips-unknown-linux-gnu
x86_64-unknown-linux-gnu
x86_64-apple-darwin
aarch64-apple-ios
I'm interested in fixing this issue, and have been trying to better understand librustc_mir/monomorphize/partitioning.rs
(which I assume is where the problem is). I'll update this issue if I've made any progress, but I would appreciate any guidance anyone might be able to offer.
These private symbols are useful for low-level FFI work (e.g. the linker on macOS/iOS will deduplicate selector names only if they have a private symbol name).