diff options
author | Matt Mastracci <matthew@mastracci.com> | 2023-06-29 10:23:14 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-29 10:23:14 -0600 |
commit | fbb69329343c9985c26181e6297e6556c46d381d (patch) | |
tree | ee428c94727bdfdf9040a4944bd66981b4cd07fb /ops/op2/mod.rs | |
parent | 98df69fd4cbe3687e2ff3519fbd6bff4e5f3101f (diff) |
refactor(ops): op2 support for generics (#19636)
Implementation of generics for `#[op2]`, along with some refactoring to
improve the ergonomics of ops with generics parameters:
- The ops have generics on the struct rather than the associated
methods, which allows us to trait-ify ops (impossible when they are on
the methods)
- The decl() method can become a trait-associated const field which
unlocks future optimizations
Callers of ops need to switch from:
`op_net_connect_tcp::call::<TestPermission>(conn_state, ip_addr)` to
`op_net_connect_tcp::<TestPermission>::call(conn_state, ip_addr)`.
Diffstat (limited to 'ops/op2/mod.rs')
-rw-r--r-- | ops/op2/mod.rs | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/ops/op2/mod.rs b/ops/op2/mod.rs index 67a92d450..7f652fe1b 100644 --- a/ops/op2/mod.rs +++ b/ops/op2/mod.rs @@ -8,6 +8,7 @@ use quote::quote; use quote::ToTokens; use std::iter::zip; use syn2::parse2; +use syn2::parse_str; use syn2::FnArg; use syn2::ItemFn; use syn2::Path; @@ -104,6 +105,7 @@ fn generate_op2( let call = Ident::new("call", Span::call_site()); let mut op_fn = func.clone(); op_fn.attrs.clear(); + op_fn.sig.generics.params.clear(); op_fn.sig.ident = call.clone(); // Clear inert attributes @@ -133,8 +135,8 @@ fn generate_op2( let scope = Ident::new("scope", Span::call_site()); let info = Ident::new("info", Span::call_site()); let opctx = Ident::new("opctx", Span::call_site()); - let slow_function = Ident::new("slow_function", Span::call_site()); - let fast_function = Ident::new("fast_function", Span::call_site()); + let slow_function = Ident::new("v8_fn_ptr", Span::call_site()); + let fast_function = Ident::new("v8_fn_ptr_fast", Span::call_site()); let fast_api_callback_options = Ident::new("fast_api_callback_options", Span::call_site()); @@ -196,13 +198,39 @@ fn generate_op2( let arg_count: usize = generator_state.args.len(); let vis = func.vis; + let generic = signature + .generic_bounds + .keys() + .map(|s| format_ident!("{s}")) + .collect::<Vec<_>>(); + let bound = signature + .generic_bounds + .values() + .map(|p| parse_str::<Path>(p).expect("Failed to reparse path")) + .collect::<Vec<_>>(); Ok(quote! { #[allow(non_camel_case_types)] - #vis struct #name { + #vis struct #name <#(#generic),*> { + // We need to mark these type parameters as used, so we use a PhantomData + _unconstructable: ::std::marker::PhantomData<(#(#generic),*)> } - impl #name { + impl <#(#generic : #bound),*> #deno_core::_ops::Op for #name <#(#generic),*> { + const NAME: &'static str = stringify!(#name); + const DECL: #deno_core::_ops::OpDecl = #deno_core::_ops::OpDecl { + name: stringify!(#name), + v8_fn_ptr: Self::#slow_function as _, + enabled: true, + fast_fn: #fast_definition, + is_async: false, + is_unstable: false, + is_v8: false, + arg_count: #arg_count as u8, + }; + } + + impl <#(#generic : #bound),*> #name <#(#generic),*> { pub const fn name() -> &'static str { stringify!(#name) } @@ -220,8 +248,8 @@ fn generate_op2( } } - #slow_fn #fast_fn + #slow_fn #[inline(always)] #op_fn |