dtolnay / linkme

Safe cross-platform linker shenanigans
Apache License 2.0
628 stars 42 forks source link

Data silently disappeared with certain configuration on Linux #31

Closed crlf0710 closed 2 years ago

crlf0710 commented 4 years ago

I created a minimal repro project at https://github.com/crlf0710/linkme_bug_repro/

To reproduce: run cargo run, the program will panic (the distributed slice is empty), while it should be not (there is one data entry in module sub within the inner crate.)

Interestingly, if you comment the module sub part out (lifting the definition to toplevel), the program will work fine.

dtolnay commented 4 years ago

Looks like this compiler bug: https://github.com/rust-lang/rust/issues/47384. If nothing else from the enclosing module is used by the program, the whole module is incorrectly dropped.

phorward commented 2 years ago

Looks like this compiler bug: rust-lang/rust#47384.

Thanks for filing this issue @crlf0710 and the link @dtolnay. I think this problem is the same with inventory/issues#32. I wanted to switch over to linkme from inventory, but the same problem appears here.

I created a minimal repro project at https://github.com/crlf0710/linkme_bug_repro/

I can confirm that your repository runs fine with RUSTFLAGS="-C codegen-units=1" cargo run.

phorward commented 2 years ago

I now added this to my Cargo.toml, as workaround to continue development, in hope the bug will be fixed sometime.

[profile.dev]
codegen-units = 1

[profile.release]
codegen-units = 1
ilyvion commented 2 years ago

I now added this to my Cargo.toml, as workaround to continue development, in hope the bug will be fixed sometime.

Even this didn't work for me. I had to explicitly use something from the relevant crate to get Rust to populate the distributed slice. That is to say, this code leads to a panic:

// Binary crate
assert_eq!(STORAGE_SYSTEM.len(), 1);

// Downstream "plugin" crate
#[distributed_slice(STORAGE_SYSTEM)]
fn make_storage_provider() -> Box<dyn StorageProvider> {
    Box::new(FileStorageProvider)
}

and this code does not lead to a panic:

// Binary crate
let _nine = file::foo();
assert_eq!(STORAGE_SYSTEM.len(), 1);

// Downstream "plugin" crate
pub fn foo() -> usize {
    9
}

#[distributed_slice(STORAGE_SYSTEM)]
fn make_storage_provider() -> Box<dyn StorageProvider> {
    Box::new(FileStorageProvider)
}

If it matters, my distributed slice STORAGE_SYSTEM lives in a third crate that both the binary crate and the downstream crate depends on.

dtolnay commented 2 years ago

This is fixed in rustc 1.62.0 / linkme 0.3.0.

svenknobloch commented 2 years ago

The repro project still fails the assertion for me using rustc 1.62.1 and linkme 0.3.0 (macOS)

pan93412 commented 2 years ago

The repro project still fails the assertion for me using rustc 1.62.1 and linkme 0.3.0 (macOS)

@dtolnay I can also reproduce it in Inventory 0.3.1 on rustc 1.65-nightly, macOS – see https://github.com/getditto/safer_ffi/issues/131 (no minimum reproducible repo at this moment 😞). Is there any approach that can workaround that?

AdamSimpson commented 1 year ago

Ran into this with linkme 0.3.9 and rustc 1.70.0-nightly on macOS. My top-level Cargo.toml looked like

[workspace]

members = ["lib", "cli"]

Where I register objects in lib and use them in cli. Adding codegen-units = 1 in my top level Cargo.toml works around the issue for me.

dtolnay commented 1 year ago

The macOS-specific issue is tracked in #61.

TheNeikos commented 1 year ago

I am not sure if I should open a new issue for this, but I thought that this would work since 1.62:

Unless I do extern crate dep it is not included in my static array. Is this expected? (I didn't find anything in the readme or the issues) And I am not sure how to interpret the fixes in the rust compiler.

My rust version is: rustc 1.69.0 (84c898d65 2023-04-16) and I am on Linux as well