rvolosatovs opened PR #11257 from rvolosatovs:feat/wasip3-cli to bytecodealliance:main:
follow-up on #11221, this implements
wasi:cli, mostly by moving and cleaning up the implementation from https://github.com/bytecodealliance/wasip3-prototyping
alexcrichton submitted PR review.
alexcrichton created PR review comment:
Could the
InputStreamandOutputStreamtraits directly have aSendsupertrait to avoid needingInputStream + Sendfor example in the builder and such?
alexcrichton created PR review comment:
Would it be possible to use
std::io::IsTerminalinstead?
alexcrichton created PR review comment:
FWIW a trick I've used in the past is to use
T::clocks(self)in the body which forcibly ensures that recursion doesn't happen and avoids**syntax as well. Just a style thing though, no meaningful difference
alexcrichton created PR review comment:
Would it be possible to drop
Unpinsince this is already in a box anyway?
alexcrichton created PR review comment:
I'm a bit wary of making the implementation more generic than it already is, so would it be possible to drop these associated types and hardwire the trait objects? Or are these needed to multiplex the p2/p3 implementation?
alexcrichton created PR review comment:
Could you explain a bit more as to why this is necessary?
I forget the matrix of types/traits involved here, but I would naively expect that
&mut WasiImpl<Self>is basically equivalent toWasiImpl<&mut Self>
alexcrichton created PR review comment:
My guess is "no" given the litany of implementations we have, but in such a case could documentation be added that this is basically a mirror of what's in libstd? Also is it worth trying to add a blanket
impl<T: std::IsTerminal> wasi::IsTermainal for Timpl?
rvolosatovs submitted PR review.
rvolosatovs created PR review comment:
We cannot use the
std::io::IsTerminal, because it's sealed: https://github.com/rust-lang/rust/blob/f8f6997469237299c1d60814c7b9828602a1f8e4/library/std/src/io/stdio.rs#L1197Unfortunately, largely because of that, blanket implementations for
Talso do not appear to be possible.For example:
error[E0119]: conflicting implementations of trait `cli::IsTerminal` for type `tokio::io::Stderr` --> crates/wasi/src/cli.rs:126:1 | 66 | impl<T: std::io::IsTerminal> IsTerminal for T { | --------------------------------------------- first implementation here ... 126 | impl IsTerminal for tokio::io::Stderr { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `tokio::io::Stderr` | = note: upstream crates may add a new impl of trait `std::sealed::Sealed` for type `tokio::io::Stderr` in future versions = note: upstream crates may add a new impl of trait `std::io::IsTerminal` for type `tokio::io::Stderr` in future versions
tokio::io::Stderrcannot implementstd::io::IsTerminal, because it's sealed and we cannot implementwasmtime_wasi::cli::IsTerminalfor it if we provide a blanket implementation forstd::io::IsTerminal
rvolosatovs submitted PR review.
rvolosatovs created PR review comment:
Depends, if these per-proposal "View" traits are adopted by
p2implementation, then the associated types would be used for exactly this purpose. Currently, only the p3 implementation uses these traits.I'll move this trait to
wasmtime_wasi::p3::cli::WasiCliViewwithout the associated types for now and maybe we can revisit once we have all of WASI implemented in this repo.
rvolosatovs submitted PR review.
rvolosatovs created PR review comment:
I was hoping for that as well, but I've spent roughly 1h actively working on it and roughly an hour more trying things out while in meetings, but I could not figure it out without significant API changes.
What I'd like to get from this implementation:
- be able to select a proposal to link (
wasi:cliin this case) and:
- only implement parts relevant for that proposal (
WasiCliViewinstead ofWasiView)- add symbols to linker using a familiar API (
wasmtime_wasi::p3::cli::add_to_linker) without having to resort to lower-level, generatedwasmtime_wasi::p3::bindings::wasi::cli::*per-interface functions - which is error prone, tedious and introduces additional maintenance burden- be able to link all of WASI, i.e. implement
WasiViewand callwasmtime_wasi::p3::add_to_linkerThe convention is that we implement interfaces for
WasiCliImpl<T>, whereT: WasiCliView. The challenge then in the likes of: https://github.com/bytecodealliance/wasmtime/blob/90ab7916a996a38dc405b1ff861c7c137ed230a7/crates/wasi/src/p3/clocks/mod.rs#L74We need a
WasiCliImpl(&mut T), whereTimplementsWasiCliView, but I don't see a way to acquire such aT, when we start withWasiView. I can't do a|v| &mut WasiImpl(v), since that would create an intermediate reference, which would be immediately dropped. I don't see a way to thread the lifetime through in a way that supports two different traits directly here.
We also currently have a separate trait for getting the resource table and we cannot call bothWasiCliView::cliandResourceView::tableinside the closure, since that would make us mutably borrow twiceThere are workarounds though:
- Have
WasiCliView::clireturn a tuple(&mut WasiCliCtx, &mut ResourceTable)- Store
ResourceTableinWasiCliCtxThis morning I actually got another idea, which I'm going to try now:
WasiCliCtxView<'a>, which would have to&mutborrows,&mut WasiCliCtxand&mut ResourceTable, soWasiCliView::cliwould have to return that. A bit awkward to use, but potentially it could work and hopefully it'd only be required in this lower level/advanced use case API
rvolosatovs edited PR review comment.
rvolosatovs updated PR #11257.
rvolosatovs submitted PR review.
rvolosatovs created PR review comment:
It worked! No
WasiCliImpland no need for generics in the host implementations anymore
rvolosatovs updated PR #11257.
rvolosatovs updated PR #11257.
rvolosatovs updated PR #11257.
rvolosatovs updated PR #11257.
rvolosatovs commented on PR #11257:
Semantics of
wasi:clistdio are not completely clear to me at this point, so I don't want to spend too much time designing the API for it, especially since this interface will likely change soon. There's currently no out-of-the-box way to "capture" stdout/stderr, users will have to implement their own with synchronization (e.g. using aMutex)refs https://github.com/WebAssembly/wasi-cli/issues/65
refs https://github.com/WebAssembly/wasi-cli/issues/64
rvolosatovs edited a comment on PR #11257:
Semantics of
wasi:clistdio are not completely clear to me at this point, so I don't want to spend too much time designing the API for it, especially since this interface will likely change soon. There's currently no out-of-the-box way to "capture" stdout/stderr, users will have to implement their own with synchronization (e.g. using aMutex) for nowrefs https://github.com/WebAssembly/wasi-cli/issues/65
refs https://github.com/WebAssembly/wasi-cli/issues/64
rvolosatovs has marked PR #11257 as ready for review.
rvolosatovs requested wasmtime-wasi-reviewers for a review on PR #11257.
rvolosatovs requested alexcrichton for a review on PR #11257.
rvolosatovs requested wasmtime-core-reviewers for a review on PR #11257.
alexcrichton submitted PR review:
Nice I like how the changes worked out, thanks for pushing on it!
alexcrichton commented on PR #11257:
There's currently no out-of-the-box way to "capture" stdout/stderr
Agreed yeah this is ok for now. For anything else along these lines mind opening an issue for that? I'll open an issue for this one specifically
alexcrichton commented on PR #11257:
Oh while cargo vet I think was spurious the failure on Windows I think is valid which is this line. IIRC we set a few extra env vars for Windows for WASI testing
rvolosatovs updated PR #11257.
rvolosatovs has enabled auto merge for PR #11257.
rvolosatovs merged PR #11257.
Last updated: Dec 06 2025 at 07:03 UTC