Skip to content

Commit 37d71db

Browse files
alexcrichtonlann
andauthored
Add GetHost to generated bindings for more flexible linking (#8448) (#8620)
* Remove unused generated `add_root_to_linker` method * WIP: bindgen GetHost * Compile with Rust 1.78+ Use <https://users.rust-lang.org/t/generic-closure-returns-that-can-capture-arguments/76513/3> as a guide of how to implement this by making the `GetHost` trait a bit uglier. * Add an option to skip `&mut T -> T` impls Also enable this for WASI crates since they do their own thing with `WasiView` for now. A future refactoring should be able to remove this option entirely and switch wasi crates to a new design of `WasiView`. * Update test expectations * Review comments * Undo temporary change * Handle some TODOs * Remove no-longer-relevant note * Fix wasmtime-wasi-http doc link --------- Co-authored-by: Lann <lann.martin@fermyon.com>
1 parent 2690964 commit 37d71db

File tree

10 files changed

+515
-233
lines changed

10 files changed

+515
-233
lines changed

crates/component-macro/src/bindgen.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ impl Parse for Config {
144144
.map(|p| p.into_token_stream().to_string())
145145
.collect()
146146
}
147+
Opt::SkipMutForwardingImpls(val) => opts.skip_mut_forwarding_impls = val,
147148
}
148149
}
149150
} else {
@@ -213,6 +214,7 @@ mod kw {
213214
syn::custom_keyword!(only_imports);
214215
syn::custom_keyword!(trappable_imports);
215216
syn::custom_keyword!(additional_derives);
217+
syn::custom_keyword!(skip_mut_forwarding_impls);
216218
}
217219

218220
enum Opt {
@@ -227,6 +229,7 @@ enum Opt {
227229
With(HashMap<String, String>),
228230
TrappableImports(TrappableImports),
229231
AdditionalDerives(Vec<syn::Path>),
232+
SkipMutForwardingImpls(bool),
230233
}
231234

232235
impl Parse for Opt {
@@ -367,6 +370,12 @@ impl Parse for Opt {
367370
syn::bracketed!(contents in input);
368371
let list = Punctuated::<_, Token![,]>::parse_terminated(&contents)?;
369372
Ok(Opt::AdditionalDerives(list.iter().cloned().collect()))
373+
} else if l.peek(kw::skip_mut_forwarding_impls) {
374+
input.parse::<kw::skip_mut_forwarding_impls>()?;
375+
input.parse::<Token![:]>()?;
376+
Ok(Opt::SkipMutForwardingImpls(
377+
input.parse::<syn::LitBool>()?.value,
378+
))
370379
} else {
371380
Err(l.error())
372381
}

crates/wasi-http/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
//! 2. Add WASI HTTP interfaces to a [`wasmtime::component::Linker<T>`]. This is either
2828
//! done through functions like [`proxy::add_to_linker`] (which bundles all interfaces
2929
//! in the `wasi:http/proxy` world together) or through individual interfaces like the
30-
//! [`bindings::http::outgoing_handler::add_to_linker`] function.
30+
//! [`bindings::http::outgoing_handler::add_to_linker_get_host`] function.
3131
//! 3. Use the previous [`wasmtime::component::Linker<T>::instantiate`] to instantiate
3232
//! a [`wasmtime::component::Component`] within a [`wasmtime::Store<T>`]. If you're
3333
//! targeting the `wasi:http/proxy` world, you can instantiate the component with
@@ -78,6 +78,7 @@ pub mod bindings {
7878
trappable_error_type: {
7979
"wasi:http/types/error-code" => crate::HttpError,
8080
},
81+
skip_mut_forwarding_impls: true,
8182
});
8283

8384
pub use wasi::http;

crates/wasi-http/src/proxy.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -83,26 +83,37 @@ pub fn add_to_linker<T>(l: &mut wasmtime::component::Linker<T>) -> anyhow::Resul
8383
where
8484
T: WasiHttpView + wasmtime_wasi::WasiView,
8585
{
86-
wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker(l, |t| t)?;
87-
wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker(l, |t| t)?;
88-
wasmtime_wasi::bindings::io::poll::add_to_linker(l, |t| t)?;
89-
wasmtime_wasi::bindings::io::error::add_to_linker(l, |t| t)?;
90-
wasmtime_wasi::bindings::io::streams::add_to_linker(l, |t| t)?;
91-
wasmtime_wasi::bindings::cli::stdin::add_to_linker(l, |t| t)?;
92-
wasmtime_wasi::bindings::cli::stdout::add_to_linker(l, |t| t)?;
93-
wasmtime_wasi::bindings::cli::stderr::add_to_linker(l, |t| t)?;
94-
wasmtime_wasi::bindings::random::random::add_to_linker(l, |t| t)?;
86+
let closure = type_annotate::<T, _>(|t| t);
87+
wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?;
88+
wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?;
89+
wasmtime_wasi::bindings::io::poll::add_to_linker_get_host(l, closure)?;
90+
wasmtime_wasi::bindings::io::error::add_to_linker_get_host(l, closure)?;
91+
wasmtime_wasi::bindings::io::streams::add_to_linker_get_host(l, closure)?;
92+
wasmtime_wasi::bindings::cli::stdin::add_to_linker_get_host(l, closure)?;
93+
wasmtime_wasi::bindings::cli::stdout::add_to_linker_get_host(l, closure)?;
94+
wasmtime_wasi::bindings::cli::stderr::add_to_linker_get_host(l, closure)?;
95+
wasmtime_wasi::bindings::random::random::add_to_linker_get_host(l, closure)?;
9596

9697
add_only_http_to_linker(l)
9798
}
9899

100+
// NB: workaround some rustc inference - a future refactoring may make this
101+
// obsolete.
102+
fn type_annotate<T, F>(val: F) -> F
103+
where
104+
F: Fn(&mut T) -> &mut T,
105+
{
106+
val
107+
}
108+
99109
#[doc(hidden)]
100110
pub fn add_only_http_to_linker<T>(l: &mut wasmtime::component::Linker<T>) -> anyhow::Result<()>
101111
where
102112
T: WasiHttpView + wasmtime_wasi::WasiView + crate::bindings::http::types::Host,
103113
{
104-
crate::bindings::http::outgoing_handler::add_to_linker(l, |t| t)?;
105-
crate::bindings::http::types::add_to_linker(l, |t| t)?;
114+
let closure = type_annotate::<T, _>(|t| t);
115+
crate::bindings::http::outgoing_handler::add_to_linker_get_host(l, closure)?;
116+
crate::bindings::http::types::add_to_linker_get_host(l, closure)?;
106117

107118
Ok(())
108119
}
@@ -185,15 +196,17 @@ pub mod sync {
185196
where
186197
T: WasiHttpView + wasmtime_wasi::WasiView,
187198
{
188-
wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker(l, |t| t)?;
189-
wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker(l, |t| t)?;
190-
wasmtime_wasi::bindings::sync::io::poll::add_to_linker(l, |t| t)?;
191-
wasmtime_wasi::bindings::sync::io::streams::add_to_linker(l, |t| t)?;
192-
wasmtime_wasi::bindings::io::error::add_to_linker(l, |t| t)?;
193-
wasmtime_wasi::bindings::cli::stdin::add_to_linker(l, |t| t)?;
194-
wasmtime_wasi::bindings::cli::stdout::add_to_linker(l, |t| t)?;
195-
wasmtime_wasi::bindings::cli::stderr::add_to_linker(l, |t| t)?;
196-
wasmtime_wasi::bindings::random::random::add_to_linker(l, |t| t)?;
199+
let closure = super::type_annotate::<T, _>(|t| t);
200+
201+
wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?;
202+
wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?;
203+
wasmtime_wasi::bindings::sync::io::poll::add_to_linker_get_host(l, closure)?;
204+
wasmtime_wasi::bindings::sync::io::streams::add_to_linker_get_host(l, closure)?;
205+
wasmtime_wasi::bindings::io::error::add_to_linker_get_host(l, closure)?;
206+
wasmtime_wasi::bindings::cli::stdin::add_to_linker_get_host(l, closure)?;
207+
wasmtime_wasi::bindings::cli::stdout::add_to_linker_get_host(l, closure)?;
208+
wasmtime_wasi::bindings::cli::stderr::add_to_linker_get_host(l, closure)?;
209+
wasmtime_wasi::bindings::random::random::add_to_linker_get_host(l, closure)?;
197210

198211
add_only_http_to_linker(l)?;
199212

@@ -206,8 +219,10 @@ pub mod sync {
206219
where
207220
T: WasiHttpView + wasmtime_wasi::WasiView + crate::bindings::http::types::Host,
208221
{
209-
crate::bindings::http::outgoing_handler::add_to_linker(l, |t| t)?;
210-
crate::bindings::http::types::add_to_linker(l, |t| t)?;
222+
let closure = super::type_annotate::<T, _>(|t| t);
223+
224+
crate::bindings::http::outgoing_handler::add_to_linker_get_host(l, closure)?;
225+
crate::bindings::http::types::add_to_linker_get_host(l, closure)?;
211226

212227
Ok(())
213228
}

crates/wasi-http/src/types.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl WasiHttpCtx {
3030
}
3131

3232
/// A trait which provides internal WASI HTTP state.
33-
pub trait WasiHttpView: Send {
33+
pub trait WasiHttpView {
3434
/// Returns a mutable reference to the WASI HTTP context.
3535
fn ctx(&mut self) -> &mut WasiHttpCtx;
3636

@@ -71,10 +71,7 @@ pub trait WasiHttpView: Send {
7171
&mut self,
7272
request: hyper::Request<HyperOutgoingBody>,
7373
config: OutgoingRequestConfig,
74-
) -> crate::HttpResult<HostFutureIncomingResponse>
75-
where
76-
Self: Sized,
77-
{
74+
) -> crate::HttpResult<HostFutureIncomingResponse> {
7875
Ok(default_send_request(request, config))
7976
}
8077

@@ -84,6 +81,37 @@ pub trait WasiHttpView: Send {
8481
}
8582
}
8683

84+
impl<T: ?Sized + WasiHttpView> WasiHttpView for &mut T {
85+
fn ctx(&mut self) -> &mut WasiHttpCtx {
86+
T::ctx(self)
87+
}
88+
89+
fn table(&mut self) -> &mut ResourceTable {
90+
T::table(self)
91+
}
92+
93+
fn new_response_outparam(
94+
&mut self,
95+
result: tokio::sync::oneshot::Sender<
96+
Result<hyper::Response<HyperOutgoingBody>, types::ErrorCode>,
97+
>,
98+
) -> wasmtime::Result<Resource<HostResponseOutparam>> {
99+
T::new_response_outparam(self, result)
100+
}
101+
102+
fn send_request(
103+
&mut self,
104+
request: hyper::Request<HyperOutgoingBody>,
105+
config: OutgoingRequestConfig,
106+
) -> crate::HttpResult<HostFutureIncomingResponse> {
107+
T::send_request(self, request, config)
108+
}
109+
110+
fn is_forbidden_header(&mut self, name: &HeaderName) -> bool {
111+
T::is_forbidden_header(self, name)
112+
}
113+
}
114+
87115
/// Returns `true` when the header is forbidden according to this [`WasiHttpView`] implementation.
88116
pub(crate) fn is_forbidden_header(view: &mut dyn WasiHttpView, name: &HeaderName) -> bool {
89117
static FORBIDDEN_HEADERS: [HeaderName; 10] = [

crates/wasi-nn/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ workspace = true
1616

1717
[dependencies]
1818
# These dependencies are necessary for the WITX-generation macros to work:
19-
anyhow = { workspace = true }
19+
anyhow = { workspace = true, features = ['std'] }
2020
wiggle = { workspace = true, features = ["wasmtime"] }
2121

2222
# This dependency is necessary for the WIT-generation macros to work:

crates/wasi/src/bindings.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ pub mod sync {
3333
"wasi:io/poll/pollable": super::super::io::poll::Pollable,
3434
"wasi:io/streams/input-stream": super::super::io::streams::InputStream,
3535
"wasi:io/streams/output-stream": super::super::io::streams::OutputStream,
36-
}
36+
},
37+
skip_mut_forwarding_impls: true,
3738
});
3839
}
3940
pub use self::generated::exports;
@@ -49,10 +50,6 @@ pub mod sync {
4950
/// component through the [`Command::wasi_cli_run`] method plus
5051
/// [`Guest::call_run`](exports::wasi::cli::run::Guest::call_run).
5152
///
52-
/// > **Note**: it's recommended to use
53-
/// > [`wasmtime_wasi::add_to_linker_sync`] instead of the auto-generated
54-
/// > [`Command::add_to_linker`] here.
55-
///
5653
/// [async]: wasmtime::Config::async_support
5754
/// [`wasmtime_wasi::add_to_linker_sync`]: crate::add_to_linker_sync
5855
///
@@ -202,6 +199,7 @@ mod async_io {
202199
"wasi:cli/terminal-input/terminal-input": crate::stdio::TerminalInput,
203200
"wasi:cli/terminal-output/terminal-output": crate::stdio::TerminalOutput,
204201
},
202+
skip_mut_forwarding_impls: true,
205203
});
206204
}
207205

@@ -218,9 +216,6 @@ pub use self::async_io::wasi::*;
218216
/// through the [`Command::wasi_cli_run`] method plus
219217
/// [`Guest::call_run`](exports::wasi::cli::run::Guest::call_run).
220218
///
221-
/// > **Note**: it's recommended to use [`wasmtime_wasi::add_to_linker_async`]
222-
/// > instead of the auto-generated [`Command::add_to_linker`] here.
223-
///
224219
/// [async]: wasmtime::Config::async_support
225220
/// [`wasmtime_wasi::add_to_linker_async`]: crate::add_to_linker_async
226221
///

crates/wasi/src/ctx.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,15 @@ pub trait WasiView: Send {
581581
fn ctx(&mut self) -> &mut WasiCtx;
582582
}
583583

584+
impl<T: ?Sized + WasiView> WasiView for &mut T {
585+
fn table(&mut self) -> &mut ResourceTable {
586+
T::table(self)
587+
}
588+
fn ctx(&mut self) -> &mut WasiCtx {
589+
T::ctx(self)
590+
}
591+
}
592+
584593
/// Per-[`Store`] state which holds state necessary to implement WASI from this
585594
/// crate.
586595
///

0 commit comments

Comments
 (0)