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

Reexported private functions cause linker errors #9790

Closed
alexcrichton opened this issue Oct 10, 2013 · 3 comments · Fixed by #9791
Closed

Reexported private functions cause linker errors #9790

alexcrichton opened this issue Oct 10, 2013 · 3 comments · Fixed by #9791
Labels
A-codegen Area: Code generation

Comments

@alexcrichton
Copy link
Member

If you have a library with this code:

pub use foo::bar;

mod foo {
  pub fn bar() {}
}

No one can use the bar function at the top-level. The reason for this is that we mark the function with an inline linkage, and LLVM then internalizes the symbol so no one else can use it.

After some digging, it looks like this is because it is not flagged as "reachable" in the reachability pass of the compiler. After taking a look at the code, the reachability pass is doing a lot of approximations about privacy, and it's not taking public re-exports into account.

I believe that the best solution is to instead use the output of the privacy pass of the compiler to initially seed the work list of the reachability pass. Reachability should know nothing about privacy, it should only have to perform the iterations necessary to create a set of reachable items from public items.

@alexcrichton
Copy link
Member Author

As an example of where this can go wrong:

$ cat foo.rs
pub use foo::bar;

mod foo {
    pub fn bar() {}
}
$ cat bar.rs
extern mod foo;

fn main() {
    foo::bar();
}
$ rustc foo.rs --lib
warning: missing crate link meta `name`, using `foo` as default
warning: missing crate link meta `vers`, using `0.0` as default
warning: no debug symbols in executable (-arch x86_64)
$ rustc bar.rs -L.
warning: no debug symbols in executable (-arch x86_64)                                                              
$ ./bar
dyld: lazy symbol binding failed: Symbol not found: __ZN3foo3bar19h15bec6257b8bff78ak4v0.0E                         
  Referenced from: /Users/alex/code/rust-opt/./bar                                                                  
  Expected in: flat namespace                                                                                       

dyld: Symbol not found: __ZN3foo3bar19h15bec6257b8bff78ak4v0.0E                                                     
  Referenced from: /Users/alex/code/rust-opt/./bar                                                                  
  Expected in: flat namespace                                                                                       

zsh: trace trap  ./bar                                                                                              

@SiegeLord
Copy link
Contributor

Is this the same issue affecting this code?

pub use internal::S;
mod internal
{
    pub struct S;
    impl S
    {
        pub fn test(&self) {}
    }
}
test.rc:(.text+0x39): undefined reference to `internal::S::test::he344781a19bc4532DkaI::v0.0'

@alexcrichton
Copy link
Member Author

Checked to make sure, that test case fails on master and passes with this patch.

bors added a commit that referenced this issue Oct 10, 2013
This fixes a bug in which the visibility rules were approximated by
reachability, but forgot to cover the case where a 'pub use' reexports a private
item. This fixes the commit by instead using the results of the privacy pass of
the compiler to create the initial working set of the reachability pass.

This may have the side effect of increasing the size of metadata, but it's
difficult to avoid for correctness purposes sadly.

Closes #9790
bors added a commit that referenced this issue Oct 10, 2013
This fixes a bug in which the visibility rules were approximated by
reachability, but forgot to cover the case where a 'pub use' reexports a private
item. This fixes the commit by instead using the results of the privacy pass of
the compiler to create the initial working set of the reachability pass.

This may have the side effect of increasing the size of metadata, but it's
difficult to avoid for correctness purposes sadly.

Closes #9790
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants