Skip to content

Link-time error when referencing symbols through generic types in naked_asm! block #140373

Closed
@lschuermann

Description

@lschuermann

When trying to reference a method on a generic type parameter from within a naked_asm! block, rust-lld reports a link-time error indicating that a symbol could not be resolved. This used to work on a Rust nightly from 2024-11-16, but no longer does on a recent nightly (2025-04-26), where naked_functions has been stabilized (#134213).

Here's a link to a Rust playground that results in the link-time error:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=9de6dd640b6e55f857e8d65bafb82ab1

A minimal example to trigger this bug:

trait T {
    extern "C" fn t();
}

enum E<const C: usize> {}

impl<const C: usize> T for E<C> {
    extern "C" fn t() {
        println!("Const generic: {}", C);
    }
}

#[unsafe(naked)]
extern "C" fn foo<U: T>() {
    core::arch::naked_asm!(
        "push rax",
        "call {fn}",
        "pop rax",
        "ret",
        fn = sym <U as T>::t,
    );
}

fn main() {
    foo::<E<42>>();
}

I expected to see this happen: correctly reference the proper, monomorphized function symbol <E<42> as T>::t.

Instead, this happened:

error: linking with `cc` failed: exit status: 1
  |
  = note:  "cc" "-m64" "/tmp/rustcQVxPkQ/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/tmp/rustcQVxPkQ/raw-dylibs" "-B<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld" "-fuse-ld=lld" "-Wl,-znostart-stop-gc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/playground/target/debug/build/aws-lc-sys-a7b8dbb98ccb03f8/out" "-L" "/playground/target/debug/build/libsqlite3-sys-f8b7023b84d9d43f/out" "-L" "/playground/target/debug/build/ring-75909fa7c1b7acce/out" "-L" "/playground/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/windows_x86_64_gnu-0.52.6/lib" "-L" "/playground/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/windows_aarch64_msvc-0.53.0/lib" "-L" "/playground/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/windows_i686_gnu-0.53.0/lib" "-L" "/playground/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/windows_i686_msvc-0.53.0/lib" "-L" "/playground/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/windows_x86_64_gnu-0.53.0/lib" "-L" "/playground/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/windows_x86_64_msvc-0.53.0/lib" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/playground/target/debug/deps/playground-72b3069f10cc7f34" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs"
  = note: some arguments are omitted. use `--verbose` to show all linker arguments
  = note: rust-lld: error: undefined hidden symbol: playground::T::t::h9639b9475488f044
          >>> referenced by playground.5e532e3d8d2adfd6-cgu.0
          >>>               /playground/target/debug/deps/playground-72b3069f10cc7f34.playground.5e532e3d8d2adfd6-cgu.0.rcgu.o:(playground::foo::hebf1c66e7ecb3c3d)
          collect2: error: ld returned 1 exit status

What's weird is that the symbol being referenced is not related to the actual type instantiation playground::E::<42>, but only the trait-method playground::T::t. Instead, on nightly-2024-11-16, the generated assembly references the concrete type, as one would expect:

0000000000014e00 <_ZN29naked_asm_generic_symbol_test3foo17h05ccf99589ca4161E>:
;       core::arch::naked_asm!(
   14e00: 50                            pushq   %rax
   14e01: e8 5a ff ff ff                callq   0x14d60 <_ZN94_$LT$naked_asm_generic_symbol_test..E$LT$_$GT$$u20$as$u20$naked_asm_generic_symbol_test..T$GT$1t17h182ea722fc2c8c77E>
   14e06: 58                            popq    %rax
   14e07: c3                            retq
   14e08: 0f 0b                         ud2

Hopefully the above should be sufficient information to reproduce this bug. In the meantime, I can try to bisect which nightly channel update (and perhaps which rustc change) broke this. EDIT: this error first started showing up on rustc 1.85.0-nightly (d4025ee45 2024-12-12), rustc 1.85.0-nightly (21fe748be 2024-12-11) works correctly.

Meta

rustc --version --verbose:

rustc 1.88.0-nightly (b4c8b0c3f 2025-04-25)
binary: rustc
commit-hash: b4c8b0c3f0533bb342a4873ff59bdad3883ab8e3
commit-date: 2025-04-25
host: x86_64-unknown-linux-gnu
release: 1.88.0-nightly
LLVM version: 20.1.2

Metadata

Metadata

Labels

A-monomorphizationArea: MonomorphizationA-nakedArea: `#[naked]`, prologue and epilogue-free, functions, https://git.io/vAzzSC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions