Repository: denoland/deno_core
Pull request #818 (2024-07-11 02:34:53)

feat: use cppgc::Ptr
Uses https://github.com/denoland/rusty_v8/pull/1523 to avoid cppgc::Member overhead. Also move all Persistent logic into cppgc.rs to clean up the macro code.

There is done using a new `Ptr` struct which can deref into the inner member of `CppGcObject`. This is structured so as to play a little trick and inline `T` into `CppGcObject<T>` which halves the allocations and enables a future change for getting `&dyn Reference` from deno-managed cppgc objects.


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index e54ee3f..f90c919 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2736,9 +2736,9 @@ dependencies = [
 
 [[package]]
 name = "v8"
-version = "0.97.0"
+version = "0.98.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ecc402c55b363c29901bdd0613c68213b01c5b2a3ee362d5e985cb74901b472"
+checksum = "feb252d5be11c32cb4755d66d58db30ff30af5f1f17183e83ff54383a402c5f6"
 dependencies = [
  "bindgen",
  "bitflags",
diff --git a/Cargo.toml b/Cargo.toml
index bc5a379..1804b87 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,7 +24,7 @@ deno_ops = { version = "0.169.0", path = "./ops" }
 serde_v8 = { version = "0.202.0", path = "./serde_v8" }
 deno_core_testing = { path = "./testing" }
 
-v8 = { version = "0.97.0", default-features = false }
+v8 = { version = "0.98.0", default-features = false }
 deno_ast = { version = "=0.35.3", features = ["transpiling"] }
 deno_unsync = "0.3.10"
 deno_core_icudata = "0.0.73"
diff --git a/core/cppgc.rs b/core/cppgc.rs
index 40dd147..455a962 100644
--- a/core/cppgc.rs
+++ b/core/cppgc.rs
@@ -9,12 +9,12 @@ const CPPGC_TAG: u16 = 1;
 #[repr(C)]
 struct CppGcObject<T: GarbageCollected> {
   tag: TypeId,
-  member: v8::cppgc::Member<T>,
+  member: T,
 }
 
 impl<T: GarbageCollected> v8::cppgc::GarbageCollected for CppGcObject<T> {
   fn trace(&self, visitor: &v8::cppgc::Visitor) {
-    visitor.trace(&self.member);
+    self.member.trace(visitor);
   }
 }
 
@@ -48,7 +48,7 @@ pub fn make_cppgc_object<'a, T: GarbageCollected + 'static>(
       heap,
       CppGcObject {
         tag: TypeId::of::<T>(),
-        member: v8::cppgc::make_garbage_collected(heap, t),
+        member: t,
       },
     )
   };
@@ -60,31 +60,54 @@ pub fn make_cppgc_object<'a, T: GarbageCollected + 'static>(
   obj
 }
 
+#[doc(hidden)]
+pub struct Ptr<T: GarbageCollected> {
+  inner: v8::cppgc::Ptr<CppGcObject<T>>,
+  root: Option<v8::cppgc::Persistent<CppGcObject<T>>>,
+}
+
+#[doc(hidden)]
+impl<T: GarbageCollected> Ptr<T> {
+  /// If this pointer is used in an async function, it could leave the stack,
+  /// so this method can be called to root it in the GC and keep the reference
+  /// valid.
+  pub fn root(&mut self) {
+    if self.root.is_none() {
+      self.root = Some(v8::cppgc::Persistent::new(&self.inner));
+    }
+  }
+}
+
+impl<T: GarbageCollected> std::ops::Deref for Ptr<T> {
+  type Target = T;
+  fn deref(&self) -> &T {
+    &self.inner.member
+  }
+}
+
 #[doc(hidden)]
 #[allow(clippy::needless_lifetimes)]
 pub fn try_unwrap_cppgc_object<'sc, T: GarbageCollected + 'static>(
   scope: &mut v8::HandleScope<'sc>,
   val: v8::Local<'sc, v8::Value>,
-) -> v8::cppgc::Member<T> {
+) -> Option<Ptr<T>> {
   let Ok(obj): Result<v8::Local<v8::Object>, _> = val.try_into() else {
-    return v8::cppgc::Member::empty();
+    return None;
   };
 
   if !obj.is_api_wrapper() {
-    return v8::cppgc::Member::empty();
+    return None;
   }
 
-  let ptr =
-    unsafe { v8::Object::unwrap::<CPPGC_TAG, CppGcObject<T>>(scope, obj) };
-  let Some(obj) = ptr.borrow() else {
-    return v8::cppgc::Member::empty();
-  };
+  let obj =
+    unsafe { v8::Object::unwrap::<CPPGC_TAG, CppGcObject<T>>(scope, obj) }?;
 
   if obj.tag != TypeId::of::<T>() {
-    return v8::cppgc::Member::empty();
+    return None;
   }
 
-  let mut h = v8::cppgc::Member::empty();
-  h.set(&obj.member);
-  h
+  Some(Ptr {
+    inner: obj,
+    root: None,
+  })
 }
diff --git a/ops/op2/dispatch_fast.rs b/ops/op2/dispatch_fast.rs
index e7f77b8..5680a7a 100644
--- a/ops/op2/dispatch_fast.rs
+++ b/ops/op2/dispatch_fast.rs
@@ -455,12 +455,12 @@ pub(crate) fn generate_dispatch_fast(
     generator_state.needs_fast_scope = true;
     generator_state.needs_fast_api_callback_options = true;
     gs_quote!(generator_state(self_ty, scope, fast_api_callback_options) => {
-      let self_handle_ = deno_core::_ops::try_unwrap_cppgc_object::<#self_ty>(&mut #scope, this.into());
-      let Some(self_) = self_handle_.borrow() else {
+      let Some(self_) = deno_core::_ops::try_unwrap_cppgc_object::<#self_ty>(&mut #scope, this.into()) else {
         #fast_api_callback_options.fallback = true;
         // SAFETY: All fast return types have zero as a valid value
         return unsafe { std::mem::zeroed() };
       };
+      let self_ = &*self_;
     })
   } else {
     quote!()
@@ -764,12 +764,12 @@ fn map_v8_fastcall_arg_to_arg(
       *needs_fast_scope = true;
       *needs_fast_api_callback_options = true;
       quote! {
-        let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident);
-        let Some(#arg_ident) = handle_.borrow() else {
+        let Some(#arg_ident) = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident) else {
           #fast_api_callback_options.fallback = true;
           // SAFETY: All fast return types have zero as a valid value
           return unsafe { std::mem::zeroed() };
         };
+        let #arg_ident = &*#arg_ident;
       }
     }
     Arg::OptionCppGcResource(ty) => {
@@ -779,20 +779,16 @@ fn map_v8_fastcall_arg_to_arg(
       *needs_fast_scope = true;
       *needs_fast_api_callback_options = true;
       quote! {
-        let mut handle_ = deno_core::v8::cppgc::Member::empty();
         let #arg_ident = if #arg_ident.is_null_or_undefined() {
           None
+        } else if let Some(#arg_ident) = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident) {
+          Some(#arg_ident)
         } else {
-          handle_.set(&deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident));
-          match handle_.borrow() {
-            Some(r) => Some(r),
-            None => {
-              #fast_api_callback_options.fallback = true;
-              // SAFETY: All fast return types have zero as a valid value
-              return unsafe { std::mem::zeroed() };
-            }
-          }
+          #fast_api_callback_options.fallback = true;
+          // SAFETY: All fast return types have zero as a valid value
+          return unsafe { std::mem::zeroed() };
         };
+        let #arg_ident = #arg_ident.as_deref();
       }
     }
     _ => quote!(let #arg_ident = #arg_ident as _;),
diff --git a/ops/op2/dispatch_slow.rs b/ops/op2/dispatch_slow.rs
index 19cd508..87e3785 100644
--- a/ops/op2/dispatch_slow.rs
+++ b/ops/op2/dispatch_slow.rs
@@ -257,26 +257,23 @@ pub(crate) fn with_self(
   let tokens = if matches!(ret_val, RetVal::Future(_) | RetVal::FutureResult(_))
   {
     let tokens = gs_quote!(generator_state(self_ty, fn_args, scope) => {
-      let self_handle_ = deno_core::_ops::try_unwrap_cppgc_object::<#self_ty>(&mut #scope, #fn_args.this().into());
-      if self_handle_.borrow().is_none() {
+      let Some(mut self_) = deno_core::_ops::try_unwrap_cppgc_object::<#self_ty>(&mut #scope, #fn_args.this().into()) else {
         #throw_exception;
-      }
-      let mut self_persistent_ = deno_core::v8::cppgc::Persistent::empty();
-      self_persistent_.set(&self_handle_);
-      drop(self_handle_);
+      };
+      self_.root();
     });
 
     generator_state.moves.push(quote! {
-      let self_ = self_persistent_.borrow().unwrap();
+      let self_ = &*self_;
     });
 
     tokens
   } else {
     gs_quote!(generator_state(self_ty, fn_args, scope) => {
-      let self_handle_ = deno_core::_ops::try_unwrap_cppgc_object::<#self_ty>(&mut #scope, #fn_args.this().into());
-      let Some(self_) = self_handle_.borrow() else {
+      let Some(self_) = deno_core::_ops::try_unwrap_cppgc_object::<#self_ty>(&mut #scope, #fn_args.this().into()) else {
         #throw_exception;
       };
+      let self_ = &*self_;
     })
   };
   Ok(tokens)
@@ -582,24 +579,21 @@ pub fn from_arg(
         syn::parse_str::<syn::Path>(ty).expect("Failed to reparse state type");
       if matches!(ret_val, RetVal::Future(_) | RetVal::FutureResult(_)) {
         let tokens = quote! {
-          let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident);
-          if handle_.borrow().is_none() {
+          let Some(mut #arg_ident) = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident) else {
             #throw_exception;
-          }
-          let mut #arg_ident = deno_core::v8::cppgc::Persistent::empty();
-          #arg_ident.set(&handle_);
-          drop(handle_);
+          };
+          #arg_ident.root();
         };
         generator_state.moves.push(quote! {
-          let #arg_ident = #arg_ident.borrow().unwrap();
+          let #arg_ident = &*#arg_ident;
         });
         tokens
       } else {
         quote! {
-          let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident);
-          let Some(#arg_ident) = handle_.borrow() else {
+          let Some(#arg_ident) = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident) else {
             #throw_exception;
           };
+          let #arg_ident = &*#arg_ident;
         }
       }
     }
@@ -613,37 +607,30 @@ pub fn from_arg(
       if matches!(ret_val, RetVal::Future(_) | RetVal::FutureResult(_)) {
         let tokens = quote! {
           let #arg_ident = if #arg_ident.is_null_or_undefined() {
-            deno_core::v8::cppgc::Persistent::empty()
+            None
+          } else if let Some(mut #arg_ident) = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident) {
+            #arg_ident.root();
+            Some(#arg_ident)
           } else {
-            let handle = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident);
-            if handle.borrow().is_none() {
-              #throw_exception;
-            }
-            let mut persistent = deno_core::v8::cppgc::Persistent::empty();
-            persistent.set(&handle);
-            persistent
+            #throw_exception;
           };
         };
 
         generator_state.moves.push(quote! {
-          let #arg_ident = #arg_ident.borrow();
+          let #arg_ident = #arg_ident.as_deref();
         });
 
         tokens
       } else {
         quote! {
-          let mut handle_ = deno_core::v8::cppgc::Member::empty();
           let #arg_ident = if #arg_ident.is_null_or_undefined() {
             None
+          } else if let Some(#arg_ident) = deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident) {
+            Some(#arg_ident)
           } else {
-            handle_.set(&deno_core::_ops::try_unwrap_cppgc_object::<#ty>(&mut #scope, #arg_ident));
-            match handle_.borrow() {
-              Some(r) => Some(r),
-              None => {
-                #throw_exception;
-              }
-            }
+            #throw_exception;
           };
+          let #arg_ident = #arg_ident.as_deref();
         }
       }
     }


Test patch:
diff --git a/ops/op2/test_cases/async/async_cppgc.out b/ops/op2/test_cases/async/async_cppgc.out
index 1a48043..07aaf0c 100644
--- a/ops/op2/test_cases/async/async_cppgc.out
+++ b/ops/op2/test_cases/async/async_cppgc.out
@@ -162,10 +162,9 @@ const fn op_use_cppgc_object() -> ::deno_core::_ops::OpDecl {
             };
             let result = {
                 let arg0 = args.get(1usize as i32);
-                let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<
+                let Some(mut arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
                     Wrap,
-                >(&mut scope, arg0);
-                if handle_.borrow().is_none() {
+                >(&mut scope, arg0) else {
                     let msg = deno_core::v8::String::new_from_one_byte(
                             &mut scope,
                             "expected Wrap".as_bytes(),
@@ -175,12 +174,10 @@ const fn op_use_cppgc_object() -> ::deno_core::_ops::OpDecl {
                     let exc = deno_core::v8::Exception::type_error(&mut scope, msg);
                     scope.throw_exception(exc);
                     return 1;
-                }
-                let mut arg0 = deno_core::v8::cppgc::Persistent::empty();
-                arg0.set(&handle_);
-                drop(handle_);
+                };
+                arg0.root();
                 async move {
-                    let arg0 = arg0.borrow().unwrap();
+                    let arg0 = &*arg0;
                     Self::call(arg0).await
                 }
             };
@@ -285,28 +282,25 @@ const fn op_use_optional_cppgc_object() -> ::deno_core::_ops::OpDecl {
             let result = {
                 let arg0 = args.get(1usize as i32);
                 let arg0 = if arg0.is_null_or_undefined() {
-                    deno_core::v8::cppgc::Persistent::empty()
+                    None
+                } else if let Some(mut arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
+                    Wrap,
+                >(&mut scope, arg0) {
+                    arg0.root();
+                    Some(arg0)
                 } else {
-                    let handle = deno_core::_ops::try_unwrap_cppgc_object::<
-                        Wrap,
-                    >(&mut scope, arg0);
-                    if handle.borrow().is_none() {
-                        let msg = deno_core::v8::String::new_from_one_byte(
-                                &mut scope,
-                                "expected Wrap".as_bytes(),
-                                deno_core::v8::NewStringType::Normal,
-                            )
-                            .unwrap();
-                        let exc = deno_core::v8::Exception::type_error(&mut scope, msg);
-                        scope.throw_exception(exc);
-                        return 1;
-                    }
-                    let mut persistent = deno_core::v8::cppgc::Persistent::empty();
-                    persistent.set(&handle);
-                    persistent
+                    let msg = deno_core::v8::String::new_from_one_byte(
+                            &mut scope,
+                            "expected Wrap".as_bytes(),
+                            deno_core::v8::NewStringType::Normal,
+                        )
+                        .unwrap();
+                    let exc = deno_core::v8::Exception::type_error(&mut scope, msg);
+                    scope.throw_exception(exc);
+                    return 1;
                 };
                 async move {
-                    let arg0 = arg0.borrow();
+                    let arg0 = arg0.as_deref();
                     Self::call(arg0).await
                 }
             };
diff --git a/ops/op2/test_cases/sync/cppgc_resource.out b/ops/op2/test_cases/sync/cppgc_resource.out
index 679411c..f4d1b52 100644
--- a/ops/op2/test_cases/sync/cppgc_resource.out
+++ b/ops/op2/test_cases/sync/cppgc_resource.out
@@ -91,13 +91,13 @@ const fn op_cppgc_object() -> ::deno_core::_ops::OpDecl {
                 deno_core::v8::CallbackScope::new(this)
             };
             let result = {
-                let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<
+                let Some(arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
                     Wrap,
-                >(&mut scope, arg0);
-                let Some(arg0) = handle_.borrow() else {
+                >(&mut scope, arg0) else {
                     fast_api_callback_options.fallback = true;
                     return unsafe { std::mem::zeroed() };
                 };
+                let arg0 = &*arg0;
                 Self::call(arg0)
             };
             result as _
@@ -117,10 +117,9 @@ const fn op_cppgc_object() -> ::deno_core::_ops::OpDecl {
             );
             let result = {
                 let arg0 = args.get(0usize as i32);
-                let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<
+                let Some(arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
                     Wrap,
-                >(&mut scope, arg0);
-                let Some(arg0) = handle_.borrow() else {
+                >(&mut scope, arg0) else {
                     let msg = deno_core::v8::String::new_from_one_byte(
                             &mut scope,
                             "expected Wrap".as_bytes(),
@@ -131,6 +130,7 @@ const fn op_cppgc_object() -> ::deno_core::_ops::OpDecl {
                     scope.throw_exception(exc);
                     return 1;
                 };
+                let arg0 = &*arg0;
                 Self::call(arg0)
             };
             deno_core::_ops::RustToV8RetVal::to_v8_rv(result, &mut rv);
@@ -269,24 +269,17 @@ const fn op_option_cppgc_object() -> ::deno_core::_ops::OpDecl {
                 deno_core::v8::CallbackScope::new(this)
             };
             let result = {
-                let mut handle_ = deno_core::v8::cppgc::Member::empty();
                 let arg0 = if arg0.is_null_or_undefined() {
                     None
+                } else if let Some(arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
+                    Wrap,
+                >(&mut scope, arg0) {
+                    Some(arg0)
                 } else {
-                    handle_
-                        .set(
-                            &deno_core::_ops::try_unwrap_cppgc_object::<
-                                Wrap,
-                            >(&mut scope, arg0),
-                        );
-                    match handle_.borrow() {
-                        Some(r) => Some(r),
-                        None => {
-                            fast_api_callback_options.fallback = true;
-                            return unsafe { std::mem::zeroed() };
-                        }
-                    }
+                    fast_api_callback_options.fallback = true;
+                    return unsafe { std::mem::zeroed() };
                 };
+                let arg0 = arg0.as_deref();
                 Self::call(arg0)
             };
             result as _
@@ -306,34 +299,24 @@ const fn op_option_cppgc_object() -> ::deno_core::_ops::OpDecl {
             );
             let result = {
                 let arg0 = args.get(0usize as i32);
-                let mut handle_ = deno_core::v8::cppgc::Member::empty();
                 let arg0 = if arg0.is_null_or_undefined() {
                     None
+                } else if let Some(arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
+                    Wrap,
+                >(&mut scope, arg0) {
+                    Some(arg0)
                 } else {
-                    handle_
-                        .set(
-                            &deno_core::_ops::try_unwrap_cppgc_object::<
-                                Wrap,
-                            >(&mut scope, arg0),
-                        );
-                    match handle_.borrow() {
-                        Some(r) => Some(r),
-                        None => {
-                            let msg = deno_core::v8::String::new_from_one_byte(
-                                    &mut scope,
-                                    "expected Wrap".as_bytes(),
-                                    deno_core::v8::NewStringType::Normal,
-                                )
-                                .unwrap();
-                            let exc = deno_core::v8::Exception::type_error(
-                                &mut scope,
-                                msg,
-                            );
-                            scope.throw_exception(exc);
-                            return 1;
-                        }
-                    }
+                    let msg = deno_core::v8::String::new_from_one_byte(
+                            &mut scope,
+                            "expected Wrap".as_bytes(),
+                            deno_core::v8::NewStringType::Normal,
+                        )
+                        .unwrap();
+                    let exc = deno_core::v8::Exception::type_error(&mut scope, msg);
+                    scope.throw_exception(exc);
+                    return 1;
                 };
+                let arg0 = arg0.as_deref();
                 Self::call(arg0)
             };
             deno_core::_ops::RustToV8RetVal::to_v8_rv(result, &mut rv);
@@ -562,13 +545,13 @@ const fn op_use_cppgc_object() -> ::deno_core::_ops::OpDecl {
                 deno_core::v8::CallbackScope::new(this)
             };
             let result = {
-                let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<
+                let Some(arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
                     Wrap,
-                >(&mut scope, arg0);
-                let Some(arg0) = handle_.borrow() else {
+                >(&mut scope, arg0) else {
                     fast_api_callback_options.fallback = true;
                     return unsafe { std::mem::zeroed() };
                 };
+                let arg0 = &*arg0;
                 Self::call(arg0)
             };
             result as _
@@ -588,10 +571,9 @@ const fn op_use_cppgc_object() -> ::deno_core::_ops::OpDecl {
             );
             let result = {
                 let arg0 = args.get(0usize as i32);
-                let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<
+                let Some(arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
                     Wrap,
-                >(&mut scope, arg0);
-                let Some(arg0) = handle_.borrow() else {
+                >(&mut scope, arg0) else {
                     let msg = deno_core::v8::String::new_from_one_byte(
                             &mut scope,
                             "expected Wrap".as_bytes(),
@@ -602,6 +584,7 @@ const fn op_use_cppgc_object() -> ::deno_core::_ops::OpDecl {
                     scope.throw_exception(exc);
                     return 1;
                 };
+                let arg0 = &*arg0;
                 Self::call(arg0)
             };
             deno_core::_ops::RustToV8RetVal::to_v8_rv(result, &mut rv);
@@ -833,13 +816,13 @@ const fn op_use_cppgc_object_option() -> ::deno_core::_ops::OpDecl {
                 deno_core::v8::CallbackScope::new(this)
             };
             let result = {
-                let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<
+                let Some(arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
                     Wrap,
-                >(&mut scope, arg0);
-                let Some(arg0) = handle_.borrow() else {
+                >(&mut scope, arg0) else {
                     fast_api_callback_options.fallback = true;
                     return unsafe { std::mem::zeroed() };
                 };
+                let arg0 = &*arg0;
                 Self::call(arg0)
             };
             result as _
@@ -859,10 +842,9 @@ const fn op_use_cppgc_object_option() -> ::deno_core::_ops::OpDecl {
             );
             let result = {
                 let arg0 = args.get(0usize as i32);
-                let handle_ = deno_core::_ops::try_unwrap_cppgc_object::<
+                let Some(arg0) = deno_core::_ops::try_unwrap_cppgc_object::<
                     Wrap,
-                >(&mut scope, arg0);
-                let Some(arg0) = handle_.borrow() else {
+                >(&mut scope, arg0) else {
                     let msg = deno_core::v8::String::new_from_one_byte(
                             &mut scope,
                             "expected Wrap".as_bytes(),
@@ -873,6 +855,7 @@ const fn op_use_cppgc_object_option() -> ::deno_core::_ops::OpDecl {
                     scope.throw_exception(exc);
                     return 1;
                 };
+                let arg0 = &*arg0;
                 Self::call(arg0)
             };
             deno_core::_ops::RustToV8RetVal::to_v8_rv(result, &mut rv);
diff --git a/ops/op2/test_cases_fail/lifetimes.stderr b/ops/op2/test_cases_fail/lifetimes.stderr
index f20ff7f..70f3e67 100644
--- a/ops/op2/test_cases_fail/lifetimes.stderr
+++ b/ops/op2/test_cases_fail/lifetimes.stderr
@@ -17,15 +17,15 @@ error: unused import: `std::future::Future`
 6 | use std::future::Future;
   |     ^^^^^^^^^^^^^^^^^^^
 
-error[E0597]: `handle_` does not live long enough
+error[E0597]: `arg0` does not live long enough
   --> ../op2/test_cases_fail/lifetimes.rs:12:1
    |
 12 | #[op2(fast)]
    | ^^^^^^^^^^^-
    | |          |
-   | |          `handle_` dropped here while still borrowed
+   | |          `arg0` dropped here while still borrowed
    | borrowed value does not live long enough
-   | argument requires that `handle_` is borrowed for `'static`
+   | argument requires that `arg0` is borrowed for `'static`
    |
    = note: this error originates in the attribute macro `op2` (in Nightly builds, run with -Z macro-backtrace for more info)