Skip to content

Commit 69a78fc

Browse files
authored
[22.0.0] Change WASI trait impls back to being blanket impls (#8767)
* Change WASI trait impls back to being blanket impls (#8766) This commit is a partial revert of #8609 to return `wasmtime-wasi` and `wasmtime-wasi-http` back to using blanket impls. The main change from before is to change the blanket impls to be in terms of a local newtype wrapper to avoid trait coherence issues. This is done because otherwise using the traits before required `&mut dyn WasiView` to exist but sometimes only a `Foo<'a>` is held which is not easy to get a `&mut dyn ...` view of. By changing to a blanket impl in terms of a newtype wrapper, `WasiImpl`, it's possible to call `bindgen!`-generated `add_to_linker_get_host` functions with a return value of `WasiImpl<Foo<'a>>` which enables hooking into all the generated bindings. * Update release notes
1 parent 0e93db7 commit 69a78fc

25 files changed

+475
-171
lines changed

RELEASES.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ Unreleased.
8686
[#8610](https://github.com/bytecodealliance/wasmtime/pull/8610)
8787

8888
* Implementations of `Host` traits in the `wasmtime-wasi` crate are now for
89-
`dyn WasiView` instead of blanket impls for `T: WasiView`.
89+
`WasiImpl<T>` instead of blanket impls for `T`.
9090
[#8609](https://github.com/bytecodealliance/wasmtime/pull/8609)
91+
[#8766](https://github.com/bytecodealliance/wasmtime/pull/8766)
9192

9293
* The concepts of "virtual sp offset" and "nominal sp" have been removed from all
9394
Cranelift backends.

crates/wasi-http/src/http_impl.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ use crate::{
88
error::internal_error,
99
http_request_error,
1010
types::{HostFutureIncomingResponse, HostOutgoingRequest, OutgoingRequestConfig},
11-
WasiHttpView,
11+
WasiHttpImpl, WasiHttpView,
1212
};
1313
use bytes::Bytes;
1414
use http_body_util::{BodyExt, Empty};
1515
use hyper::Method;
1616
use wasmtime::component::Resource;
1717

18-
impl outgoing_handler::Host for dyn WasiHttpView + '_ {
18+
impl<T> outgoing_handler::Host for WasiHttpImpl<T>
19+
where
20+
T: WasiHttpView,
21+
{
1922
fn handle(
2023
&mut self,
2124
request_id: Resource<HostOutgoingRequest>,

crates/wasi-http/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,4 @@ pub use crate::error::{
8787
http_request_error, hyper_request_error, hyper_response_error, HttpError, HttpResult,
8888
};
8989
#[doc(inline)]
90-
pub use crate::types::{WasiHttpCtx, WasiHttpView};
90+
pub use crate::types::{WasiHttpCtx, WasiHttpImpl, WasiHttpView};

crates/wasi-http/src/proxy.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! The implementation at the top of the module for use in async contexts,
44
//! while the `sync` module provides implementation for use in sync contexts.
55
6-
use crate::WasiHttpView;
6+
use crate::{WasiHttpImpl, WasiHttpView};
77

88
mod bindings {
99
#![allow(missing_docs)]
@@ -83,7 +83,7 @@ pub fn add_to_linker<T>(l: &mut wasmtime::component::Linker<T>) -> anyhow::Resul
8383
where
8484
T: WasiHttpView + wasmtime_wasi::WasiView,
8585
{
86-
let closure = type_annotate_wasi::<T, _>(|t| t);
86+
let closure = type_annotate_wasi::<T, _>(|t| wasmtime_wasi::WasiImpl(t));
8787
wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?;
8888
wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?;
8989
wasmtime_wasi::bindings::io::poll::add_to_linker_get_host(l, closure)?;
@@ -101,13 +101,13 @@ where
101101
// obsolete.
102102
fn type_annotate_http<T, F>(val: F) -> F
103103
where
104-
F: Fn(&mut T) -> &mut dyn WasiHttpView,
104+
F: Fn(&mut T) -> WasiHttpImpl<&mut T>,
105105
{
106106
val
107107
}
108108
fn type_annotate_wasi<T, F>(val: F) -> F
109109
where
110-
F: Fn(&mut T) -> &mut dyn wasmtime_wasi::WasiView,
110+
F: Fn(&mut T) -> wasmtime_wasi::WasiImpl<&mut T>,
111111
{
112112
val
113113
}
@@ -117,7 +117,7 @@ pub fn add_only_http_to_linker<T>(l: &mut wasmtime::component::Linker<T>) -> any
117117
where
118118
T: WasiHttpView,
119119
{
120-
let closure = type_annotate_http::<T, _>(|t| t);
120+
let closure = type_annotate_http::<T, _>(|t| WasiHttpImpl(t));
121121
crate::bindings::http::outgoing_handler::add_to_linker_get_host(l, closure)?;
122122
crate::bindings::http::types::add_to_linker_get_host(l, closure)?;
123123

@@ -126,7 +126,7 @@ where
126126

127127
/// Sync implementation of the `wasi:http/proxy` world.
128128
pub mod sync {
129-
use crate::WasiHttpView;
129+
use crate::{WasiHttpImpl, WasiHttpView};
130130

131131
mod bindings {
132132
#![allow(missing_docs)]
@@ -203,7 +203,7 @@ pub mod sync {
203203
where
204204
T: WasiHttpView + wasmtime_wasi::WasiView,
205205
{
206-
let closure = super::type_annotate_wasi::<T, _>(|t| t);
206+
let closure = super::type_annotate_wasi::<T, _>(|t| wasmtime_wasi::WasiImpl(t));
207207

208208
wasmtime_wasi::bindings::clocks::wall_clock::add_to_linker_get_host(l, closure)?;
209209
wasmtime_wasi::bindings::clocks::monotonic_clock::add_to_linker_get_host(l, closure)?;
@@ -226,7 +226,7 @@ pub mod sync {
226226
where
227227
T: WasiHttpView,
228228
{
229-
let closure = super::type_annotate_http::<T, _>(|t| t);
229+
let closure = super::type_annotate_http::<T, _>(|t| WasiHttpImpl(t));
230230

231231
crate::bindings::http::outgoing_handler::add_to_linker_get_host(l, closure)?;
232232
crate::bindings::http::types::add_to_linker_get_host(l, closure)?;

crates/wasi-http/src/types.rs

+77
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,83 @@ impl<T: ?Sized + WasiHttpView> WasiHttpView for &mut T {
112112
}
113113
}
114114

115+
impl<T: ?Sized + WasiHttpView> WasiHttpView for Box<T> {
116+
fn ctx(&mut self) -> &mut WasiHttpCtx {
117+
T::ctx(self)
118+
}
119+
120+
fn table(&mut self) -> &mut ResourceTable {
121+
T::table(self)
122+
}
123+
124+
fn new_response_outparam(
125+
&mut self,
126+
result: tokio::sync::oneshot::Sender<
127+
Result<hyper::Response<HyperOutgoingBody>, types::ErrorCode>,
128+
>,
129+
) -> wasmtime::Result<Resource<HostResponseOutparam>> {
130+
T::new_response_outparam(self, result)
131+
}
132+
133+
fn send_request(
134+
&mut self,
135+
request: hyper::Request<HyperOutgoingBody>,
136+
config: OutgoingRequestConfig,
137+
) -> crate::HttpResult<HostFutureIncomingResponse> {
138+
T::send_request(self, request, config)
139+
}
140+
141+
fn is_forbidden_header(&mut self, name: &HeaderName) -> bool {
142+
T::is_forbidden_header(self, name)
143+
}
144+
}
145+
146+
/// A concrete structure that all generated `Host` traits are implemented for.
147+
///
148+
/// This type serves as a small newtype wrapper to implement all of the `Host`
149+
/// traits for `wasi:http`. This type is internally used and is only needed if
150+
/// you're interacting with `add_to_linker` functions generated by bindings
151+
/// themselves (or `add_to_linker_get_host`).
152+
///
153+
/// This type is automatically used when using
154+
/// [`wasmtime_wasi_http::proxy::add_to_linker`](crate::proxy::add_to_linker)
155+
/// or
156+
/// [`wasmtime_wasi_http::proxy::sync::add_to_linker`](crate::proxy::sync::add_to_linker)
157+
/// and doesn't need to be manually configured.
158+
#[repr(transparent)]
159+
pub struct WasiHttpImpl<T>(pub T);
160+
161+
impl<T: WasiHttpView> WasiHttpView for WasiHttpImpl<T> {
162+
fn ctx(&mut self) -> &mut WasiHttpCtx {
163+
self.0.ctx()
164+
}
165+
166+
fn table(&mut self) -> &mut ResourceTable {
167+
self.0.table()
168+
}
169+
170+
fn new_response_outparam(
171+
&mut self,
172+
result: tokio::sync::oneshot::Sender<
173+
Result<hyper::Response<HyperOutgoingBody>, types::ErrorCode>,
174+
>,
175+
) -> wasmtime::Result<Resource<HostResponseOutparam>> {
176+
self.0.new_response_outparam(result)
177+
}
178+
179+
fn send_request(
180+
&mut self,
181+
request: hyper::Request<HyperOutgoingBody>,
182+
config: OutgoingRequestConfig,
183+
) -> crate::HttpResult<HostFutureIncomingResponse> {
184+
self.0.send_request(request, config)
185+
}
186+
187+
fn is_forbidden_header(&mut self, name: &HeaderName) -> bool {
188+
self.0.is_forbidden_header(name)
189+
}
190+
}
191+
115192
/// Returns `true` when the header is forbidden according to this [`WasiHttpView`] implementation.
116193
pub(crate) fn is_forbidden_header(view: &mut dyn WasiHttpView, name: &HeaderName) -> bool {
117194
static FORBIDDEN_HEADERS: [HeaderName; 10] = [

crates/wasi-http/src/types_impl.rs

+49-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
HostFutureIncomingResponse, HostIncomingRequest, HostIncomingResponse, HostOutgoingRequest,
99
HostOutgoingResponse, HostResponseOutparam,
1010
},
11-
WasiHttpView,
11+
WasiHttpImpl, WasiHttpView,
1212
};
1313
use anyhow::Context;
1414
use std::any::Any;
@@ -19,7 +19,10 @@ use wasmtime_wasi::{
1919
Pollable, ResourceTableError,
2020
};
2121

22-
impl crate::bindings::http::types::Host for dyn WasiHttpView + '_ {
22+
impl<T> crate::bindings::http::types::Host for WasiHttpImpl<T>
23+
where
24+
T: WasiHttpView,
25+
{
2326
fn convert_error_code(&mut self, err: crate::HttpError) -> wasmtime::Result<types::ErrorCode> {
2427
err.downcast()
2528
}
@@ -98,7 +101,10 @@ fn get_fields_mut<'a>(
98101
}
99102
}
100103

101-
impl crate::bindings::http::types::HostFields for dyn WasiHttpView + '_ {
104+
impl<T> crate::bindings::http::types::HostFields for WasiHttpImpl<T>
105+
where
106+
T: WasiHttpView,
107+
{
102108
fn new(&mut self) -> wasmtime::Result<Resource<HostFields>> {
103109
let id = self
104110
.table()
@@ -285,7 +291,10 @@ impl crate::bindings::http::types::HostFields for dyn WasiHttpView + '_ {
285291
}
286292
}
287293

288-
impl crate::bindings::http::types::HostIncomingRequest for dyn WasiHttpView + '_ {
294+
impl<T> crate::bindings::http::types::HostIncomingRequest for WasiHttpImpl<T>
295+
where
296+
T: WasiHttpView,
297+
{
289298
fn method(&mut self, id: Resource<HostIncomingRequest>) -> wasmtime::Result<Method> {
290299
let method = self.table().get(&id)?.parts.method.clone();
291300
Ok(method.into())
@@ -370,7 +379,10 @@ impl crate::bindings::http::types::HostIncomingRequest for dyn WasiHttpView + '_
370379
}
371380
}
372381

373-
impl crate::bindings::http::types::HostOutgoingRequest for dyn WasiHttpView + '_ {
382+
impl<T> crate::bindings::http::types::HostOutgoingRequest for WasiHttpImpl<T>
383+
where
384+
T: WasiHttpView,
385+
{
374386
fn new(
375387
&mut self,
376388
headers: Resource<Headers>,
@@ -556,7 +568,10 @@ impl crate::bindings::http::types::HostOutgoingRequest for dyn WasiHttpView + '_
556568
}
557569
}
558570

559-
impl crate::bindings::http::types::HostResponseOutparam for dyn WasiHttpView + '_ {
571+
impl<T> crate::bindings::http::types::HostResponseOutparam for WasiHttpImpl<T>
572+
where
573+
T: WasiHttpView,
574+
{
560575
fn drop(&mut self, id: Resource<HostResponseOutparam>) -> wasmtime::Result<()> {
561576
let _ = self.table().delete(id)?;
562577
Ok(())
@@ -579,7 +594,10 @@ impl crate::bindings::http::types::HostResponseOutparam for dyn WasiHttpView + '
579594
}
580595
}
581596

582-
impl crate::bindings::http::types::HostIncomingResponse for dyn WasiHttpView + '_ {
597+
impl<T> crate::bindings::http::types::HostIncomingResponse for WasiHttpImpl<T>
598+
where
599+
T: WasiHttpView,
600+
{
583601
fn drop(&mut self, response: Resource<HostIncomingResponse>) -> wasmtime::Result<()> {
584602
let _ = self
585603
.table()
@@ -640,7 +658,10 @@ impl crate::bindings::http::types::HostIncomingResponse for dyn WasiHttpView + '
640658
}
641659
}
642660

643-
impl crate::bindings::http::types::HostFutureTrailers for dyn WasiHttpView + '_ {
661+
impl<T> crate::bindings::http::types::HostFutureTrailers for WasiHttpImpl<T>
662+
where
663+
T: WasiHttpView,
664+
{
644665
fn drop(&mut self, id: Resource<HostFutureTrailers>) -> wasmtime::Result<()> {
645666
let _ = self
646667
.table()
@@ -687,7 +708,10 @@ impl crate::bindings::http::types::HostFutureTrailers for dyn WasiHttpView + '_
687708
}
688709
}
689710

690-
impl crate::bindings::http::types::HostIncomingBody for dyn WasiHttpView + '_ {
711+
impl<T> crate::bindings::http::types::HostIncomingBody for WasiHttpImpl<T>
712+
where
713+
T: WasiHttpView,
714+
{
691715
fn stream(
692716
&mut self,
693717
id: Resource<HostIncomingBody>,
@@ -718,7 +742,10 @@ impl crate::bindings::http::types::HostIncomingBody for dyn WasiHttpView + '_ {
718742
}
719743
}
720744

721-
impl crate::bindings::http::types::HostOutgoingResponse for dyn WasiHttpView + '_ {
745+
impl<T> crate::bindings::http::types::HostOutgoingResponse for WasiHttpImpl<T>
746+
where
747+
T: WasiHttpView,
748+
{
722749
fn new(
723750
&mut self,
724751
headers: Resource<Headers>,
@@ -807,7 +834,10 @@ impl crate::bindings::http::types::HostOutgoingResponse for dyn WasiHttpView + '
807834
}
808835
}
809836

810-
impl crate::bindings::http::types::HostFutureIncomingResponse for dyn WasiHttpView + '_ {
837+
impl<T> crate::bindings::http::types::HostFutureIncomingResponse for WasiHttpImpl<T>
838+
where
839+
T: WasiHttpView,
840+
{
811841
fn drop(&mut self, id: Resource<HostFutureIncomingResponse>) -> wasmtime::Result<()> {
812842
let _ = self.table().delete(id)?;
813843
Ok(())
@@ -866,7 +896,10 @@ impl crate::bindings::http::types::HostFutureIncomingResponse for dyn WasiHttpVi
866896
}
867897
}
868898

869-
impl crate::bindings::http::types::HostOutgoingBody for dyn WasiHttpView + '_ {
899+
impl<T> crate::bindings::http::types::HostOutgoingBody for WasiHttpImpl<T>
900+
where
901+
T: WasiHttpView,
902+
{
870903
fn write(
871904
&mut self,
872905
id: Resource<HostOutgoingBody>,
@@ -903,7 +936,10 @@ impl crate::bindings::http::types::HostOutgoingBody for dyn WasiHttpView + '_ {
903936
}
904937
}
905938

906-
impl crate::bindings::http::types::HostRequestOptions for dyn WasiHttpView + '_ {
939+
impl<T> crate::bindings::http::types::HostRequestOptions for WasiHttpImpl<T>
940+
where
941+
T: WasiHttpView,
942+
{
907943
fn new(&mut self) -> wasmtime::Result<Resource<types::RequestOptions>> {
908944
let id = self.table().push(types::RequestOptions::default())?;
909945
Ok(id)

crates/wasi/src/ctx.rs

+33
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,39 @@ impl<T: ?Sized + WasiView> WasiView for &mut T {
594594
}
595595
}
596596

597+
impl<T: ?Sized + WasiView> WasiView for Box<T> {
598+
fn table(&mut self) -> &mut ResourceTable {
599+
T::table(self)
600+
}
601+
fn ctx(&mut self) -> &mut WasiCtx {
602+
T::ctx(self)
603+
}
604+
}
605+
606+
/// A small newtype wrapper which serves as the basis for implementations of
607+
/// `Host` WASI traits in this crate.
608+
///
609+
/// This type is used as the basis for the implementation of all `Host` traits
610+
/// generated by `bindgen!` for WASI interfaces. This is used automatically with
611+
/// [`add_to_linker_sync`](crate::add_to_linker_sync) and
612+
/// [`add_to_linker_async`](crate::add_to_linker_async).
613+
///
614+
/// This type is otherwise provided if you're calling the `add_to_linker`
615+
/// functions generated by `bindgen!` from the [`bindings`
616+
/// module](crate::bindings). In this situation you'll want to create a value of
617+
/// this type in the closures added to a `Linker`.
618+
#[repr(transparent)]
619+
pub struct WasiImpl<T>(pub T);
620+
621+
impl<T: WasiView> WasiView for WasiImpl<T> {
622+
fn table(&mut self) -> &mut ResourceTable {
623+
T::table(&mut self.0)
624+
}
625+
fn ctx(&mut self) -> &mut WasiCtx {
626+
T::ctx(&mut self.0)
627+
}
628+
}
629+
597630
/// Per-[`Store`] state which holds state necessary to implement WASI from this
598631
/// crate.
599632
///

0 commit comments

Comments
 (0)