wasmtime_wasi/p2/
mod.rs

1//! # Wasmtime's WASIp2 Implementation
2//!
3//!
4//! This module provides a Wasmtime host implementation of WASI 0.2 (aka WASIp2
5//! aka Preview 2) and WASI 0.1 (aka WASIp1 aka Preview 1). WASI is implemented
6//! with the Rust crates [`tokio`] and [`cap-std`] primarily, meaning that
7//! operations are implemented in terms of their native platform equivalents by
8//! default.
9//!
10//! # WASIp2 interfaces
11//!
12//! This module contains implementations of the following interfaces:
13//!
14//! * [`wasi:cli/environment`]
15//! * [`wasi:cli/exit`]
16//! * [`wasi:cli/stderr`]
17//! * [`wasi:cli/stdin`]
18//! * [`wasi:cli/stdout`]
19//! * [`wasi:cli/terminal-input`]
20//! * [`wasi:cli/terminal-output`]
21//! * [`wasi:cli/terminal-stderr`]
22//! * [`wasi:cli/terminal-stdin`]
23//! * [`wasi:cli/terminal-stdout`]
24//! * [`wasi:clocks/monotonic-clock`]
25//! * [`wasi:clocks/wall-clock`]
26//! * [`wasi:filesystem/preopens`]
27//! * [`wasi:filesystem/types`]
28//! * [`wasi:random/insecure-seed`]
29//! * [`wasi:random/insecure`]
30//! * [`wasi:random/random`]
31//! * [`wasi:sockets/instance-network`]
32//! * [`wasi:sockets/ip-name-lookup`]
33//! * [`wasi:sockets/network`]
34//! * [`wasi:sockets/tcp-create-socket`]
35//! * [`wasi:sockets/tcp`]
36//! * [`wasi:sockets/udp-create-socket`]
37//! * [`wasi:sockets/udp`]
38//!
39//! All traits are implemented in terms of a [`WasiView`] trait which provides
40//! access to [`WasiCtx`], which defines the configuration for WASI.
41//! The [`WasiView`] trait imples [`IoView`], which provides access to a common
42//! [`ResourceTable`], which owns all host-defined component model resources.
43//!
44//! The [`wasmtime-wasi-io`] crate contains implementations of the
45//! following interfaces, and this module reuses those implementations:
46//!
47//! * [`wasi:io/error`]
48//! * [`wasi:io/poll`]
49//! * [`wasi:io/streams`]
50//!
51//! These traits are implemented in terms of a [`IoView`] trait, which only
52//! provides access to a common [`ResourceTable`]. All aspects of
53//! `wasmtime-wasi-io` that are used by this module are re-exported. Unless you
54//! are implementing other host functionality that needs to interact with the
55//! WASI scheduler and don't want to use other functionality provided by
56//! `wasmtime-wasi`, you don't need to take a direct dependency on
57//! `wasmtime-wasi-io`.
58//!
59//! # Generated Bindings
60//!
61//! This module uses [`wasmtime::component::bindgen!`] to generate bindings for
62//! all WASI interfaces. Raw bindings are available in the [`bindings`] submodule
63//! of this module. Downstream users can either implement these traits themselves
64//! or you can use the built-in implementations in this module for
65//! `WasiImpl<T: WasiView>`.
66//!
67//! # The `WasiView` trait
68//!
69//! This module's implementation of WASI is done in terms of an implementation of
70//! [`WasiView`]. This trait provides a "view" into WASI-related state that is
71//! contained within a [`Store<T>`](wasmtime::Store). [`WasiView`] implies the
72//! [`IoView`] trait, which provides access to common [`ResourceTable`] which
73//! owns all host-implemented component model resources.
74//!
75//! For all of the generated bindings in this module (Host traits),
76//! implementations are provided looking like:
77//!
78//! ```
79//! # use wasmtime_wasi::p2::WasiImpl;
80//! # trait WasiView {}
81//! # mod bindings { pub mod wasi { pub trait Host {} } }
82//! impl<T: WasiView> bindings::wasi::Host for WasiImpl<T> {
83//!     // ...
84//! }
85//! ```
86//!
87//! The [`add_to_linker_sync`] and [`add_to_linker_async`] function then require
88//! that `T: WasiView` with [`Linker<T>`](wasmtime::component::Linker).
89//!
90//! To implement the [`WasiView`] and [`IoView`] trait you will first select a
91//! `T` to put in `Store<T>` (typically, by defining your own struct).
92//! Somewhere within `T` you'll store:
93//!
94//! * [`ResourceTable`] - created through default constructors.
95//! * [`WasiCtx`] - created through [`WasiCtxBuilder`].
96//!
97//! You'll then write implementations of the [`IoView`] and [`WasiView`]
98//! traits to access those items in your `T`. For example:
99//! ```
100//! use wasmtime::component::ResourceTable;
101//! use wasmtime_wasi::p2::{WasiCtx, IoView, WasiView};
102//! struct MyCtx {
103//!     table: ResourceTable,
104//!     wasi: WasiCtx,
105//! }
106//! impl IoView for MyCtx {
107//!     fn table(&mut self) -> &mut ResourceTable {
108//!         &mut self.table
109//!     }
110//! }
111//! impl WasiView for MyCtx {
112//!     fn ctx(&mut self) -> &mut WasiCtx {
113//!         &mut self.wasi
114//!     }
115//! }
116//!
117//! ```
118//!
119//! # Async and Sync
120//!
121//! As of WASI0.2, WASI functions are not blocking from WebAssembly's point of
122//! view: a WebAssembly call into these functions returns when they are
123//! complete.
124//!
125//! This module provides an implementation of those functions in the host,
126//! where for some functions, it is appropriate to implement them using
127//! async Rust and the Tokio executor, so that the host implementation can be
128//! nonblocking when Wasmtime's [`Config::async_support`][async] is set.
129//! Synchronous wrappers are provided for all async implementations, which
130//! creates a private Tokio executor.
131//!
132//! Users can choose between these modes of implementation using variants
133//! of the add_to_linker functions:
134//!
135//! * For non-async users (the default of `Config`), use [`add_to_linker_sync`].
136//! * For async users, use [`add_to_linker_async`].
137//!
138//! Note that bindings are generated once for async and once for sync. Most
139//! interfaces do not change, however, so only interfaces with blocking
140//! functions have bindings generated twice. Bindings are organized as:
141//!
142//! * [`bindings`] - default location of all bindings, blocking functions are
143//!   `async`
144//! * [`bindings::sync`] - blocking interfaces have synchronous versions here.
145//!
146//! # Module-specific traits
147//!
148//! This module's default implementation of WASI bindings to native primitives
149//! for the platform that it is compiled for. For example opening a TCP socket
150//! uses the native platform to open a TCP socket (so long as [`WasiCtxBuilder`]
151//! allows it). There are a few important traits, however, that are specific to
152//! this module.
153//!
154//! * [`InputStream`] and [`OutputStream`] - these are the host traits
155//!   behind the WASI `input-stream` and `output-stream` types in the
156//!   `wasi:io/streams` interface. These enable embedders to build their own
157//!   custom stream and insert them into a [`ResourceTable`] (as a boxed trait
158//!   object, see [`DynInputStream`] and [`DynOutputStream`]) to be used from
159//!   wasm.
160//!
161//! * [`Pollable`] - this trait enables building arbitrary logic to get hooked
162//!   into a `pollable` resource from `wasi:io/poll`. A pollable resource is
163//!   created through the [`subscribe`] function.
164//!
165//! * [`HostWallClock`](crate::HostWallClock) and [`HostMonotonicClock`](crate::HostMonotonicClock) are used in conjunction with
166//!   [`WasiCtxBuilder::wall_clock`] and [`WasiCtxBuilder::monotonic_clock`] if
167//!   the defaults host's clock should not be used.
168//!
169//! * [`StdinStream`] and [`StdoutStream`] are used to provide custom
170//!   stdin/stdout streams if they're not inherited (or null, which is the
171//!   default).
172//!
173//! These traits enable embedders to customize small portions of WASI interfaces
174//! provided while still providing all other interfaces.
175//!
176//! # Examples
177//!
178//! Usage of this module is done through a few steps to get everything hooked up:
179//!
180//! 1. First implement [`IoView`] and [`WasiView`] for your type which is the
181//!    `T` in `Store<T>`.
182//! 2. Add WASI interfaces to a `wasmtime::component::Linker<T>`. This is either
183//!    done through top-level functions like [`add_to_linker_sync`] or through
184//!    individual `add_to_linker` functions in generated bindings throughout
185//!    this module.
186//! 3. Create a [`WasiCtx`] for each `Store<T>` through [`WasiCtxBuilder`]. Each
187//!    WASI context is "null" or "empty" by default, so items must be explicitly
188//!    added to get accessed by wasm (such as env vars or program arguments).
189//! 4. Use the previous `Linker<T>` to instantiate a `Component` within a
190//!    `Store<T>`.
191//!
192//! For examples see each of [`WasiView`], [`WasiCtx`], [`WasiCtxBuilder`],
193//! [`add_to_linker_sync`], and [`bindings::Command`].
194//!
195//! [`wasmtime::component::bindgen!`]: https://docs.rs/wasmtime/latest/wasmtime/component/macro.bindgen.html
196//! [`tokio`]: https://crates.io/crates/tokio
197//! [`cap-std`]: https://crates.io/crates/cap-std
198//! [`wasmtime-wasi-io`]: https://crates.io/crates/wasmtime-wasi-io
199//! [`wasi:cli/environment`]: bindings::cli::environment::Host
200//! [`wasi:cli/exit`]: bindings::cli::exit::Host
201//! [`wasi:cli/stderr`]: bindings::cli::stderr::Host
202//! [`wasi:cli/stdin`]: bindings::cli::stdin::Host
203//! [`wasi:cli/stdout`]: bindings::cli::stdout::Host
204//! [`wasi:cli/terminal-input`]: bindings::cli::terminal_input::Host
205//! [`wasi:cli/terminal-output`]: bindings::cli::terminal_output::Host
206//! [`wasi:cli/terminal-stdin`]: bindings::cli::terminal_stdin::Host
207//! [`wasi:cli/terminal-stdout`]: bindings::cli::terminal_stdout::Host
208//! [`wasi:cli/terminal-stderr`]: bindings::cli::terminal_stderr::Host
209//! [`wasi:clocks/monotonic-clock`]: bindings::clocks::monotonic_clock::Host
210//! [`wasi:clocks/wall-clock`]: bindings::clocks::wall_clock::Host
211//! [`wasi:filesystem/preopens`]: bindings::filesystem::preopens::Host
212//! [`wasi:filesystem/types`]: bindings::filesystem::types::Host
213//! [`wasi:io/error`]: wasmtime_wasi_io::bindings::wasi::io::error::Host
214//! [`wasi:io/poll`]: wasmtime_wasi_io::bindings::wasi::io::poll::Host
215//! [`wasi:io/streams`]: wasmtime_wasi_io::bindings::wasi::io::streams::Host
216//! [`wasi:random/insecure-seed`]: bindings::random::insecure_seed::Host
217//! [`wasi:random/insecure`]: bindings::random::insecure::Host
218//! [`wasi:random/random`]: bindings::random::random::Host
219//! [`wasi:sockets/instance-network`]: bindings::sockets::instance_network::Host
220//! [`wasi:sockets/ip-name-lookup`]: bindings::sockets::ip_name_lookup::Host
221//! [`wasi:sockets/network`]: bindings::sockets::network::Host
222//! [`wasi:sockets/tcp-create-socket`]: bindings::sockets::tcp_create_socket::Host
223//! [`wasi:sockets/tcp`]: bindings::sockets::tcp::Host
224//! [`wasi:sockets/udp-create-socket`]: bindings::sockets::udp_create_socket::Host
225//! [`wasi:sockets/udp`]: bindings::sockets::udp::Host
226//! [async]: https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.async_support
227//! [`ResourceTable`]: wasmtime::component::ResourceTable
228
229use wasmtime::component::{HasData, Linker};
230
231pub mod bindings;
232mod ctx;
233pub(crate) mod filesystem;
234mod host;
235mod ip_name_lookup;
236mod network;
237pub mod pipe;
238mod poll;
239mod stdio;
240mod tcp;
241mod udp;
242mod view;
243mod write_stream;
244
245pub use self::ctx::{WasiCtx, WasiCtxBuilder};
246pub use self::filesystem::{FileInputStream, FsError, FsResult};
247pub use self::network::{SocketError, SocketResult};
248pub use self::stdio::{
249    stderr, stdin, stdout, AsyncStdinStream, AsyncStdoutStream, IsATTY, OutputFile, Stderr, Stdin,
250    StdinStream, Stdout, StdoutStream,
251};
252pub use self::view::{WasiImpl, WasiView};
253// These contents of wasmtime-wasi-io are re-exported by this module for compatibility:
254// they were originally defined in this module before being factored out, and many
255// users of this module depend on them at these names.
256pub use wasmtime_wasi_io::poll::{subscribe, DynFuture, DynPollable, MakeFuture, Pollable};
257pub use wasmtime_wasi_io::streams::{
258    DynInputStream, DynOutputStream, Error as IoError, InputStream, OutputStream, StreamError,
259    StreamResult,
260};
261pub use wasmtime_wasi_io::{IoImpl, IoView};
262
263/// Add all WASI interfaces from this crate into the `linker` provided.
264///
265/// This function will add the `async` variant of all interfaces into the
266/// [`Linker`] provided. By `async` this means that this function is only
267/// compatible with [`Config::async_support(true)`][async]. For embeddings with
268/// async support disabled see [`add_to_linker_sync`] instead.
269///
270/// This function will add all interfaces implemented by this crate to the
271/// [`Linker`], which corresponds to the `wasi:cli/imports` world supported by
272/// this crate.
273///
274/// [async]: wasmtime::Config::async_support
275///
276/// # Example
277///
278/// ```
279/// use wasmtime::{Engine, Result, Store, Config};
280/// use wasmtime::component::{ResourceTable, Linker};
281/// use wasmtime_wasi::p2::{IoView, WasiCtx, WasiView, WasiCtxBuilder};
282///
283/// fn main() -> Result<()> {
284///     let mut config = Config::new();
285///     config.async_support(true);
286///     let engine = Engine::new(&config)?;
287///
288///     let mut linker = Linker::<MyState>::new(&engine);
289///     wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
290///     // ... add any further functionality to `linker` if desired ...
291///
292///     let mut builder = WasiCtxBuilder::new();
293///
294///     // ... configure `builder` more to add env vars, args, etc ...
295///
296///     let mut store = Store::new(
297///         &engine,
298///         MyState {
299///             ctx: builder.build(),
300///             table: ResourceTable::new(),
301///         },
302///     );
303///
304///     // ... use `linker` to instantiate within `store` ...
305///
306///     Ok(())
307/// }
308///
309/// struct MyState {
310///     ctx: WasiCtx,
311///     table: ResourceTable,
312/// }
313///
314/// impl IoView for MyState {
315///     fn table(&mut self) -> &mut ResourceTable { &mut self.table }
316/// }
317/// impl WasiView for MyState {
318///     fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx }
319/// }
320/// ```
321pub fn add_to_linker_async<T: WasiView + 'static>(linker: &mut Linker<T>) -> anyhow::Result<()> {
322    let options = bindings::LinkOptions::default();
323    add_to_linker_with_options_async(linker, &options)
324}
325
326/// Similar to [`add_to_linker_async`], but with the ability to enable unstable features.
327pub fn add_to_linker_with_options_async<T: WasiView + 'static>(
328    linker: &mut Linker<T>,
329    options: &bindings::LinkOptions,
330) -> anyhow::Result<()> {
331    wasmtime_wasi_io::add_to_linker_async(linker)?;
332    add_nonblocking_to_linker(linker, options)?;
333
334    let l = linker;
335    let f: fn(&mut T) -> WasiImpl<&mut T> = |t| WasiImpl(IoImpl(t));
336    bindings::filesystem::types::add_to_linker::<T, HasWasi<T>>(l, f)?;
337    bindings::sockets::tcp::add_to_linker::<T, HasWasi<T>>(l, f)?;
338    bindings::sockets::udp::add_to_linker::<T, HasWasi<T>>(l, f)?;
339    Ok(())
340}
341
342/// Shared functionality for [`add_to_linker_async`] and [`add_to_linker_sync`].
343fn add_nonblocking_to_linker<'a, T: WasiView + 'static, O>(
344    linker: &mut Linker<T>,
345    options: &'a O,
346) -> anyhow::Result<()>
347where
348    bindings::sockets::network::LinkOptions: From<&'a O>,
349    bindings::cli::exit::LinkOptions: From<&'a O>,
350{
351    use crate::p2::bindings::{cli, clocks, filesystem, random, sockets};
352
353    let l = linker;
354    let f: fn(&mut T) -> WasiImpl<&mut T> = |t| WasiImpl(IoImpl(t));
355    clocks::wall_clock::add_to_linker::<T, HasWasi<T>>(l, f)?;
356    clocks::monotonic_clock::add_to_linker::<T, HasWasi<T>>(l, f)?;
357    filesystem::preopens::add_to_linker::<T, HasWasi<T>>(l, f)?;
358    random::random::add_to_linker::<T, HasWasi<T>>(l, f)?;
359    random::insecure::add_to_linker::<T, HasWasi<T>>(l, f)?;
360    random::insecure_seed::add_to_linker::<T, HasWasi<T>>(l, f)?;
361    cli::exit::add_to_linker::<T, HasWasi<T>>(l, &options.into(), f)?;
362    cli::environment::add_to_linker::<T, HasWasi<T>>(l, f)?;
363    cli::stdin::add_to_linker::<T, HasWasi<T>>(l, f)?;
364    cli::stdout::add_to_linker::<T, HasWasi<T>>(l, f)?;
365    cli::stderr::add_to_linker::<T, HasWasi<T>>(l, f)?;
366    cli::terminal_input::add_to_linker::<T, HasWasi<T>>(l, f)?;
367    cli::terminal_output::add_to_linker::<T, HasWasi<T>>(l, f)?;
368    cli::terminal_stdin::add_to_linker::<T, HasWasi<T>>(l, f)?;
369    cli::terminal_stdout::add_to_linker::<T, HasWasi<T>>(l, f)?;
370    cli::terminal_stderr::add_to_linker::<T, HasWasi<T>>(l, f)?;
371    sockets::tcp_create_socket::add_to_linker::<T, HasWasi<T>>(l, f)?;
372    sockets::udp_create_socket::add_to_linker::<T, HasWasi<T>>(l, f)?;
373    sockets::instance_network::add_to_linker::<T, HasWasi<T>>(l, f)?;
374    sockets::network::add_to_linker::<T, HasWasi<T>>(l, &options.into(), f)?;
375    sockets::ip_name_lookup::add_to_linker::<T, HasWasi<T>>(l, f)?;
376    Ok(())
377}
378
379/// Same as [`add_to_linker_async`] except that this only adds interfaces
380/// present in the `wasi:http/proxy` world.
381pub fn add_to_linker_proxy_interfaces_async<T: WasiView + 'static>(
382    linker: &mut Linker<T>,
383) -> anyhow::Result<()> {
384    wasmtime_wasi_io::add_to_linker_async(linker)?;
385    add_proxy_interfaces_nonblocking(linker)
386}
387
388/// Same as [`add_to_linker_sync`] except that this only adds interfaces
389/// present in the `wasi:http/proxy` world.
390#[doc(hidden)]
391pub fn add_to_linker_proxy_interfaces_sync<T: WasiView + 'static>(
392    linker: &mut Linker<T>,
393) -> anyhow::Result<()> {
394    add_sync_wasi_io(linker)?;
395    add_proxy_interfaces_nonblocking(linker)
396}
397
398fn add_proxy_interfaces_nonblocking<T: WasiView + 'static>(
399    linker: &mut Linker<T>,
400) -> anyhow::Result<()> {
401    use crate::p2::bindings::{cli, clocks, random};
402
403    let l = linker;
404    let f: fn(&mut T) -> WasiImpl<&mut T> = |t| WasiImpl(IoImpl(t));
405    clocks::wall_clock::add_to_linker::<T, HasWasi<T>>(l, f)?;
406    clocks::monotonic_clock::add_to_linker::<T, HasWasi<T>>(l, f)?;
407    random::random::add_to_linker::<T, HasWasi<T>>(l, f)?;
408    cli::stdin::add_to_linker::<T, HasWasi<T>>(l, f)?;
409    cli::stdout::add_to_linker::<T, HasWasi<T>>(l, f)?;
410    cli::stderr::add_to_linker::<T, HasWasi<T>>(l, f)?;
411    Ok(())
412}
413
414/// Add all WASI interfaces from this crate into the `linker` provided.
415///
416/// This function will add the synchronous variant of all interfaces into the
417/// [`Linker`] provided. By synchronous this means that this function is only
418/// compatible with [`Config::async_support(false)`][async]. For embeddings
419/// with async support enabled see [`add_to_linker_async`] instead.
420///
421/// This function will add all interfaces implemented by this crate to the
422/// [`Linker`], which corresponds to the `wasi:cli/imports` world supported by
423/// this crate.
424///
425/// [async]: wasmtime::Config::async_support
426///
427/// # Example
428///
429/// ```
430/// use wasmtime::{Engine, Result, Store, Config};
431/// use wasmtime::component::{ResourceTable, Linker};
432/// use wasmtime_wasi::p2::{IoView, WasiCtx, WasiView, WasiCtxBuilder};
433///
434/// fn main() -> Result<()> {
435///     let engine = Engine::default();
436///
437///     let mut linker = Linker::<MyState>::new(&engine);
438///     wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
439///     // ... add any further functionality to `linker` if desired ...
440///
441///     let mut builder = WasiCtxBuilder::new();
442///
443///     // ... configure `builder` more to add env vars, args, etc ...
444///
445///     let mut store = Store::new(
446///         &engine,
447///         MyState {
448///             ctx: builder.build(),
449///             table: ResourceTable::new(),
450///         },
451///     );
452///
453///     // ... use `linker` to instantiate within `store` ...
454///
455///     Ok(())
456/// }
457///
458/// struct MyState {
459///     ctx: WasiCtx,
460///     table: ResourceTable,
461/// }
462/// impl IoView for MyState {
463///     fn table(&mut self) -> &mut ResourceTable { &mut self.table }
464/// }
465/// impl WasiView for MyState {
466///     fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx }
467/// }
468/// ```
469pub fn add_to_linker_sync<T: WasiView + 'static>(
470    linker: &mut wasmtime::component::Linker<T>,
471) -> anyhow::Result<()> {
472    let options = bindings::sync::LinkOptions::default();
473    add_to_linker_with_options_sync(linker, &options)
474}
475
476/// Similar to [`add_to_linker_sync`], but with the ability to enable unstable features.
477pub fn add_to_linker_with_options_sync<T: WasiView + 'static>(
478    linker: &mut wasmtime::component::Linker<T>,
479    options: &bindings::sync::LinkOptions,
480) -> anyhow::Result<()> {
481    add_nonblocking_to_linker(linker, options)?;
482    add_sync_wasi_io(linker)?;
483
484    let l = linker;
485    let f: fn(&mut T) -> WasiImpl<&mut T> = |t| WasiImpl(IoImpl(t));
486    bindings::sync::filesystem::types::add_to_linker::<T, HasWasi<T>>(l, f)?;
487    bindings::sync::sockets::tcp::add_to_linker::<T, HasWasi<T>>(l, f)?;
488    bindings::sync::sockets::udp::add_to_linker::<T, HasWasi<T>>(l, f)?;
489    Ok(())
490}
491
492/// Shared functionality of [`add_to_linker_sync`]` and
493/// [`add_to_linker_proxy_interfaces_sync`].
494fn add_sync_wasi_io<T: WasiView + 'static>(
495    linker: &mut wasmtime::component::Linker<T>,
496) -> anyhow::Result<()> {
497    let l = linker;
498    let f: fn(&mut T) -> IoImpl<&mut T> = |t| IoImpl(t);
499    wasmtime_wasi_io::bindings::wasi::io::error::add_to_linker::<T, HasIo<T>>(l, f)?;
500    bindings::sync::io::poll::add_to_linker::<T, HasIo<T>>(l, f)?;
501    bindings::sync::io::streams::add_to_linker::<T, HasIo<T>>(l, f)?;
502    Ok(())
503}
504
505struct HasIo<T>(T);
506
507impl<T: 'static> HasData for HasIo<T> {
508    type Data<'a> = IoImpl<&'a mut T>;
509}
510
511struct HasWasi<T>(T);
512
513impl<T: 'static> HasData for HasWasi<T> {
514    type Data<'a> = WasiImpl<&'a mut T>;
515}