@@ -246,10 +246,21 @@ fn write_generated_file(path: &Path, contents: &str) {
246246fn builtin_source_specs ( namespaces : & [ NamespaceDecl ] ) -> Vec < SourceSpec > {
247247 namespaces
248248 . iter ( )
249- . map ( |namespace| SourceSpec {
250- path : format ! ( "src/builtins/runtime/{}.rs" , namespace. module) ,
251- module : namespace. module . clone ( ) ,
252- category : SourceCategory :: NamespacedBuiltin ,
249+ . map ( |namespace| {
250+ let path = if namespace. module == "io" {
251+ if cfg ! ( feature = "async" ) {
252+ "src/builtins/runtime/io/async_io.rs" . to_string ( )
253+ } else {
254+ "src/builtins/runtime/io/blocking.rs" . to_string ( )
255+ }
256+ } else {
257+ format ! ( "src/builtins/runtime/{}.rs" , namespace. module)
258+ } ;
259+ SourceSpec {
260+ path,
261+ module : namespace. module . clone ( ) ,
262+ category : SourceCategory :: NamespacedBuiltin ,
263+ }
253264 } )
254265 . collect ( )
255266}
@@ -271,6 +282,9 @@ fn parse_sources(
271282}
272283
273284pub ( crate ) fn classify_host_binding ( function : & ItemFn ) -> HostBindingKind {
285+ if function. sig . asyncness . is_some ( ) {
286+ return HostBindingKind :: StaticStack ;
287+ }
274288 if function. sig . inputs . iter ( ) . any ( |input| match input {
275289 FnArg :: Typed ( pat_type) => is_vm_context_type ( & pat_type. ty ) ,
276290 _ => false ,
@@ -296,6 +310,9 @@ pub(crate) fn classify_host_binding(function: &ItemFn) -> HostBindingKind {
296310}
297311
298312pub ( crate ) fn infer_host_execution ( function : & ItemFn ) -> HostExecutionKind {
313+ if function. sig . asyncness . is_some ( ) {
314+ return HostExecutionKind :: MaySuspend ;
315+ }
299316 let return_type = normalized_return_type ( & function. sig . output ) ;
300317 if contains_host_call_result ( & return_type) {
301318 HostExecutionKind :: MaySuspend
@@ -979,6 +996,7 @@ fn render_builtin_catalog(
979996 & actual_builtin_by_variant,
980997 ) ;
981998 render_builtin_signature_method ( & mut out, & builtin_variant_order) ;
999+ render_builtin_capability_method ( & mut out, builtin_callables) ;
9821000 writeln ! (
9831001 & mut out,
9841002 " pub fn from_namespaced_name(name: &str) -> Option<Self> {{"
@@ -1553,6 +1571,35 @@ fn required_param_count(params: &[CallableParamDecl]) -> usize {
15531571 params. iter ( ) . take_while ( |param| !param. optional ) . count ( )
15541572}
15551573
1574+ fn render_builtin_capability_method ( out : & mut String , builtin_callables : & [ CallableDecl ] ) {
1575+ let mut capability_variants = Vec :: new ( ) ;
1576+ for callable in builtin_callables {
1577+ let variant = builtin_variant_name ( & callable. name ) ;
1578+ if !capability_variants. contains ( & variant) {
1579+ capability_variants. push ( variant) ;
1580+ }
1581+ }
1582+ capability_variants. sort ( ) ;
1583+ writeln ! ( out, " #[cfg(feature = \" runtime\" )]" ) . unwrap ( ) ;
1584+ writeln ! (
1585+ out,
1586+ " pub(crate) const fn requires_explicit_host_capability(self) -> bool {{"
1587+ )
1588+ . unwrap ( ) ;
1589+ if capability_variants. is_empty ( ) {
1590+ writeln ! ( out, " false" ) . unwrap ( ) ;
1591+ } else {
1592+ let patterns = capability_variants
1593+ . iter ( )
1594+ . map ( |variant| format ! ( "BuiltinFunction::{variant}" ) )
1595+ . collect :: < Vec < _ > > ( )
1596+ . join ( " | " ) ;
1597+ writeln ! ( out, " matches!(self, {patterns})" ) . unwrap ( ) ;
1598+ }
1599+ writeln ! ( out, " }}" ) . unwrap ( ) ;
1600+ writeln ! ( out) . unwrap ( ) ;
1601+ }
1602+
15561603fn stable_groups < F > ( callables : & [ CallableDecl ] , mut key_fn : F ) -> Vec < Group < ' _ > >
15571604where
15581605 F : FnMut ( & CallableDecl ) -> String ,
@@ -1863,6 +1910,9 @@ fn host_wrapper_adapter_name(callable: &CallableDecl) -> String {
18631910
18641911fn generated_wrapper_decl ( function : & ItemFn ) -> WrapperDecl {
18651912 let mut params = Vec :: new ( ) ;
1913+ if function. sig . asyncness . is_some ( ) {
1914+ params. push ( WrapperParamKind :: Vm ) ;
1915+ }
18661916 for input in & function. sig . inputs {
18671917 let FnArg :: Typed ( pat_type) = input else {
18681918 panic ! ( "methods are not supported in #[pd_host_function] declarations" ) ;
@@ -1889,6 +1939,13 @@ fn parse_callable_params(function: &ItemFn) -> Vec<CallableParamDecl> {
18891939 let FnArg :: Typed ( pat_type) = input else {
18901940 panic ! ( "methods are not supported in #[pd_host_function] declarations" ) ;
18911941 } ;
1942+ if pat_type
1943+ . attrs
1944+ . iter ( )
1945+ . any ( |attr| attr. path ( ) . is_ident ( "pd_host_context" ) )
1946+ {
1947+ return None ;
1948+ }
18921949 if is_vm_context_type ( & pat_type. ty ) {
18931950 return None ;
18941951 }
@@ -2055,7 +2112,7 @@ fn type_label(ty: &Type) -> String {
20552112 } ;
20562113 format ! ( "{} | null" , type_label( inner) )
20572114 }
2058- "VmResult" | "HostCallResult" => {
2115+ "VmResult" | "HostCallResult" | "HostFutureOutput" => {
20592116 let syn:: PathArguments :: AngleBracketed ( args) = & segment. arguments else {
20602117 panic ! ( "{ident}<T> requires one generic argument" ) ;
20612118 } ;
0 commit comments