diff --git a/gen/src/write.rs b/gen/src/write.rs index 5dd5cc29f..7a1765dc3 100644 --- a/gen/src/write.rs +++ b/gen/src/write.rs @@ -233,7 +233,9 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) { Type::SliceRef(_) => out.builtin.rust_slice = true, Type::Array(_) => out.include.array = true, Type::Ref(_) | Type::Void(_) | Type::Ptr(_) => {} - Type::Future(_) | Type::Own(_) => out.include.kj_rs = true, + Type::Future(_) | Type::Own(_) | Type::KjRc(_) | Type::KjArc(_) => { + out.include.kj_rs = true; + } } } } @@ -1253,6 +1255,16 @@ fn write_type(out: &mut OutFile, ty: &Type) { write_type(out, &ptr.inner); write!(out, ">"); } + Type::KjRc(ptr) => { + write!(out, "::kj::Rc<"); + write_type(out, &ptr.inner); + write!(out, ">"); + } + Type::KjArc(ptr) => { + write!(out, "::kj::Arc<"); + write_type(out, &ptr.inner); + write!(out, ">"); + } Type::SharedPtr(ptr) => { write!(out, "::std::shared_ptr<"); write_type(out, &ptr.inner); @@ -1354,6 +1366,8 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) { | Type::RustBox(_) | Type::UniquePtr(_) | Type::Own(_) + | Type::KjRc(_) + | Type::KjArc(_) | Type::SharedPtr(_) | Type::WeakPtr(_) | Type::Str(_) @@ -1431,6 +1445,8 @@ fn write_generic_instantiations(out: &mut OutFile) { ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident), ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident), ImplKey::Own(ident) => write_kj_own(out, ident), + ImplKey::KjRc(ident) => write_kj_rc(out, ident), + ImplKey::KjArc(ident) => write_kj_arc(out, ident), ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident), ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident), ImplKey::CxxVector(ident) => write_cxx_vector(out, ident), @@ -1669,6 +1685,106 @@ fn write_kj_own(out: &mut OutFile, key: NamedImplKey) { ); } +// Writes static assertion that we do not use an Own with a static disposer +fn write_kj_rc(out: &mut OutFile, key: NamedImplKey) { + let ident = key.rust; + let resolve = out.types.resolve(ident); + let inner = resolve.name.to_fully_qualified(); + let instance = resolve.name.to_symbol(); + + out.include.utility = true; + out.include.kj_rs = true; + + // Static disposers are not supported, only Owns containing 2 pointers are allowed + writeln!( + out, + "static_assert(sizeof(::kj::Rc<{}>) == 2 * sizeof(void *), \"Static disposers for Own are not supported in workerd-cxx\");", + inner, + ); + writeln!( + out, + "static_assert(alignof(::kj::Rc<{}>) == sizeof(void *), \"Static disposers for Own are not supported in workerd-cxx\");", + inner, + ); + writeln!( + out, + "static_assert(::std::is_base_of<::kj::Refcounted, {}>::value, \"Value must inherit kj::Refcounted\");", + inner + ); + + begin_function_definition(out); + writeln!( + out, + "void cxxbridge1$kj_rs$rc${}$is_shared(::kj::Refcounted *ptr, bool *ret) noexcept {{", + instance, + ); + writeln!(out, " *ret = ptr->isShared();"); + writeln!(out, "}}"); + + begin_function_definition(out); + writeln!( + out, + "void cxxbridge1$kj_rs$rc${}$add_ref(::kj::Rc<{}> *refcounted, ::kj::Rc<{}> *ptr) noexcept {{", + instance, inner, inner + ); + writeln!( + out, + " ::new (ptr) ::kj::Rc<{}>(refcounted->addRef());", + inner + ); + writeln!(out, "}}"); +} + +// Writes static assertion that we do not use an Own with a static disposer +fn write_kj_arc(out: &mut OutFile, key: NamedImplKey) { + let ident = key.rust; + let resolve = out.types.resolve(ident); + let inner = resolve.name.to_fully_qualified(); + let instance = resolve.name.to_symbol(); + + out.include.utility = true; + out.include.kj_rs = true; + + // Static disposers are not supported, only Owns containing 2 pointers are allowed + writeln!( + out, + "static_assert(sizeof(::kj::Arc<{}>) == 2 * sizeof(void *), \"Static disposers for Own are not supported in workerd-cxx\");", + inner, + ); + writeln!( + out, + "static_assert(alignof(::kj::Arc<{}>) == sizeof(void *), \"Static disposers for Own are not supported in workerd-cxx\");", + inner, + ); + writeln!( + out, + "static_assert(::std::is_base_of<::kj::AtomicRefcounted, {}>::value, \"Value must inherit kj::AtomicRefcounted\");", + inner + ); + + begin_function_definition(out); + writeln!( + out, + "void cxxbridge1$kj_rs$arc${}$is_shared(::kj::AtomicRefcounted *ptr, bool *ret) noexcept {{", + instance, + ); + writeln!(out, " *ret = ptr->isShared();"); + writeln!(out, "}}"); + + begin_function_definition(out); + writeln!( + out, + "void cxxbridge1$kj_rs$arc${}$add_ref(::kj::Arc<{}> *refcounted, ::kj::Arc<{}> *ptr) noexcept {{", + instance, inner, inner + ); + writeln!( + out, + " ::new (ptr) ::kj::Arc<{}>(refcounted->addRef());", + inner + ); + writeln!(out, "}}"); +} + fn write_unique_ptr(out: &mut OutFile, key: NamedImplKey) { let ty = UniquePtr::Ident(key.rust); write_unique_ptr_common(out, ty); diff --git a/kj-rs/lib.rs b/kj-rs/lib.rs index e32d631b6..4c4b12a46 100644 --- a/kj-rs/lib.rs +++ b/kj-rs/lib.rs @@ -15,11 +15,13 @@ mod awaiter; mod future; mod own; mod promise; +mod refcount; mod waker; pub mod repr { pub use crate::future::repr::*; pub use crate::own::repr::*; + pub use crate::refcount::repr::*; } pub type Result = std::io::Result; diff --git a/kj-rs/own.rs b/kj-rs/own.rs index 24fdd6f2e..18e3213eb 100644 --- a/kj-rs/own.rs +++ b/kj-rs/own.rs @@ -21,7 +21,7 @@ pub mod repr { /// - Currently, it is runtime asserted in the bridge macro that no null Own can be passed /// to Rust #[repr(C)] - pub struct Own { + pub struct Own { disposer: *const c_void, ptr: NonNull, } @@ -62,7 +62,7 @@ pub mod repr { /// Returns a raw const pointer to the object owned by this [`Own`] #[must_use] pub fn as_ptr(&self) -> *const T { - self.ptr.as_ptr().cast() + self.ptr.as_ptr().cast_const() } } @@ -153,7 +153,7 @@ pub mod repr { } } - impl Drop for Own { + impl Drop for Own { fn drop(&mut self) { unsafe extern "C" { #[link_name = "cxxbridge$kjrs$own$drop"] diff --git a/kj-rs/refcount.rs b/kj-rs/refcount.rs new file mode 100644 index 000000000..9b37b0446 --- /dev/null +++ b/kj-rs/refcount.rs @@ -0,0 +1,102 @@ +//! Module for both [`KjRc`] and [`KjArc`], since they're nearly identical types + +pub mod repr { + use crate::Own; + use std::ops::Deref; + + /// # Safety + /// Should only be automatically implemented by the bridge macro + pub unsafe trait Refcounted { + fn is_shared(&self) -> bool; + fn add_ref(rc: &KjRc) -> KjRc; + } + /// # Safety + /// Should only be automatically implemented by the bridge macro + pub unsafe trait AtomicRefcounted { + fn is_shared(&self) -> bool; + fn add_ref(arc: &KjArc) -> KjArc; + } + + #[repr(C)] + /// Bindings to the kj type `kj::Rc`. Represents and owned and reference counted type, + /// like Rust's [`std::rc::Rc`]. + pub struct KjRc { + own: Own, + } + + #[repr(C)] + /// Bindings to the kj type `kj::Arc`. Represents and owned and atomically reference + /// counted type, like Rust's [`std::sync::Arc`]. + pub struct KjArc { + own: Own, + } + + unsafe impl Send for KjArc where T: Send {} + unsafe impl Sync for KjArc where T: Sync {} + + impl KjRc { + #[must_use] + pub fn get(&self) -> *const T { + self.own.as_ptr() + } + + // The return value here represents exclusive access to the internal `Own`. + // This allows for exclusive mutation of the inner value. + pub fn get_mut(&mut self) -> Option<&mut Own> { + if self.own.is_shared() { + None + } else { + Some(&mut self.own) + } + } + } + + impl KjArc { + #[must_use] + pub fn get(&self) -> *const T { + self.own.as_ptr() + } + + // The return value here represents exclusive access to the internal `Own`. + // This allows for exclusive mutation of the inner value. + pub fn get_mut(&mut self) -> Option<&mut Own> { + if self.own.is_shared() { + None + } else { + Some(&mut self.own) + } + } + } + + impl Deref for KjRc { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.own + } + } + + impl Deref for KjArc { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.own + } + } + + /// Using clone to create another count, like how Rust does it. + impl Clone for KjRc { + fn clone(&self) -> Self { + T::add_ref(self) + } + } + + impl Clone for KjArc { + fn clone(&self) -> Self { + T::add_ref(self) + } + } + + // No `Drop` needs to be implemented for `KjRc` or `KjArc`, because the + // internal `Own` `Drop` is sufficient. +} diff --git a/kj-rs/tests/BUILD.bazel b/kj-rs/tests/BUILD.bazel index 7636d884d..c013ed58a 100644 --- a/kj-rs/tests/BUILD.bazel +++ b/kj-rs/tests/BUILD.bazel @@ -45,7 +45,8 @@ rust_cxx_bridge( src = "lib.rs", hdrs = [ "test-promises.h", - "test-own.h" + "test-own.h", + "test-refcount.h" ], include_prefix = "kj-rs-demo", deps = [ @@ -57,7 +58,8 @@ cc_library( name = "test-promises", srcs = [ "test-promises.c++", - "test-own.c++" + "test-own.c++", + "test-refcount.c++" ], linkstatic = select({ "@platforms//os:windows": True, diff --git a/kj-rs/tests/lib.rs b/kj-rs/tests/lib.rs index aaba6f18f..26a0ff6e8 100644 --- a/kj-rs/tests/lib.rs +++ b/kj-rs/tests/lib.rs @@ -8,6 +8,7 @@ mod test_futures; mod test_own; +mod test_refcount; use test_futures::{ new_awaiting_future_i32, new_error_handling_future_void_infallible, new_errored_future_void, @@ -72,6 +73,36 @@ mod ffi { fn rust_take_own_driver(); } + unsafe extern "C++" { + include!("kj-rs-demo/test-refcount.h"); + + type OpaqueRefcountedClass; + + #[allow(dead_code)] + fn get_rc() -> KjRc; + #[allow(dead_code)] + #[cxx_name = "getData"] + fn get_data(&self) -> u64; + #[allow(dead_code)] + #[cxx_name = "setData"] + fn set_data(self: Pin<&mut OpaqueRefcountedClass>, data: u64); + } + + unsafe extern "C++" { + include!("kj-rs-demo/test-refcount.h"); + + type OpaqueAtomicRefcountedClass; + + #[allow(dead_code)] + fn get_arc() -> KjArc; + + #[allow(dead_code)] + #[cxx_name = "getData"] + fn get_data(&self) -> u64; + #[allow(dead_code)] + #[cxx_name = "setData"] + fn set_data(self: Pin<&mut OpaqueAtomicRefcountedClass>, data: u64); + } // Helper function to test moving `Own` to C++ extern "Rust" { fn modify_own_return(cpp_own: Own) -> Own; @@ -122,6 +153,9 @@ mod ffi { } } +unsafe impl Send for ffi::OpaqueAtomicRefcountedClass {} +unsafe impl Sync for ffi::OpaqueAtomicRefcountedClass {} + pub fn modify_own_return(mut own: Own) -> Own { own.pin_mut().set_data(72); own diff --git a/kj-rs/tests/test-refcount.c++ b/kj-rs/tests/test-refcount.c++ new file mode 100644 index 000000000..4b2a3162d --- /dev/null +++ b/kj-rs/tests/test-refcount.c++ @@ -0,0 +1,11 @@ +#include "test-refcount.h" + +namespace kj_rs_demo { +kj::Rc get_rc() { + return kj::rc(15); +} + +kj::Arc get_arc() { + return kj::arc(16); +} +} diff --git a/kj-rs/tests/test-refcount.h b/kj-rs/tests/test-refcount.h new file mode 100644 index 000000000..79e1be7a5 --- /dev/null +++ b/kj-rs/tests/test-refcount.h @@ -0,0 +1,42 @@ +#pragma once + +#include "kj/refcount.h" + +#include + +namespace kj_rs_demo { + +class OpaqueRefcountedClass: public kj::Refcounted { + public: + OpaqueRefcountedClass(uint64_t data): data(data) {} + ~OpaqueRefcountedClass() {} + uint64_t getData() const { + return this->data; + } + void setData(uint64_t val) { + this->data = val; + } + + private: + uint64_t data; +}; + +class OpaqueAtomicRefcountedClass: public kj::AtomicRefcounted { + public: + OpaqueAtomicRefcountedClass(uint64_t data): data(data) {} + ~OpaqueAtomicRefcountedClass() {} + uint64_t getData() const { + return this->data; + } + void setData(uint64_t val) { + this->data = val; + } + + private: + uint64_t data; +}; + +kj::Rc get_rc(); +kj::Arc get_arc(); + +} // namespace kj_rs_demo diff --git a/kj-rs/tests/test_futures.rs b/kj-rs/tests/test_futures.rs index b7b5a9628..9040ab072 100644 --- a/kj-rs/tests/test_futures.rs +++ b/kj-rs/tests/test_futures.rs @@ -149,10 +149,7 @@ pub async fn new_layered_ready_future_void() -> Result<()> { } // From example at https://doc.rust-lang.org/std/future/fn.poll_fn.html#capturing-a-pinned-state -async fn naive_select( - a: impl Future, - b: impl Future, -) -> T { +async fn naive_select(a: impl Future, b: impl Future) -> T { let (mut a, mut b) = (pin!(a), pin!(b)); future::poll_fn(move |cx| { if let Poll::Ready(r) = a.as_mut().poll(cx) { diff --git a/kj-rs/tests/test_refcount.rs b/kj-rs/tests/test_refcount.rs new file mode 100644 index 000000000..cb3054049 --- /dev/null +++ b/kj-rs/tests/test_refcount.rs @@ -0,0 +1,59 @@ +#[cfg(test)] +pub mod tests { + use kj_rs::repr::{AtomicRefcounted, Refcounted}; + + use crate::ffi; + + #[test] + fn test_rc() { + let rc = ffi::get_rc(); + assert_eq!(rc.get_data(), 15); + let rc_clone = rc.clone(); + assert_eq!(rc_clone.get_data(), 15); + + assert!(rc.is_shared()); + std::mem::drop(rc_clone); + assert!(!rc.is_shared()); + } + + #[test] + fn test_arc() { + let arc = ffi::get_arc(); + assert_eq!(arc.get_data(), 16); + let arc_clone = arc.clone(); + assert_eq!(arc_clone.get_data(), 16); + + assert!(arc.is_shared()); + std::mem::drop(arc_clone); + assert!(!arc.is_shared()); + } + + #[test] + fn test_arc_thread() { + let mut arc = ffi::get_arc(); + + std::thread::scope(|s| { + let mut c = arc.clone(); + assert!(c.get_mut().is_none()); + + s.spawn(|| { + assert_eq!(arc.clone().get_data(), 16); + }); + + s.spawn(|| { + let a = arc.clone(); + assert!(a.is_shared()); + }); + }); + + { + let mut cloned = arc.clone(); + assert!(cloned.get_mut().is_none()); + } + + let mut_ref = arc.get_mut(); + assert!(mut_ref.is_some()); + mut_ref.unwrap().pin_mut().set_data(35643); + assert_eq!(arc.get_data(), 35643); + } +} diff --git a/macro/src/expand.rs b/macro/src/expand.rs index 7a3d2428e..38c286c23 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -128,6 +128,8 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) ImplKey::CxxVector(ident) => { expanded.extend(expand_cxx_vector(ident, explicit_impl, types)); } + ImplKey::KjRc(ident) => expanded.extend(expand_kj_rc(ident, types, explicit_impl)), + ImplKey::KjArc(ident) => expanded.extend(expand_kj_arc(ident, types, explicit_impl)), // We do not need to generate code on the rust side for [`kj_rs::Own`] ImplKey::Own(_) => (), } @@ -1726,6 +1728,86 @@ fn expand_shared_ptr( } } +fn expand_kj_rc(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream { + let ident = key.rust; + let resolve = types.resolve(ident); + let prefix = format!("cxxbridge1$kj_rs$rc${}$", resolve.name.to_symbol()); + let is_shared = format!("{}is_shared", prefix); + let add_ref = format!("{}add_ref", prefix); + + let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span); + let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join()); + let unsafe_token = format_ident!("unsafe", span = begin_span); + + quote_spanned! {end_span=> + #[automatically_derived] + #unsafe_token impl ::kj_rs::repr::Refcounted for #ident { + fn is_shared(&self) -> bool { + #UnsafeExtern extern "C" { + #[link_name = #is_shared] + fn __is_shared(ptr: *const ::cxx::core::ffi::c_void, ret: *mut bool); + } + let mut ret = ::cxx::core::mem::MaybeUninit::uninit(); + unsafe { + __is_shared(self as *const #ident as *const ::cxx::core::ffi::c_void, ret.as_mut_ptr()); + ret.assume_init() + } + } + fn add_ref(rc: &::kj_rs::repr::KjRc<#ident>) -> ::kj_rs::repr::KjRc<#ident> { + #UnsafeExtern extern "C" { + #[link_name = #add_ref] + fn __add_ref(refcounted: *const ::kj_rs::repr::KjRc<#ident>, ptr: *const ::kj_rs::repr::KjRc<#ident>); + } + let mut ret = ::cxx::core::mem::MaybeUninit::uninit(); + unsafe { + __add_ref(rc as *const ::kj_rs::repr::KjRc<#ident>, ret.as_mut_ptr()); + ret.assume_init() + } + } + } + } +} + +fn expand_kj_arc(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream { + let ident = key.rust; + let resolve = types.resolve(ident); + let prefix = format!("cxxbridge1$kj_rs$arc${}$", resolve.name.to_symbol()); + let is_shared = format!("{}is_shared", prefix); + let add_ref = format!("{}add_ref", prefix); + + let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span); + let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join()); + let unsafe_token = format_ident!("unsafe", span = begin_span); + + quote_spanned! {end_span=> + #[automatically_derived] + #unsafe_token impl ::kj_rs::repr::AtomicRefcounted for #ident { + fn is_shared(&self) -> bool { + #UnsafeExtern extern "C" { + #[link_name = #is_shared] + fn __is_shared(ptr: *const ::cxx::core::ffi::c_void, ret: *mut bool); + } + let mut ret = ::cxx::core::mem::MaybeUninit::uninit(); + unsafe { + __is_shared(self as *const #ident as *const ::cxx::core::ffi::c_void, ret.as_mut_ptr()); + ret.assume_init() + } + } + fn add_ref(arc: &::kj_rs::repr::KjArc<#ident>) -> ::kj_rs::repr::KjArc<#ident> { + #UnsafeExtern extern "C" { + #[link_name = #add_ref] + fn __add_ref(refcounted: *const ::kj_rs::repr::KjArc<#ident>, ptr: *const ::kj_rs::repr::KjArc<#ident>); + } + let mut ret = ::cxx::core::mem::MaybeUninit::uninit(); + unsafe { + __add_ref(arc as *const ::kj_rs::repr::KjArc<#ident>, ret.as_mut_ptr()); + ret.assume_init() + } + } + } + } +} + fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream { let ident = key.rust; let name = ident.to_string(); diff --git a/syntax/check.rs b/syntax/check.rs index 8d2ff35be..b28b4a6b3 100644 --- a/syntax/check.rs +++ b/syntax/check.rs @@ -73,6 +73,8 @@ fn check_type(cx: &mut Check, ty: &Type) { Type::RustVec(ty) => check_type_rust_vec(cx, ty), Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr), Type::Own(ptr) => check_type_kj_own(cx, ptr), + Type::KjRc(ptr) => check_type_kj_rc(cx, ptr), + Type::KjArc(ptr) => check_type_kj_arc(cx, ptr), Type::SharedPtr(ptr) => check_type_shared_ptr(cx, ptr), Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr), Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr), @@ -186,6 +188,41 @@ fn check_type_kj_own(cx: &mut Check, ptr: &Ty1) { cx.error(ptr, "unsupported kj::Own target type"); } +fn check_type_kj_rc(cx: &mut Check, ptr: &Ty1) { + if let Type::Ident(ident) = &ptr.inner { + if cx.types.rust.contains(&ident.rust) { + cx.error( + ptr, + "kj::Rc of a Rust type is not supported yet, use a Box instead", + ); + return; + } + + if Atom::from(&ident.rust).is_none() { + return; + } + } + + cx.error(ptr, "unsupported KjRc target type"); +} + +fn check_type_kj_arc(cx: &mut Check, ptr: &Ty1) { + if let Type::Ident(ident) = &ptr.inner { + if cx.types.rust.contains(&ident.rust) { + cx.error( + ptr, + "kj::Arc of a Rust type is not supported yet, use a Box instead", + ); + return; + } + + if Atom::from(&ident.rust).is_none() { + return; + } + } + + cx.error(ptr, "unsupported KjArc target type"); +} fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) { if let Type::Ident(ident) = &ptr.inner { @@ -708,6 +745,8 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool { | Type::RustVec(_) | Type::UniquePtr(_) | Type::Own(_) + | Type::KjRc(_) + | Type::KjArc(_) | Type::SharedPtr(_) | Type::WeakPtr(_) | Type::Ref(_) @@ -784,6 +823,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String { Type::RustVec(_) => "Vec".to_owned(), Type::UniquePtr(_) => "unique_ptr".to_owned(), Type::Own(_) => "kj::Own".to_owned(), + Type::KjRc(_) => "kj::Rc".to_owned(), + Type::KjArc(_) => "kj::Arc".to_owned(), Type::SharedPtr(_) => "shared_ptr".to_owned(), Type::WeakPtr(_) => "weak_ptr".to_owned(), Type::Ref(_) => "reference".to_owned(), diff --git a/syntax/impls.rs b/syntax/impls.rs index 8ce98759e..53aeeb1c7 100644 --- a/syntax/impls.rs +++ b/syntax/impls.rs @@ -48,6 +48,8 @@ impl Hash for Type { Type::RustBox(t) => t.hash(state), Type::UniquePtr(t) => t.hash(state), Type::Own(t) => t.hash(state), + Type::KjRc(t) => t.hash(state), + Type::KjArc(t) => t.hash(state), Type::SharedPtr(t) => t.hash(state), Type::WeakPtr(t) => t.hash(state), Type::Ref(t) => t.hash(state), diff --git a/syntax/improper.rs b/syntax/improper.rs index a99e97fa6..aa70c5d67 100644 --- a/syntax/improper.rs +++ b/syntax/improper.rs @@ -34,7 +34,9 @@ impl<'a> Types<'a> { Type::Ref(ty) => self.determine_improper_ctype(&ty.inner), Type::Ptr(ty) => self.determine_improper_ctype(&ty.inner), Type::Array(ty) => self.determine_improper_ctype(&ty.inner), - Type::Future(_) | Type::Own(_) => todo!("file a workerd-cxx ticket"), + Type::Future(_) | Type::Own(_) | Type::KjRc(_) | Type::KjArc(_) => { + todo!("file a workerd-cxx ticket") + } } } } diff --git a/syntax/instantiate.rs b/syntax/instantiate.rs index fc568381d..dce34cf53 100644 --- a/syntax/instantiate.rs +++ b/syntax/instantiate.rs @@ -9,6 +9,8 @@ pub enum ImplKey<'a> { RustVec(NamedImplKey<'a>), UniquePtr(NamedImplKey<'a>), Own(NamedImplKey<'a>), + KjRc(NamedImplKey<'a>), + KjArc(NamedImplKey<'a>), SharedPtr(NamedImplKey<'a>), WeakPtr(NamedImplKey<'a>), CxxVector(NamedImplKey<'a>), @@ -45,6 +47,14 @@ impl Type { if let Type::Ident(ident) = &ty.inner { return Some(ImplKey::Own(NamedImplKey::new(ty, ident))); } + } else if let Type::KjRc(ty) = self { + if let Type::Ident(ident) = &ty.inner { + return Some(ImplKey::KjRc(NamedImplKey::new(ty, ident))); + } + } else if let Type::KjArc(ty) = self { + if let Type::Ident(ident) = &ty.inner { + return Some(ImplKey::KjArc(NamedImplKey::new(ty, ident))); + } } else if let Type::SharedPtr(ty) = self { if let Type::Ident(ident) = &ty.inner { return Some(ImplKey::SharedPtr(NamedImplKey::new(ty, ident))); diff --git a/syntax/mod.rs b/syntax/mod.rs index 9b93cb3cd..64b443dfe 100644 --- a/syntax/mod.rs +++ b/syntax/mod.rs @@ -293,6 +293,8 @@ pub enum Type { RustVec(Box), UniquePtr(Box), Own(Box), + KjRc(Box), + KjArc(Box), SharedPtr(Box), WeakPtr(Box), Ref(Box), diff --git a/syntax/parse.rs b/syntax/parse.rs index 6576ccd65..4b6ffc703 100644 --- a/syntax/parse.rs +++ b/syntax/parse.rs @@ -1058,6 +1058,8 @@ fn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result { | Type::RustVec(ty) | Type::UniquePtr(ty) | Type::Own(ty) + | Type::KjRc(ty) + | Type::KjArc(ty) | Type::SharedPtr(ty) | Type::WeakPtr(ty) | Type::CxxVector(ty) => match &ty.inner { @@ -1236,6 +1238,26 @@ fn parse_type_path(ty: &TypePath) -> Result { rangle: generic.gt_token, }))); } + } else if ident == "KjRc" && generic.args.len() == 1 { + if let GenericArgument::Type(arg) = &generic.args[0] { + let inner = parse_type(arg)?; + return Ok(Type::KjRc(Box::new(Ty1 { + name: ident, + langle: generic.lt_token, + inner, + rangle: generic.gt_token, + }))); + } + } else if ident == "KjArc" && generic.args.len() == 1 { + if let GenericArgument::Type(arg) = &generic.args[0] { + let inner = parse_type(arg)?; + return Ok(Type::KjArc(Box::new(Ty1 { + name: ident, + langle: generic.lt_token, + inner, + rangle: generic.gt_token, + }))); + } } else if ident == "SharedPtr" && generic.args.len() == 1 { if let GenericArgument::Type(arg) = &generic.args[0] { let inner = parse_type(arg)?; @@ -1487,6 +1509,8 @@ fn has_references_without_lifetime(ty: &Type) -> bool { | Type::RustVec(t) | Type::UniquePtr(t) | Type::Own(t) + | Type::KjRc(t) + | Type::KjArc(t) | Type::SharedPtr(t) | Type::WeakPtr(t) | Type::CxxVector(t) => has_references_without_lifetime(&t.inner), diff --git a/syntax/pod.rs b/syntax/pod.rs index fe56957ff..40a26a041 100644 --- a/syntax/pod.rs +++ b/syntax/pod.rs @@ -26,6 +26,8 @@ impl<'a> Types<'a> { | Type::RustVec(_) | Type::UniquePtr(_) | Type::Own(_) + | Type::KjRc(_) + | Type::KjArc(_) | Type::SharedPtr(_) | Type::WeakPtr(_) | Type::CxxVector(_) diff --git a/syntax/tokens.rs b/syntax/tokens.rs index 8398ca6bf..91ead3efe 100644 --- a/syntax/tokens.rs +++ b/syntax/tokens.rs @@ -27,6 +27,8 @@ impl ToTokens for Type { Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Own(ty) + | Type::KjRc(ty) + | Type::KjArc(ty) | Type::SharedPtr(ty) | Type::WeakPtr(ty) | Type::CxxVector(ty) @@ -75,6 +77,12 @@ impl ToTokens for Ty1 { "Own" => { tokens.extend(quote_spanned!(span => ::kj_rs::repr::)); } + "KjRc" => { + tokens.extend(quote_spanned!(span => ::kj_rs::repr::)); + } + "KjArc" => { + tokens.extend(quote_spanned!(span => ::kj_rs::repr::)); + } "Box" => { tokens.extend(quote_spanned!(span=> ::cxx::alloc::boxed::)); } diff --git a/syntax/types.rs b/syntax/types.rs index ad32e49d0..066fc087d 100644 --- a/syntax/types.rs +++ b/syntax/types.rs @@ -179,6 +179,8 @@ impl<'a> Types<'a> { | ImplKey::RustVec(ident) | ImplKey::UniquePtr(ident) | ImplKey::Own(ident) + | ImplKey::KjRc(ident) + | ImplKey::KjArc(ident) | ImplKey::SharedPtr(ident) | ImplKey::WeakPtr(ident) | ImplKey::CxxVector(ident) => { diff --git a/syntax/visit.rs b/syntax/visit.rs index 7b4924067..885cd4c4b 100644 --- a/syntax/visit.rs +++ b/syntax/visit.rs @@ -15,6 +15,8 @@ where Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Own(ty) + | Type::KjRc(ty) + | Type::KjArc(ty) | Type::SharedPtr(ty) | Type::WeakPtr(ty) | Type::CxxVector(ty)