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

Linker error with non-reachable type #16734

Closed
3 tasks
alexcrichton opened this issue Aug 24, 2014 · 11 comments
Closed
3 tasks

Linker error with non-reachable type #16734

alexcrichton opened this issue Aug 24, 2014 · 11 comments
Labels
A-visibility Area: Visibility / privacy P-low Low priority

Comments

@alexcrichton
Copy link
Member

// foo.rs
pub use foo::Bar;

pub fn test() -> Bar<i32> {
    loop {}
}

mod foo {
    pub type Bar<T> = Result<T, Baz>;

    pub struct Baz;

    impl Baz {
        pub fn foo(&self) {}
    }
}
// bar.rs
extern crate foo;

fn main() {
    match foo::test() {
        Ok(..) => {}
        Err(e) => e.foo()
    }
}
$ rustc --crate-type lib foo.rs      
foo.rs:13:9: 13:29 warning: code is never used: `foo`, #[warn(dead_code)] on by default
foo.rs:13         pub fn foo(&self) {}
                  ^~~~~~~~~~~~~~~~~~~~
$ rustc bar.rs -L.    
error: linking with `cc` failed: exit code: 1
note: cc '-m64' '-L' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib' '-o' 'bar' 'bar.o' '-Wl,--whole-archive' '-lmorestack' '-Wl,--no-whole-archive' '-nodefaultlibs' '-Wl,--gc-sections' '-pie' '-Wl,--as-needed' '/home/alex/code/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libnative-4e7c5e5c.rlib' '/home/alex/libfoo.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/librand-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/liballoc-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/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: bar.o: In function `main::hbeb79415393a4115faa':
bar.rs:(.text._ZN4main20hbeb79415393a4115faaE+0x45): undefined reference to `foo::Baz::foo::h3d69757c908833a5Yaa'
collect2: error: ld returned 1 exit status

error: aborting due to previous error

There are a number of problems with this, and they may likely all be inter-related.

  • linker error
  • dead code which is not actually dead code
  • it should be an error that Baz is a publicly visible private type.

Nominating due to the publicly visible private type not generating an error.

@alexcrichton
Copy link
Member Author

Another example: #20201 (comment)

@steveklabnik
Copy link
Member

This example now builds just fine with Cargo, but the example from the comment still fails with rustc.

@davidrhyswhite
Copy link

I came across a related issue today, put an example of the problematic project here: https://github.com/davidrhyswhite/rust-structs-example

Essentially when running cargo run --example example I get a linking error. The Parent struct is public has a public member called child which is a second struct with a public method. Calling parent.child.method() within the example causes a linking error.

Also a little more information from the rust IRC channel:

davidrhyswhite - Don't suppose anyone could help me understand why I get a 'linking with cc failed exit code 1' when I have a struct nested inside another struct and attempt to call a method on the child struct?
davidrhyswhite - Have a git repo with an example here: https://github.com/davidrhyswhite/rust-structs-example
krdln          - davidrhyswhite: Changing mod child to pub mod child works. You should file a bug, but I'm not shure what should be expected behaviour
mbrubeck       - davidrhyswhite: `cargo build` succeeds for me with only a dead_code warning
davidrhyswhite - Yeah cargo build was fine it was running 'cargo run --example example' that fails for me
mbrubeck       - ah, got it
krdln          - davidrhyswhite: Changing `use child` into `pub use child` works too
davidrhyswhite - Awesome thanks krdln been stuck on this for a while
mbrubeck       - davidrhyswhite: an example is compiled as a separate crate, so it can only call exported (`pub`) code from the main crate.
mbrubeck       - It'd be nice to have better diagnostics instead of just a linker error in cases like this...
krdln          - davidrhyswhite: Rust should either forbid returning private things from public funtions, or it should forbid calling method in example. Either way, file a bug
davidrhyswhite - mbrubeck: Okay, but I though since the child member on the Parent struct was pub and the method was pub too it would allow me to call it
krdln          - davidrhyswhite: Notice that you get warned about Child::method when building a lib
mbrubeck       - since `child::Child::method` is not a publicly-accessible path, it's not exported by the library, so other crates can't link to it.
aawe           - so the rust linker could use a patch for better error messages then
davidrhyswhite - mbrubeck: Thanks, that makes a bit more sense now.
mbrubeck       - aawe: Yeah, it'd be nice if rustc could thrown an error while compiling example.rs, instead of waiting for linking to fail.
mbrubeck       - The error is actually ends up coming from the system linker, gcc in my case.

@dhardy
Copy link
Contributor

dhardy commented Nov 14, 2015

I stumbled across a variation (slightly simpler since there is no templated type). Repo

@petrochenkov
Copy link
Contributor

FWIW, properly exporting everything used in public interfaces is the next thing in my queue after #29822

@dhardy
Copy link
Contributor

dhardy commented Nov 14, 2015

The problem in my example is that the compiler is happy to export a public function (make_greeter) which exports a type (Greeter) public within a submodule but private to the crate. It should complain that make_greeter() returns a private type.

@petrochenkov
Copy link
Contributor

@dhardy

It should complain that make_greeter() returns a private type.

Сommon sense may say this, but the current edition of RFC 136 says otherwise.
Basically, if a type is marked with pub, then you can use it in any public interfaces even if other crates can't name it.

@dhardy
Copy link
Contributor

dhardy commented Nov 14, 2015

No, according to that RFC, what should happen is that:

If it is an fn declaration, items referred to in its trait bounds,
argument types, and return type must be public.

My understanding of the RFC is thus that the compiler currently allows behaviour it shouldn't. Maybe there are some cases where code does this even though it shouldn't, but they will need to enable a gated feature to continue doing so.

@petrochenkov
Copy link
Contributor

@dhardy

When is an item "public"?
Items that are explicitly declared as pub are always public.

I agree, the current rules are somewhat counterintuitive, but changing them requires writing a new RFC and breaking some (pretty rare) code.
Edit: some comments from @nikomatsakis : #28450 (comment)

@DanielKeep
Copy link
Contributor

Just hit this during a refactoring: had a pub-in-private type that I forgot to explicitly re-export.

@petrochenkov
Copy link
Contributor

Ok, I'll try to allocate some time this weekend and fix this, people continue hitting this bug again and again.

bors added a commit that referenced this issue Feb 18, 2016
Fixes #16734 and probably some other issues

This is a continuation of #29822, but the algorithm is mostly a copy of #29973, so
r? @alexcrichton or @nikomatsakis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-visibility Area: Visibility / privacy P-low Low priority
Projects
None yet
Development

No branches or pull requests

7 participants