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`
This commit is contained in:
commit
116201eefe
8 changed files with 217 additions and 134 deletions
|
|
@ -8,6 +8,6 @@ extern crate proc_macro;
|
|||
|
||||
#[proc_macro_derive(A)]
|
||||
pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
//~^ ERROR: mismatched types
|
||||
//~^ ERROR: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn
|
||||
loop {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,23 @@
|
|||
error[E0308]: mismatched types
|
||||
error[E0277]: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
|
||||
--> $DIR/signature.rs:10:1
|
||||
|
|
||||
LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
LL | |
|
||||
LL | | loop {}
|
||||
LL | | }
|
||||
| |_^ expected normal fn, found unsafe fn
|
||||
| | ^
|
||||
| | |
|
||||
| |_call the function in a closure: `|| unsafe { /* code */ }`
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected fn pointer `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
|
||||
found fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
|
||||
note: associated function defined here
|
||||
= help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
|
||||
= note: unsafe function cannot be called generically without an unsafe block
|
||||
note: required by a bound in `ProcMacro::custom_derive`
|
||||
--> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
|
||||
|
|
||||
LL | pub const fn custom_derive(
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue