Repository navigation
Open
Labels
A-FFIArea: Foreign function interface (FFI)Area: Foreign function interface (FFI)A-reprArea: the `#[repr(stuff)]` attributeArea: the `#[repr(stuff)]` attributeC-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-windowsOperating system: WindowsOperating system: WindowsO-windows-msvcToolchain: MSVC, Operating system: WindowsToolchain: MSVC, Operating system: WindowsP-mediumMedium priorityMedium priorityT-langRelevant to the language teamRelevant to the language team
Description
Also see this summary below.
Consider
#![allow(dead_code)]
use std::mem;
#[no_mangle]
pub fn sizeof_empty_struct_1() -> usize {
#[repr(C)]
struct EmptyS1 {
f: [i64; 0],
}
// Expected: 4
// Actual: 0
mem::size_of::<EmptyS1>()
}
#[no_mangle]
pub fn sizeof_empty_struct_2() -> usize {
#[repr(C, align(8))]
struct X {
i: i32,
}
#[repr(C)]
struct EmptyS2 {
x: [X; 0],
}
// Expected: 8
// Actual: 0
mem::size_of::<EmptyS2>()
}
#[no_mangle]
pub fn sizeof_enum() -> usize {
#[repr(C)]
enum E {
A = 1111111111111111111
}
// Expected: 4
// Actual: 8
mem::size_of::<E>()
}
#[no_mangle]
pub fn sizeof_empty_union_1() -> usize {
#[repr(C)]
union EmptyU1 {
f: [i8; 0],
}
// Expected: 1
// Actual: 0
mem::size_of::<EmptyU1>()
}
#[no_mangle]
pub fn sizeof_empty_union_2() -> usize {
#[repr(C)]
union EmptyU2 {
f: [i64; 0],
}
// Expected: 8
// Actual: 0
mem::size_of::<EmptyU2>()
}and the corresponding MSVC output: https://godbolt.org/z/csv4qc
The behavior of MSVC is described here as far as it is known to me: https://github.com/mahkoh/repr-c/blob/a04e931b67eed500aea672587492bd7335ea549d/repc/impl/src/builder/msvc.rs#L215-L236
Reacted by Stepan Koltsov
Metadata
Metadata
Assignees
Labels
A-FFIArea: Foreign function interface (FFI)Area: Foreign function interface (FFI)A-reprArea: the `#[repr(stuff)]` attributeArea: the `#[repr(stuff)]` attributeC-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-windowsOperating system: WindowsOperating system: WindowsO-windows-msvcToolchain: MSVC, Operating system: WindowsToolchain: MSVC, Operating system: WindowsP-mediumMedium priorityMedium priorityT-langRelevant to the language teamRelevant to the language team
Activity
jyn514 commentedon Feb 11, 2021
@mahkoh can you reproduce this without
no_mangle? no_mangle should really require unsafe, it can cause unsoundness if it overlaps with another linker symbol.mahkoh commentedon Feb 11, 2021
@jyn514 Yes
mahkoh commentedon Feb 11, 2021
repr(C) has served two purposes:
The first purpose is advertised both in the reference and in stdlib code e.g. in
Layout. It is probably used in many other places.The second purpose is also advertised in the reference.
However, these purposes are not compatible as shown above.
jonas-schievink commentedon Feb 11, 2021
The layout algorithm is not the same across all targets, it is always supposed to be whatever the C ABI mandates on that particular target
jonas-schievink commentedon Feb 11, 2021
Does this reproduce with clang?
mahkoh commentedon Feb 11, 2021
The layout algorithms used by the C compilers are not the same. But repr(C) is advertised with a specific layout algorithm that is the same across all targets. Namely in these places
Clang contains many bugs in their MSVC-compatible layout algorithm. It should not be used as a reference:
The output of clang is incompatible with both MSVC and rustc: https://github.com/llvm/llvm-project/blob/661f9e2a92302b1c7140528423fdbfc133a68b41/clang/lib/AST/RecordLayoutBuilder.cpp#L3076-L3087
rylev commentedon Feb 12, 2021
Let's make sure the windows notification group is aware of this:
@rustbot ping windows
rustbot commentedon Feb 12, 2021
Hey Windows Group! This bug has been identified as a good "Windows candidate".
In case it's useful, here are some instructions for tackling these sorts of
bugs. Maybe take a look?
Thanks! <3
cc @arlosi @danielframpton @gdr-at-ms @kennykerr @luqmana @lzybkr @nico-abram @retep998 @rylev @sivadeilra
rylev commentedon Feb 12, 2021
Assigning P-high as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.
126 remaining items
briansmith commentedon Mar 31, 2025
No, I would instead expect
repr(c)to product a result that matches the ABI spec, which usually is defined in reference to C.To clarify further my positoin, I think that
#[repr(C)]cannot be used on field-less array structs or an empty array types, since ISO C doesn't support them.repr(C)makes it not zero-sized ("warning, this field-less struct isn't zero-sized").Note that the ABI might define a representation for zero-sized arrays but not field-less structs, or vice-versa. The idea that these are somehow similar constructs is a Rust-ism that doesn't naturally apply to C.
I don't distinguish between "lints" and other kinds of type checks, and I don't know enough to suggest how they should be implemented. I am just suggesting the checks that should exist, independently of how they are implemented
RalfJung commentedon Apr 1, 2025
Note that the examples above don't even involve any field-less structs, they involve 0-length arrays. And apparently those are allowed by MSVC, there's a link in the issue description. So I don't understand why you are focusing on fieldless structs.
Other than that, warnings have been suggested above, so -- not sure what new point you are intending to bring to this conversation.
briansmith commentedon Apr 1, 2025
RalfJung commentedon Apr 1, 2025
I am genuinely puzzled by your comments, I am sorry if that comes across as negative. This is a huge thread, and lints were discussed multiple times before. I was trying to understand if you are suggesting something new or supporting some previously voiced position.
I was referring specifically to the 2nd bullet about windows -- sorry, I should have made that more clear. I'm sometimes replying in haste when wading through my backlog. Maybe I should stop engaging in some threads entirely so that I can spend proper time on the remaining ones and be more likely to be productive there.
In that bullet, you mostly spoke about "fieldless structs"; there was one mention of "fieldless arrays" which looked like a typo since the immediately next sentence just spoke about "structs" again and "fieldless array" does not make sense (I think? arrays don't usually have "fields").
Now you edited this adding more mentions of "arrays", without leaving a note that there was an edit, which is disingenuous given that I already replied.
In the edited version you are claiming the windows ABI does not have zero-sized arrays, but in the OP we have C code using zero-sized arrays with MSVC. I am still puzzled by your comments.
I mean, the Rust compiler does, so when proposing changes to the Rust compiler it'd be good to use terms that make sense in this context. Otherwise how should anyone understand what you are saying?
Also, my key question for you was in the next line which you did not reply to at all:
"What is not clear to me is whether you think a lint with false negatives is sufficient to resolve this issue or not."
That's entirely unrelated to whether it's called a "lint" or not, the key is you did not make it clear whether the check should in your opinion be best-effort or must be fully reliable to realize your vision for how this should be handled (where the latter requires a post-monomorphization check which has a long list of downsides).
But, I think I am getting the clue, you don't like the way I am probing your comments to try and understand them. I am not sure what to do about that. Asking a question does not mean I am saying you are wrong, or being negative. Don't try to read things between the lines, there's nothing there, what I want to express is just literally the question that I wrote.
CAD97 commentedon Apr 1, 2025
There are two ways of defining "the Win64 ABI:" what the Microsoft Learn documentation says, and what MSVC does.
I believe @briansmith's position is that the prose documentation (which in the MSVC case, is never referred to as a specification) should be considered authoritative, and anything not defined in said documentation should not be considered defined for FFI.
The more typically expected understanding is that MSVC provides a stable ABI for any C signature that it allows you to write, and that what the compiler does is the source of truth, not the documentation.
Jules-Bertholet commentedon May 5, 2026
Godbolt says that this C program:
Prints the following on x86-64 MSVC:
Even if we split
repr(ordered_fields)fromrepr(C), that just seems too cursed to replicate?(Replacing
long longwithdoublehas the same effect. With__m64, however, the size is 8.)However, we could interpret this as a specific instance of the general issue that
_Alignofon MSVC is a lie, and define this as having alignment of 4 in Rust. But that doesn't work for 64-bit…Jules-Bertholet commentedon May 6, 2026
Reported to Microsoft: https://developercommunity.visualstudio.com/t/C-structs-containing-only-a-flexible-arr/11086085
(An upvote on the issue might help it get prioritized)
RalfJung commentedon May 6, 2026
_Alignofon MSVC is "preferred alignment", right? I don't think we have any way of querying the required alignment on MSVC, do we? So, there's not that much we can actually read into that value sadly.Jules-Bertholet commentedon May 6, 2026
Yes, that's what I explain in the issue. But if
struct empty { long long i[]; };is to have alignment 4 even on x64, as thesizeofwould imply, that's going to be a problem (because it would imply that we have to makeu644-aligned on x64, or that the Rust equivalent of that struct has to effectively berepr(packed))jendrikw commentedon May 7, 2026
You can also upvote this issue about
alignashttps://developercommunity.visualstudio.com/t/visual-c-alignof-is-not-conformant-on-x86/1258506Jules-Bertholet commentedon Aug 10, 2026
Microsoft responded: https://developercommunity.visualstudio.com/t/C-structs-containing-only-a-flexible-arr/11086085
Jules-Bertholet commentedon Aug 10, 2026
https://rust-lang.zulipchat.com/#narrow/channel/122651-general/topic/Please.20upvote.20my.20issue.20on.20MSVC's.20issue.20tracker/near/615558327