Repository navigation
Distinguish repr(C) ZSTs from others in ABI computation - #156112
Jules-Bertholet wants to merge 1 commit into
Conversation
|
r? @JohnTitor rustbot has assigned @JohnTitor. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
|
I don't think this fixes that issue. We need #155299 for that (and a wording change to the ABI docs). This new logic can be entirely removed again once we compute the right layout for zero-element Let's see if this new field shows up in perf. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Distinguish `repr(C)` ZSTs from others in ABI computation
f72b6fa to
9a2f4c8
Compare
| // CHECK: define win64cc void @pass_zst_win64(ptr {{[^,]*}}) | ||
| // CHECK: define win64cc void @pass_rust_zst_win64() | ||
| #[no_mangle] | ||
| extern "win64" fn pass_rust_zst_win64(_: ()) {} |
There was a problem hiding this comment.
This will be interesting... I am not sure how to make sense of this ABI on non-MSVC targets. Given that the type layout itself is "wrong", how could one possibly actually call such a function...?
There was a problem hiding this comment.
You could call such a function from C with a signature of void pass_rust_zst_win64(). However, the Rust signature trips the improper_ctypes lint, so that's not something we are committing to.
There was a problem hiding this comment.
Currently, you could not. We don't allow any arguments to be omitted at the moment.
There was a problem hiding this comment.
Also note that I am talking about the "win64" ABI in general, not just this particular function -- I should have been more clear about that.
A "win64" function call on a windows-gnu or Linux target that involves a zero-field struct (or struct whose only field is a 0-element array) might just produce nonsense, right? We'd need repr(win64) as well.
There was a problem hiding this comment.
Reading through prior discussion in rust-lang/unsafe-code-guidelines#552, I still agree with what I wrote there:
I think my stance here is what the win64 ABI simply does not support 1-ZST structs. We shouldn't take what gcc/clang do for that ABI as gospel since they do not "own" the ABI, MSVC/Microsoft does.
We should emit FFI warnings (and, eventually, errors) for code that uses an ABI outside of what the vendor has (explicitly or implicitly) defined. We should not take what GCC/clang do as gospel for Windows targets. For this concrete question that means we should disallow passing ZST.
And it seems like windows-gnu targets use the same ABI so this applies to them as well.
Is that too radical or is it something we could get away with?
There was a problem hiding this comment.
this hasn't really been answered yet
There was a problem hiding this comment.
My position hasn't changed. We could always add a lint, but I don't think we should block this PR on that.
There was a problem hiding this comment.
What is the behavior of the win64 ABI with this PR?
There was a problem hiding this comment.
Trivial ABI types are ignored, and empty repr(C) structs are passed by pointer.
There was a problem hiding this comment.
I guess for now that's the only thing we can do. However it'd be worth a FIXME to say that empty repr(C) structs shouldn't even exist on this target, i.e., this is primarily working around our layout computation being slightly off, and now is also needed due to backwards compatibility.
9a2f4c8 to
8a01401
Compare
That's
No, because these structs should remain zero-sized on many targets, including ones where they are passed by pointer. |
a74ed3a to
e2ee4b8
Compare
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (167ff94): comparison URL. Overall result: ❌✅ regressions and improvements - please read:Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. Next, please: If you can, justify the regressions found in this try perf run in writing along with @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -3.1%, secondary 2.4%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (secondary -0.2%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary -0.0%, secondary -0.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 494.817s -> 493.602s (-0.25%) |
If you are putting non-trivial implementation changes into the same PR as insta-stable docs updates (that will require t-lang FCP), you're making this PR a lot more difficult to work with. It'd be a good idea to split this up. |
This comment has been minimized.
This comment has been minimized.
|
r? RalfJung |
…alfJung Distinguish `repr(C)` ZSTs from others in ABI compatibility rules FCP: rust-lang/rust#157973 (comment) (Split out from compiler implementation in rust-lang/rust#156112) Some C ABIs pass and return ZSTs by pointer. But `()` should never be returned by pointer, as it must match `void`. To account for this, we have to weaken the present guarantee of "any two types with size 0 and alignment 1 are ABI-compatible" to exclude `repr(C)`. [t-lang nomination summary comment](rust-lang/rust#157973 (comment)) Fixes rust-lang/unsafe-code-guidelines#552; see also rust-lang/rust#78586, rust-lang/rust#155299. Also related to rust-lang/rust#155984. @rustbot label T-lang A-ABI needs-fcp
|
@bors rollup=iffy |
…, r=oli-obk Distinguish `repr(C)` ZSTs from others in ABI computation Implement rust-lang#157973: Some C ABIs pass and return ZSTs by pointer. But `()` should never be returned by pointer, as it must match `void`. To fix this, distinguish `repr(C)` ZSTs (and `repr(transparent)` wrappers around them) from other ZSTs in ABI computation. Fixes rust-lang/unsafe-code-guidelines#552. cc @RalfJung
|
💔 I suspect this PR failed tests as part of a rollup After fixing the problem, consider running a try job for the failed job before re-approving. Link to failure: #163929 (comment) |
|
This pull request was unapproved. This PR was contained in a rollup (#163929), which was unapproved. |
This comment has been minimized.
This comment has been minimized.
95811cf to
071a730
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
Co-Authored-By: Ralf Jung <post@ralfj.de>
071a730 to
916dda0
Compare
|
@rustbot ready |
| }, | ||
| max_repr_align: None, | ||
| unadjusted_abi_align: Align(8 bytes), | ||
| repr_c: false, |
There was a problem hiding this comment.
So VaList<'_> is not repr_c? But it was before the most recent rebase? Odd.
There was a problem hiding this comment.
That is not from the rebase, that is to fix the test failure in rollup. It always should have been false (for Windows specifically)
There was a problem hiding this comment.
Hm, that seems surprising, we make ABI guarantees about that type after all...
It looks like it's a transparent wrapper around a pointer. That has guaranteed ABI but is not repr_c. I guess that matches the definition of the field. Makes me wonder if a general "has C-compatible ABI" field would make sense but that's a separate refactor.
|
@bors r=oli-obk |
…, r=oli-obk Distinguish `repr(C)` ZSTs from others in ABI computation Implement rust-lang#157973: Some C ABIs pass and return ZSTs by pointer. But `()` should never be returned by pointer, as it must match `void`. To fix this, distinguish `repr(C)` ZSTs (and `repr(transparent)` wrappers around them) from other ZSTs in ABI computation. Fixes rust-lang/unsafe-code-guidelines#552. cc @RalfJung
…uwer Rollup of 19 pull requests Successful merges: - #156112 (Distinguish `repr(C)` ZSTs from others in ABI computation) - #157941 (Deny partial `-Z stack-protector` by default in all editions) - #163462 (Fix COFF renaming of decorated (stdcall/fastcall/vectorcall) exports) - #163855 (Include enclosing item's context on const errors) - #163861 (Run LLDB debuginfo tests on `x86_64-mingw`) - #163913 ( Silence redundant failed obligations on the same statement) - #161201 (Speed up tidy again) - #163380 (Tweak "name not found" resolution error when it happens from within a derive expansion) - #163538 (Add `rustc::missing_generic_type_visitable` lint) - #163617 (mips: make `Complex<T>` ABI match GCC) - #163772 (comptime fn error: suggest wrapping in const block) - #163813 (use pre-borrowck typing env for early MIR validation) - #163924 (replace instances of NonNull::new(&mut x).expect("...") with NonNull::from_mut) - #163958 (only make `RustaceansAreAwesome` satisfy trait clauses) - #163960 (vexos: clear .bss from assembly) - #163974 (Condense AdtDef lang item checks into one match) - #163979 (Add `bf16` to arm features) - #163989 (Revert "compiletest: stream output of executor process when --no-capture is set") - #163995 (m68k-unknown-none-elf: Remove code model) Failed merges: - #163832 (reject non-async coroutine closures as async callables) - #163972 (const-eval: ICE when we hit a non-const fn)
View all comments
Implement #157973:
Some C ABIs pass and return ZSTs by pointer. But
()should never be returned by pointer, as it must matchvoid. To fix this, distinguishrepr(C)ZSTs (andrepr(transparent)wrappers around them) from other ZSTs in ABI computation.Fixes rust-lang/unsafe-code-guidelines#552.
cc @RalfJung