diff options
| author | bors <bors@rust-lang.org> | 2022-05-28 16:49:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-05-28 16:49:52 +0000 |
| commit | 116201eefebcf45074ae232377e7145f5fbb704b (patch) | |
| tree | a5981e4e7c67e1ab311782da7926c135f5b9645a /compiler/rustc_mir_transform/src | |
| parent | 4f39fb1f34d4bd25d9ce96afe7b2d109f073e286 (diff) | |
| parent | 78a83b0d5fb90d3fa9418592282b55e9f2e496be (diff) | |
| download | rust-116201eefebcf45074ae232377e7145f5fbb704b.tar.gz rust-116201eefebcf45074ae232377e7145f5fbb704b.zip | |
Auto merge of #97461 - eddyb:proc-macro-less-payload, r=bjorn3
proc_macro: don't pass a client-side function pointer through the server.
Before this PR, `proc_macro::bridge::Client<F>` contained both:
* the C ABI entry-point `run`, that the server can call to start the client
* some "payload" `f: F` passed to that entry-point
* in practice, this was always a (client-side Rust ABI) `fn` pointer to the actual function the proc macro author wrote, i.e. `#[proc_macro] fn foo(input: TokenStream) -> TokenStream`
In other words, the client was passing one of its (Rust) `fn` pointers to the server, which was passing it back to the client, for the client to call (see later below for why that was ever needed).
I was inspired by `@nnethercote's` attempt to remove the `get_handle_counters` field from `Client` (see https://github.com/rust-lang/rust/pull/97004#issuecomment-1139273301), which combined with removing the `f` ("payload") field, could theoretically allow for a `#[repr(transparent)]` `Client` that mostly just newtypes the C ABI entry-point `fn` pointer <sub>(and in the context of e.g. wasm isolation, that's *all* you want, since you can reason about it from outside the wasm VM, as just a 32-bit "function table index", that you can pass to the wasm VM to call that function)</sub>.
<hr/>
So this PR removes that "payload". But it's not a simple refactor: the reason the field existed in the first place is because monomorphizing over a function type doesn't let you call the function without having a value of that type, because function types don't implement anything like `Default`, i.e.:
```rust
extern "C" fn ffi_wrapper<A, R, F: Fn(A) -> R>(arg: A) -> R {
let f: F = ???; // no way to get a value of `F`
f(arg)
}
```
That could be solved with something like this, if it was allowed:
```rust
extern "C" fn ffi_wrapper<
A, R,
F: Fn(A) -> R,
const f: F // not allowed because the type is a generic param
>(arg: A) -> R {
f(arg)
}
```
Instead, this PR contains a workaround in `proc_macro::bridge::selfless_reify` (see its module-level comment for more details) that can provide something similar to the `ffi_wrapper` example above, but limited to `F` being `Copy` and ZST (and requiring an `F` value to prove the caller actually can create values of `F` and it's not uninhabited or some other unsound situation).
<hr/>
Hopefully this time we don't have a performance regression, and this has a chance to land.
cc `@mystor` `@bjorn3`
Diffstat (limited to 'compiler/rustc_mir_transform/src')
0 files changed, 0 insertions, 0 deletions
