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

"Unused" "private" methods are stripped, then linking fails while looking for them #23686

Closed
shepmaster opened this issue Mar 25, 2015 · 3 comments

Comments

@shepmaster
Copy link
Member

Sorry for the scare quotes in the title, it's just that the definitions of "unused" and "private" are a bit fuzzy with this example.

Reproduction

Create a new Cargo project with these two files. It's important that the files be in different crates:

src/lib.rs

mod order {
    pub struct Alpha(pub u8);

    impl Alpha {
        pub fn value(&self) -> u8 { self.0 }
    }
}

pub mod interface {
    use super::order::Alpha;
    pub fn yeah() -> Alpha {
        Alpha(8)
    }
}

src/main.rs

extern crate repro;

fn main() {
    println!("{:?}", repro::interface::yeah().value());
}

When compiling, we get this error:

   Compiling repro v0.0.1 (file:///private/tmp/repro)
src/lib.rs:5:9: 5:45 warning: method is never used: `value`, #[warn(dead_code)] on by default
src/lib.rs:5         pub fn value(&self) -> u8 { self.0 }
                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: linking with `cc` failed: exit code: 1
note: "cc" "-m64" "-L" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib" "-o" "/private/tmp/repro/target/debug/repro" "/private/tmp/repro/target/debug/repro.o" "-Wl,-force_load,/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/libmorestack.a" "-Wl,-dead_strip" "-nodefaultlibs" "/private/tmp/repro/target/debug/librepro-f09a031052375ca3.rlib" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/libstd-4e7c5e5c.rlib" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/libcollections-4e7c5e5c.rlib" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/libunicode-4e7c5e5c.rlib" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/librand-4e7c5e5c.rlib" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/liballoc-4e7c5e5c.rlib" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/liblibc-4e7c5e5c.rlib" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib/libcore-4e7c5e5c.rlib" "-L" "/private/tmp/repro/target/debug" "-L" "/private/tmp/repro/target/debug/deps" "-L" "/Users/shep/Projects/rust/x86_64-apple-darwin/stage2/lib/rustlib/x86_64-apple-darwin/lib" "-L" "/private/tmp/repro/.rust/lib/x86_64-apple-darwin" "-L" "/private/tmp/repro/lib/x86_64-apple-darwin" "-lSystem" "-lpthread" "-lc" "-lm" "-lcompiler-rt"
note: ld: warning: directory not found for option '-L/private/tmp/repro/.rust/lib/x86_64-apple-darwin'
ld: warning: directory not found for option '-L/private/tmp/repro/lib/x86_64-apple-darwin'
Undefined symbols for architecture x86_64:
  "order::Alpha::value::hc3fc9d038437a2d2maa", referenced from:
      main::hbbccecd49f526e36faa in repro.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

It looks like the method value is considered unused, and so it is stripped from the final crate. That's fine, except that in another crate we expect to be able to link against that method, and fail nastily when it's not there!

Meta

rustc 1.0.0-dev (c6ca2205e 2015-03-19) (built 2015-03-19)
binary: rustc
commit-hash: c6ca2205eae522387237057812b7901a2c5d3906
commit-date: 2015-03-19
build-date: 2015-03-19
host: x86_64-apple-darwin
release: 1.0.0-dev

Originally from Stack Overflow

@japaric
Copy link
Member

japaric commented Mar 25, 2015

This looks the same as #18082 (comment)

it's just that the definitions of "unused" and "private" are a bit fuzzy with this example.

This RFC states: "Items that are explicitly declared as pub are always public". Per the RFC, the Alpha struct is public, therefore it's correct for it to appear in the return type of yeah. Alpha also happens to be, what I call, an "inaccesible" item because it's inside a private module that downstream crates can't use/reference/name.

Not sure what the behavior should be in this case:

  • yeah().value() should just work, i.e. the inaccessible Alpha::value symbol should be exported in the upstream rlib, even though it's not visible in the upstream docs and is not #[doc(hidden)].
  • yeah().value() should not compile, and error with "type Alpha does not implement any method in scope named value". Which begs the question, what can you do with the return value of yeah()?
  • Forbid putting "inaccessible" items in public signatures, i.e. the upstream crate should fail to compile the yeah function. (FWIW, I prefer this option)

cc @pnkfelix @nrc @alexcrichton

@alexcrichton
Copy link
Member

This code is valid, and it's a compiler bug that the link error is coming up. As @japaric noted, the Alpha struct is considered public because it's marked pub, and then the compiler's analysis is falling down by not detecting that the value function is indeed reachable and needs to be a public symbol.

The link error is covered by #16734, so I'm going to close in favor of that. Thanks for the report though!

@dvdplm
Copy link

dvdplm commented Aug 18, 2015

This helped me a lot, I thought I was going nuts there for a while. :)

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

4 participants