Skip to content

Rollup of 9 pull requests #129933

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

Closed
wants to merge 26 commits into from
Closed
Changes from 3 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
102997a
Update Tests
veera-sivarajan Jul 13, 2024
764675e
Add Tests
veera-sivarajan Aug 6, 2024
f003e92
Don't Suggest Labeling `const` and `unsafe` Blocks
veera-sivarajan Aug 6, 2024
12de141
Suggest `impl Trait` for References to Bare Trait in Function Header
veera-sivarajan Jul 13, 2024
992b0b3
Document the broken C ABI of `wasm32-unknown-unknown`
alexcrichton Aug 26, 2024
28dc116
Don't ICE when dumping MIR of a synthetic coroutine body
compiler-errors Aug 28, 2024
8d3945d
Rename dump of coroutine by-move-body to be more consistent, adjust test
compiler-errors Aug 28, 2024
98106cf
Re-parent the by-move body
compiler-errors Aug 28, 2024
6f6a6bc
Non-exhaustive structs may be empty
Nadrieril Aug 10, 2024
5410900
Adjust `SanityCheck`.
nnethercote Sep 3, 2024
2aae619
Move `MirPass` to `rustc_mir_transform`.
nnethercote Sep 3, 2024
827fa43
Reduce visibility of `MirPass` and related things.
nnethercote Sep 3, 2024
0b2b03c
Clarify a comment.
nnethercote Sep 3, 2024
6188aae
do not attempt to prove unknowable goals
lcnr Sep 2, 2024
aa1f60e
rustc_driver_impl: remove some old dead logic
RalfJung Sep 3, 2024
17f3f92
include 1.80.1 release notes on master
pietroalbini Sep 3, 2024
2d6d6a8
Updates/clarifications
alexcrichton Aug 27, 2024
4b38ef6
Rollup merge of #127692 - veera-sivarajan:bugfix-125139, r=estebank
matthiaskrgr Sep 3, 2024
e3155ab
Rollup merge of #128701 - veera-sivarajan:fix-128604, r=estebank
matthiaskrgr Sep 3, 2024
4e6fa3c
Rollup merge of #128934 - Nadrieril:fix-empty-non-exhaustive, r=compi…
matthiaskrgr Sep 3, 2024
b9c99b6
Rollup merge of #129630 - alexcrichton:document-broken-c-abi-on-wasm3…
matthiaskrgr Sep 3, 2024
aa669ef
Rollup merge of #129706 - compiler-errors:scratch, r=estebank
matthiaskrgr Sep 3, 2024
b777ba9
Rollup merge of #129896 - lcnr:bail-on-unknowable, r=jackh726
matthiaskrgr Sep 3, 2024
7a8ffbc
Rollup merge of #129926 - nnethercote:mv-SanityCheck-and-MirPass, r=c…
matthiaskrgr Sep 3, 2024
b447cd5
Rollup merge of #129928 - RalfJung:rustc_driver_impl-crt-static, r=co…
matthiaskrgr Sep 3, 2024
67c3113
Rollup merge of #129930 - ferrocene:pa-relnotes-1801, r=pietroalbini
matthiaskrgr Sep 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,120 @@ conditionally compile code instead. This is notably different to the way native
platforms such as x86\_64 work, and this is due to the fact that WebAssembly
binaries must only contain code the engine understands. Native binaries work so
long as the CPU doesn't execute unknown code dynamically at runtime.

## Broken `extern "C"` ABI

This target has what is considered a broken `extern "C"` ABI implementation at
this time. Notably the same signature in Rust and C will compile to different
WebAssembly functions and be incompatible. This is considered a bug and it will
be fixed in a future version of Rust.

For example this Rust code:

```rust,ignore (does-not-link)
#[repr(C)]
struct MyPair {
a: u32,
b: u32,
}

extern "C" {
fn take_my_pair(pair: MyPair) -> u32;
}

#[no_mangle]
pub unsafe extern "C" fn call_c() -> u32 {
take_my_pair(MyPair { a: 1, b: 2 })
}
```

compiles to a WebAssembly module that looks like:

```wasm
(module
(import "env" "take_my_pair" (func $take_my_pair (param i32 i32) (result i32)))
(func $call_c
i32.const 1
i32.const 2
call $take_my_pair
)
)
```

The function when defined in C, however, looks like

```c
struct my_pair {
unsigned a;
unsigned b;
};

unsigned take_my_pair(struct my_pair pair) {
return pair.a + pair.b;
}
```

```wasm
(module
(import "env" "__linear_memory" (memory 0))
(func $take_my_pair (param i32) (result i32)
local.get 0
i32.load offset=4
local.get 0
i32.load
i32.add
)
)
```

Notice how Rust thinks `take_my_pair` takes two `i32` parameters but C thinks it
only takes one.

The correct definition of the `extern "C"` ABI for WebAssembly is located in the
[WebAssembly/tool-conventions](https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md)
repository. The `wasm32-unknown-unknown` target (and only this target, not other
WebAssembly targets Rust support) does not correctly follow this document.

Example issues in the Rust repository about this bug are:

* [#115666](https://github.com/rust-lang/rust/issues/115666)
* [#129486](https://github.com/rust-lang/rust/issues/129486)

This current state of the `wasm32-unknown-unknown` backend is due to an
unfortunate accident which got relied on. The `wasm-bindgen` project prior to
0.2.89 was incompatible with the "correct" definition of `extern "C"` and it was
seen as not worth the tradeoff of breaking `wasm-bindgen` historically to fix
this issue in the compiler.

Thanks to the heroic efforts of many involved in this, however, `wasm-bindgen`
0.2.89 and later are compatible with the correct definition of `extern "C"` and
the nightly compiler currently supports a `-Zwasm-c-abi` implemented in
[#117919](https://github.com/rust-lang/rust/pull/117919). This nightly-only flag
can be used to indicate whether the spec-defined version of `extern "C"` should
be used instead of the "legacy" version of
whatever-the-Rust-target-originally-implemented. For example using the above
code you can see (lightly edited for clarity):

```shell
$ rustc +nightly -Zwasm-c-abi=spec foo.rs --target wasm32-unknown-unknown --crate-type lib --emit obj -O
$ wasm-tools print foo.o
(module
(import "env" "take_my_pair" (func $take_my_pair (param i32) (result i32)))
(func $call_c (result i32)
;; ...
)
;; ...
)
```

which shows that the C and Rust definitions of the same function now agree like
they should.

The `-Zwasm-c-abi` compiler flag is tracked in
[#122532](https://github.com/rust-lang/rust/issues/122532) and a lint was
implemented in [#117918](https://github.com/rust-lang/rust/issues/117918) to
help warn users about the transition if they're using `wasm-bindgen` 0.2.88 or
prior. The current plan is to, in the future, switch `-Zwasm-c-api=spec` to
being the default. Some time after that the `-Zwasm-c-abi` flag and the
"legacy" implementation will all be removed. During this process users on a
sufficiently updated version of `wasm-bindgen` should not experience breakage.