rust-lang/rust

#[linkage] does not propagate through generic functions

alexcrichton opened this issue · 3 comments

For example:

// lib.rs
#![feature(linkage)]

pub fn foo<T>() -> *const () {
    extern {
        #[linkage = "extern_weak"]
        static FOO: *const ();
    }
    FOO
}
// main.rs
extern crate lib;

fn main() {
    lib::foo::<int>();
}
$ rustc lib.rs --crate-type rlib
$ rustc main.rs -L .
error: linking with `cc` failed: exit code: 1
note: cc '-Wl,--as-needed' '-m64' '-L' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib' '-o' 'main' 'main.o' '-Wl,--whole-archive' '-lmorestack' '-Wl,--no-whole-archive' '-fno-lto' '-Wl,--gc-sections' '-pie' '-nodefaultlibs' '/home/alex/liblib.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libsync-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustrt-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunicode-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-4e7c5e5c.rlib' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-4e7c5e5c.rlib' '-L' '.' '-L' '/home/alex/.rust' '-L' '/home/alex' '-Wl,--whole-archive' '-Wl,-Bstatic' '-Wl,--no-whole-archive' '-Wl,-Bdynamic' '-ldl' '-lpthread' '-lgcc_s' '-lpthread' '-lc' '-lm' '-lcompiler-rt'
note: main.o:main.0.rs:function foo::h6978205699166201756: error: undefined reference to 'FOO'
collect2: error: ld returned 1 exit status

error: aborting due to previous error

This can be a little more clearly seen with the IR generated for main:

; ModuleID = 'main.0.rs'
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@FOO = external global {}*

...

Note the lack of extern_weak anywhere on FOO.

Triage: this is still true today, though int needs to be updated to i32, and there's now a warning about () not being a valid foreign type, which is irrelevant to this particular issue.

brson commented

@Mark-Simulacrum claims it repros still.

Updated test code:

// lib.rs
#![feature(linkage)]

pub fn foo<T>() -> *const() {
    extern {
        #[linkage = "extern_weak"]
        static FOO: *const();
    }
    unsafe { FOO }
}
// main.rs
extern crate lib;

fn main() {
    lib::foo::<i32>();
}

Still fails to compile with the same errors mentioned in the top post along with the irrelevant invalid foreign type warning mentioned by @steveklabnik.