-
Notifications
You must be signed in to change notification settings - Fork 14k
Closed
Labels
A-codegenArea: Code generationArea: Code generation
Description
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):
- 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). - The function
baris resolved in-crate, and because the symbol names have already been generated,N1will be returned (5). - When compiling
foo.rs, the functionbar::foois again instantiated, but this time we have our clever optimization which ignores the first block of theifstatement, hence only one of the statics is translated. In this case, it's declared with the name N. - When linking is done, the version of
bar::fooinbarreturns N1, and the version ofbar::fooinfooreturns 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).
Metadata
Metadata
Assignees
Labels
A-codegenArea: Code generationArea: Code generation