Skip to content

Commit 228214c

Browse files
authored
[workerd-cxx] initial async C++ functions support (#16)
Can't test int & struct yet b/c of mistake in kj-rs.
1 parent b2eec6a commit 228214c

File tree

20 files changed

+192
-51
lines changed

20 files changed

+192
-51
lines changed

MODULE.bazel.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gen/src/include.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub(crate) struct Includes<'a> {
4343
pub basetsd: bool,
4444
pub sys_types: bool,
4545
pub content: Content<'a>,
46+
pub kj_rs: bool,
4647
}
4748

4849
impl<'a> Includes<'a> {
@@ -105,6 +106,7 @@ pub(super) fn write(out: &mut OutFile) {
105106
vector,
106107
basetsd,
107108
sys_types,
109+
kj_rs,
108110
content: _,
109111
} = *include;
110112

@@ -186,6 +188,9 @@ pub(super) fn write(out: &mut OutFile) {
186188
writeln!(out, "#include <ranges>");
187189
writeln!(out, "#endif");
188190
}
191+
if kj_rs && !cxx_header {
192+
writeln!(out, "#include <kj-rs/promise.h>");
193+
}
189194
}
190195

191196
impl<'i, 'a> Extend<&'i Include> for Includes<'a> {

gen/src/write.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
223223
Type::SliceRef(_) => out.builtin.rust_slice = true,
224224
Type::Array(_) => out.include.array = true,
225225
Type::Ref(_) | Type::Void(_) | Type::Ptr(_) => {}
226+
Type::Future(_) => out.include.kj_rs = true,
226227
}
227228
}
228229
}
@@ -1146,6 +1147,7 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
11461147
}
11471148
write!(out, "*");
11481149
}
1150+
Type::Future(_) => write!(out, "kj_rs::repr::KjPromiseNodeImpl"),
11491151
_ => write_type(out, ty),
11501152
}
11511153
}
@@ -1280,7 +1282,12 @@ fn write_type(out: &mut OutFile, ty: &Type) {
12801282
write_type(out, &a.inner);
12811283
write!(out, ", {}>", &a.len);
12821284
}
1283-
Type::Void(_) => unreachable!(),
1285+
Type::Void(_) => write!(out, "void"),
1286+
Type::Future(ty) => {
1287+
write!(out, "kj::Promise<");
1288+
write_type(out, &ty.output);
1289+
write!(out, ">");
1290+
}
12841291
}
12851292
}
12861293

@@ -1325,6 +1332,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
13251332
| Type::Array(_) => write!(out, " "),
13261333
Type::Ref(_) | Type::Ptr(_) => {}
13271334
Type::Void(_) => unreachable!(),
1335+
Type::Future(_) => write!(out, " "),
13281336
}
13291337
}
13301338

justfile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
1+
alias w := watch
2+
alias b := build
3+
alias t := test
4+
5+
watch +WATCH_TARGET='test':
6+
watchexec -rc -w tests -w src -w gen -w macro -w syntax -- just {{WATCH_TARGET}}
7+
8+
build:
9+
bazel build //...
10+
11+
test:
12+
bazel test //...
13+
14+
clippy:
15+
bazel build --config=clippy //...
16+
117
cargo-update:
218
bazel run //third-party:vendor

kj_rs.bzl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
22

33

4-
URL = "https://github.com/capnproto/kj-rs/tarball/9fc9de649bbf9832d343cebc1c6cb84f47191f77"
5-
STRIP_PREFIX = "capnproto-kj-rs-9fc9de6"
6-
SHA256 = "25513ed21ca27471520e65fb126dca2ceff50c3d06e3056005febc28ee39e408"
4+
URL = "https://github.com/capnproto/kj-rs/tarball/13f2152e0cca109b0c64f9eeca4f62bcf0689a87"
5+
STRIP_PREFIX = "capnproto-kj-rs-13f2152"
6+
SHA256 = "bcd3b2b22a422936bebb5fcefa56eb7d4fa076e329fb6214683c4d6b5e7ec4c3"
77
TYPE = "tgz"
8-
COMMIT = "9fc9de649bbf9832d343cebc1c6cb84f47191f77"
8+
COMMIT = "13f2152e0cca109b0c64f9eeca4f62bcf0689a87"
99

1010
def _kj_rs(_ctx):
1111
http_archive(

macro/src/expand.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::type_id::Crate;
1414
use crate::{derive, generics};
1515
use proc_macro2::{Ident, Span, TokenStream};
1616
use quote::{format_ident, quote, quote_spanned, ToTokens};
17+
use syn::spanned::Spanned;
1718
use std::mem;
1819
use syn::{parse_quote, punctuated, Generics, Lifetime, Result, Token};
1920

@@ -77,6 +78,9 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
7778
}
7879
}
7980
Api::CxxFunction(efn) => {
81+
if efn.asyncness.is_some() {
82+
// todo!("expand_cxx_function_shim\n{}", expand_cxx_function_shim(efn, types).to_string());
83+
}
8084
expanded.extend(expand_cxx_function_shim(efn, types));
8185
}
8286
Api::RustType(ety) => {
@@ -719,7 +723,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
719723
false => quote_spanned!(span=> #call.as_slice::<#inner>()),
720724
true => quote_spanned!(span=> #call.as_mut_slice::<#inner>()),
721725
}
722-
}
726+
},
727+
Type::Future(_) => {
728+
quote_spanned!(span=> ::kj_rs::new_callbacks_promise_future(#call))
729+
},
723730
_ => call,
724731
},
725732
};
@@ -1932,6 +1939,10 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
19321939
let rust_slice = Ident::new("RustSlice", ty.bracket.span.join());
19331940
quote_spanned!(span=> ::cxx::private::#rust_slice)
19341941
}
1942+
Type::Future(ty) => {
1943+
let span = ty.span();
1944+
quote_spanned!(span=> ::kj_rs::KjPromiseNodeImpl)
1945+
}
19351946
_ => quote!(#ty),
19361947
}
19371948
}

syntax/check.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::syntax::report::Errors;
33
use crate::syntax::visit::{self, Visit};
44
use crate::syntax::{
55
error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Lifetimes,
6-
NamedType, Ptr, Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
6+
NamedType, Ptr, Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types, Future
77
};
88
use proc_macro2::{Delimiter, Group, Ident, TokenStream};
99
use quote::{quote, ToTokens};
@@ -43,21 +43,7 @@ fn do_typecheck(cx: &mut Check) {
4343
ident::check_all(cx, cx.apis);
4444

4545
for ty in cx.types {
46-
match ty {
47-
Type::Ident(ident) => check_type_ident(cx, ident),
48-
Type::RustBox(ptr) => check_type_box(cx, ptr),
49-
Type::RustVec(ty) => check_type_rust_vec(cx, ty),
50-
Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
51-
Type::SharedPtr(ptr) => check_type_shared_ptr(cx, ptr),
52-
Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr),
53-
Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
54-
Type::Ref(ty) => check_type_ref(cx, ty),
55-
Type::Ptr(ty) => check_type_ptr(cx, ty),
56-
Type::Array(array) => check_type_array(cx, array),
57-
Type::Fn(ty) => check_type_fn(cx, ty),
58-
Type::SliceRef(ty) => check_type_slice_ref(cx, ty),
59-
Type::Str(_) | Type::Void(_) => {}
60-
}
46+
check_type(cx, ty);
6147
}
6248

6349
for api in cx.apis {
@@ -79,6 +65,25 @@ impl Check<'_> {
7965
}
8066
}
8167

68+
fn check_type(cx: &mut Check, ty: &Type) {
69+
match ty {
70+
Type::Ident(ident) => check_type_ident(cx, ident),
71+
Type::RustBox(ptr) => check_type_box(cx, ptr),
72+
Type::RustVec(ty) => check_type_rust_vec(cx, ty),
73+
Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
74+
Type::SharedPtr(ptr) => check_type_shared_ptr(cx, ptr),
75+
Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr),
76+
Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
77+
Type::Ref(ty) => check_type_ref(cx, ty),
78+
Type::Ptr(ty) => check_type_ptr(cx, ty),
79+
Type::Array(array) => check_type_array(cx, array),
80+
Type::Fn(ty) => check_type_fn(cx, ty),
81+
Type::SliceRef(ty) => check_type_slice_ref(cx, ty),
82+
Type::Str(_) | Type::Void(_) => {}
83+
Type::Future(ty) => check_type_future(cx, ty),
84+
}
85+
}
86+
8287
fn check_type_ident(cx: &mut Check, name: &NamedType) {
8388
let ident = &name.rust;
8489
if Atom::from(ident).is_none()
@@ -640,6 +645,10 @@ fn check_generics(cx: &mut Check, generics: &Generics) {
640645
}
641646
}
642647

648+
fn check_type_future(cx: &mut Check, f: &Future) {
649+
check_type(cx, &f.output);
650+
}
651+
643652
fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
644653
match ty {
645654
Type::Ident(ident) => {
@@ -657,6 +666,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
657666
| Type::Ptr(_)
658667
| Type::Str(_)
659668
| Type::SliceRef(_) => false,
669+
Type::Future(_) => false,
660670
}
661671
}
662672

@@ -735,5 +745,6 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
735745
Type::Fn(_) => "function pointer".to_owned(),
736746
Type::Void(_) => "()".to_owned(),
737747
Type::Array(_) => "array".to_owned(),
748+
Type::Future(f) => format!("Future<Output = {}>", describe(cx, &f.output)),
738749
}
739750
}

syntax/impls.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::syntax::{
2-
Array, ExternFn, Include, Lifetimes, Ptr, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
2+
Array, ExternFn, Future, Include, Lifetimes, Ptr, Receiver, Ref, Signature, SliceRef, Ty1,
3+
Type, Var,
34
};
45
use std::hash::{Hash, Hasher};
56
use std::mem;
@@ -57,6 +58,7 @@ impl Hash for Type {
5758
Type::SliceRef(t) => t.hash(state),
5859
Type::Array(t) => t.hash(state),
5960
Type::Void(_) => {}
61+
Type::Future(t) => t.hash(state),
6062
}
6163
}
6264
}
@@ -78,6 +80,7 @@ impl PartialEq for Type {
7880
(Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
7981
(Type::SliceRef(lhs), Type::SliceRef(rhs)) => lhs == rhs,
8082
(Type::Void(_), Type::Void(_)) => true,
83+
(Type::Future(lhs), Type::Future(rhs)) => lhs == rhs,
8184
(_, _) => false,
8285
}
8386
}
@@ -290,6 +293,12 @@ impl PartialEq for Array {
290293
}
291294
}
292295

296+
impl PartialEq for Future {
297+
fn eq(&self, other: &Self) -> bool {
298+
self.output == other.output
299+
}
300+
}
301+
293302
impl Hash for Array {
294303
fn hash<H: Hasher>(&self, state: &mut H) {
295304
let Array {
@@ -304,6 +313,12 @@ impl Hash for Array {
304313
}
305314
}
306315

316+
impl Hash for Future {
317+
fn hash<H: Hasher>(&self, state: &mut H) {
318+
self.output.hash(state);
319+
}
320+
}
321+
307322
impl Eq for Signature {}
308323

309324
impl PartialEq for Signature {

syntax/improper.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ impl<'a> Types<'a> {
3434
Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
3535
Type::Ptr(ty) => self.determine_improper_ctype(&ty.inner),
3636
Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
37+
Type::Future(_) => todo!("file a workerd-cxx ticket"),
3738
}
3839
}
3940
}

syntax/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ pub(crate) enum Type {
275275
Void(Span),
276276
SliceRef(Box<SliceRef>),
277277
Array(Box<Array>),
278+
Future(Box<Future>),
278279
}
279280

280281
pub(crate) struct Ty1 {
@@ -319,6 +320,10 @@ pub(crate) struct Array {
319320
pub len_token: LitInt,
320321
}
321322

323+
pub(crate) struct Future {
324+
pub output: Type,
325+
}
326+
322327
#[derive(Copy, Clone, PartialEq)]
323328
pub(crate) enum Lang {
324329
Cxx,

0 commit comments

Comments
 (0)