Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upSpecifying linkage on externs silently removes indirection #31508
Comments
This comment has been minimized.
This comment has been minimized.
|
This seems like very strange behaviour to me. I'm not sure if "some pointers can't be null" is a sensible reason for this behaviour at all. |
Aatch
added
A-linkage
A-codegen
labels
Feb 9, 2016
This comment has been minimized.
This comment has been minimized.
|
The supported added in #12556 (the indirection here) was only really intended for weak symbols. Weak symbols are currently required to be pointers as otherwise this is not memory safe: extern {
#[linkage = "extern_weak"]
static SYMBOL: extern fn();
}because |
This comment has been minimized.
This comment has been minimized.
|
I guess this bug in particular is about the non-weak pointer case. However, I think the weak pointer case also warrants more discussion, for which I've opened a topic on internals.r-l.o. Here's the code in question btw: https://github.com/rust-lang/rust/blob/3e9589c/src/librustc_trans/trans/foreign.rs#L139-L145 . It does not distinguish at all between different types of linkage. |
jethrogb commentedFeb 9, 2016
When compiling the following code:
using
running
./externswill output something like the following:Wat.
Taking a look at the IR:
So, Rust removes a layer of indirection defining
static explicitvar: [u8;10]and adding a new variablestatic _rust_extern_with_linkage_explicitvar: *const [u8;10]=&explicitvar. All mentions ofexplicitvarin Rust source code get replaced with_rust_extern_with_linkage_explicitvar. This results in the C version and this new Rust version not having the same type! To get “correct” behavior in the example above, you would need to definestatic explicitvar: *const *const [u8;10]instead.This weird assymmetry between the types associated with symbols in Rust and in C is a source of great confusion and can easily lead to bugs. In the example above, we just read 2 bytes past some pointer by interpreting it as a 10-byte array.
This weird behavior was introduced in #12556 (see also #11978), the rationale being weak linkage and the fact that some pointers can't be null in the Rust typesystem. While true, I don't think that's sufficient rationale to add this layer of indirection. I think the layer of indirection should be removed completely. For weak linkage, a restriction can be added to allow only zeroable types.