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

Inner statics all have the same symbol name #9188

Closed
alexcrichton opened this issue Sep 14, 2013 · 0 comments · Fixed by #9206
Closed

Inner statics all have the same symbol name #9188

alexcrichton opened this issue Sep 14, 2013 · 0 comments · Fixed by #9206
Labels
A-codegen Area: Code generation

Comments

@alexcrichton
Copy link
Member

Turns out this is not only inconvenient, but also a serious problem.

// bar.rs
pub fn foo<T>() -> &'static int {
    if false {               
        static a: int = 4;       
        return &a;               
    } else {                     
        static a: int = 5;       
        return &a;               
    }                            
}                                

pub fn bar() -> &'static int {   
    foo::<int>()                 
}                                
// foo.rs
extern mod bar;                 

fn main() {                     
    let a = bar::bar();         
    let b = bar::foo::<int>();
    println!("{} {}", *a, *b);  
}                               
$ rustc --lib bar.rs
warning: missing crate link meta `name`, using `bar` as default
warning: missing crate link meta `vers`, using `0.0` as default
warning: no debug symbols in executable (-arch x86_64)
$ rustc foo.rs -L.
warning: no debug symbols in executable (-arch x86_64)
$ ./foo
5 4

Here's what's happening (to the best of my knowledge):

  1. When compiling bar.rs, the same symbol name, N, is generated for both statics. LLVM will silently rename the second to N1, so we have N = 4, N1 = 5. Note that both statics are walked through because this is a generic function, meaning that we still walk the statics to emit them into this crate (may have to do that for inner functions as well).
  2. The function bar is resolved in-crate, and because the symbol names have already been generated, N1 will be returned (5).
  3. When compiling foo.rs, the function bar::foo is again instantiated, but this time we have our clever optimization which ignores the first block of the if statement, hence only one of the statics is translated. In this case, it's declared with the name N.
  4. When linking is done, the version of bar::foo in bar returns N1, and the version of bar::foo in foo returns N, hence the difference.

There's a lot of things going wrong here, and I'm not entirely sure why, but I think that this would all be fixed if inner statics had different symbol names (no silent renamings from LLVM).

bors added a commit that referenced this issue Sep 16, 2013
While they may have the same name within various scopes, this changes static
names to use path_pretty_name to append some hash information at the end of the
symbol. We're then guaranteed that each static has a unique NodeId, so this
NodeId is as the "hash" of the pretty name.

Closes #9188
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.

1 participant