Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impls containing static defined in private modules cause linking errors #20201

Closed
nagisa opened this issue Dec 24, 2014 · 5 comments
Closed

impls containing static defined in private modules cause linking errors #20201

nagisa opened this issue Dec 24, 2014 · 5 comments

Comments

@nagisa
Copy link
Member

nagisa commented Dec 24, 2014

Yesterday on IRC @kmcguire3413 asked about interesting link issue which stems from the use of panic! macro. Sadly we couldn’t quite pinpoint the exact issue or produce more minimal test case than a full repository of code.

The repository in question is water.rs. When debugging be sure to use this exact commit linked by previous link since the next commit introduces a workaroud. Steps to reproduce:

$ git checkout e4638ff
$ cargo test
…
error: linking with `cc` failed: exit code: 1
…
safesync.0.rs:(.text._ZN7message11SyncMessage11get_payload21h13055894943565378597E+0x17b): undefined reference to `message::SyncMessage::get_payload::_FILE_LINE::hfe26c9c1d4aeb16dNgb'

Now the funny thing is, that the symbol exists in the rlib, that’s linked to the test (though it’s type should probably be D, rather than d):

$ nm -C target/libwater-6db6f607792c73a1.rlib | grep hfe26c9c1d4aeb16dNgb
0000000000000000 d message::SyncMessage::get_payload::_FILE_LINE::hfe26c9c1d4aeb16dNgb

Commenting the panic or call to the relevant function fixes the issue as well as moving SyncMessage implementation to a different file.

@nagisa
Copy link
Member Author

nagisa commented Dec 24, 2014

Additionally, inlining rawmessage.rs into message.rs will introduce new linker erorrs:

$ cargo test
…
/home/nagisa/files/rust/fails/water.rs/target/safesync-490939a7cdc50d58.o: In function `message::SyncMessage::get_payload::h8503016970478518134':
safesync.0.rs:(.text._ZN7message11SyncMessage11get_payload20h8503016970478518134E+0x17b): undefined reference to `message::SyncMessage::get_payload::_FILE_LINE::h7cd42812b01f00a3Vzb'
/home/nagisa/files/rust/fails/water.rs/target/safesync-490939a7cdc50d58.o: In function `message::RawMessage::readstructunsafe::h9415964264797449173':
safesync.0.rs:(.text._ZN7message10RawMessage16readstructunsafe20h9415964264797449173E+0xa8): undefined reference to `message::RawMessage::readstructunsafe::_FILE_LINE::h7cd42812b01f00a3Ilb'
collect2: error: ld returned 1 exit status

@alexcrichton
Copy link
Member

Closing as a dupe of #16734, but if you can get a minimized example that's different, feel free to reopen!

@nagisa
Copy link
Member Author

nagisa commented Dec 25, 2014

@alexcrichton It seems I have no button to repoen. This minimal case is pretty different, since I could reduce it enough to cause it even without the use of ⊥ type:

lib.rs:

#![crate_name="repr"]
#![crate_type="rlib"]

pub use link::Link;

mod link {
    use error::Error;
    pub struct Link;
    impl Link {
        pub fn error(&self) -> Error { Error }
    }
}

mod error {
    use std::default::Default;
    pub struct Error;
    impl Error {
        pub fn produce<T : Default>(self) -> (T, uint) {
            static LINK_ERROR : uint = 0u;
            (Default::default(), LINK_ERROR)
        }
    }
}

main.rs:

extern crate repr;

use repr::Link;

fn main() {
    let link_error : (uint, uint) = Link.error().produce();
}
$ bash -c 'rustc lib.rs && rustc main.rs -L.'
…
note: main.o: In function `error::Error::produce::h13795623746139935984':
main.0.rs:(.text._ZN5error5Error7produce21h13795623746139935984E+0x3d): undefined reference to `error::Error::produce::LINK_ERROR::h6790b04a8ae1707fTaa'
collect2: error: ld returned 1 exit status

I hypothesise, that this is caused by module visibility issues (note: only the Link type is exported as a public type). If the mod error is made pub, then the error disappears. If the produce method is not polymorphic, linker fails to link to the method itself rather than just its static constant.

This gist contains a “non-prettified” (i.e. before I renamed Messages and Endpoints to Links and Errors) test case which results in same error message that I reported in the first message.

@nagisa nagisa changed the title Odd linking error due to panic! use impls defined in private modules (for types returned by public methods) cause linking errors Dec 25, 2014
@kmcallister kmcallister reopened this Dec 25, 2014
@nagisa nagisa changed the title impls defined in private modules (for types returned by public methods) cause linking errors impls containing static defined in private modules cause linking errors Dec 25, 2014
@alexcrichton
Copy link
Member

That example is actually a dupe of #16734 in that the reachability pass isn't quite doing as much as it should. The type Error is "reachable" so its functions must be public symbols, but our reachability analysis currently does not propagate through the signatures of reachable types right now. For example #16734 is an error because we don't see that Baz is a reachable type.

Once a generic method is used we always monomorphize across crates, which is why the error goes away. Regardless though, I'm going to close this as a dupe again of #16734, but thanks for the minimized example!

@nagisa
Copy link
Member Author

nagisa commented Dec 28, 2014

I see. Thanks for the explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants