From fbb69329343c9985c26181e6297e6556c46d381d Mon Sep 17 00:00:00 2001 From: Matt Mastracci Date: Thu, 29 Jun 2023 10:23:14 -0600 Subject: 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::(conn_state, ip_addr)` to `op_net_connect_tcp::::call(conn_state, ip_addr)`. --- ops/op2/mod.rs | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'ops/op2/mod.rs') 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::>(); + let bound = signature + .generic_bounds + .values() + .map(|p| parse_str::(p).expect("Failed to reparse path")) + .collect::>(); 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 -- cgit v1.2.3