Stream: wasmtime

Topic: Meeting with the Rust Lang Team


view this post on Zulip Yosh Wuyts (Aug 06 2025 at 17:22):

Hey all, following up on my question a few weeks ago: the Rust lang team would be happy to meet to talk about limitations in the language that currently affect Wasmtime. The date they've proposed for that is , scheduled for 90 mins.

view this post on Zulip Yosh Wuyts (Aug 06 2025 at 17:26):

For Wasmtime maintainers: can y'all make this date?

view this post on Zulip Yosh Wuyts (Aug 06 2025 at 17:29):

Once we confirm the date, I'm happy to take point on writing up a doc for the meeting. My hope for the outcome of this meeting is that the Rust language team can walk away with a healthy set of use cases and problems, which can then be used to motivate language features which resolve those limitations.

view this post on Zulip Alex Crichton (Aug 06 2025 at 23:34):

I can make the date as well, and in the meantime I'm going to drop some loose notes here about what we can talk about. I'm a bit intimidated to take up 90m of the lang team's time just for us in the sense that I'm not sure our feedback is worth so much time, but I figure we can collect things first to better gauge if it'll be worth it. The things that I can think of are:

become

On the top of my head because I just saw it, but our Pulley interpreter in "tail loop" mode requires the become keyword. Right now we have a #[cfg] to switch between a "match loop" and a "tail loop" but it'd be nice to commit to just one. This isn't entirely on Rust though, we have what we need to evaluate become and we mostly just haven't put in all the legwork to say with confidence "yep this is what we want"

Non-overwritable &mut T

We have a problem where host functions get &mut Store<T> more-or-less, but the problem is that it's not sound to do something like *the_store = Store::new(some_ctor()). To work around this we have our own type StoreContextMut<'_, T> which internally holds &mut Store<T>. This has decent enough ergonomics for external users given enough trait impls, but it has pretty awful ergonomics internally within Wasmtime. It'd be much nicer to "just use &mut Thing".

Read-only fields (unsafe fields?)

We're (ab)using Pin right now to make it unsafe to get a &mut vm::Instance right now. It's not really about self-referential types at all, we just want to make it unsafe to get a &mut vm::Instance because it's not safe to mutate some fields. This works well-enough but it's a roundabout solution for what we want which is to disallow mutation of a field after creation (or overwriting it?). Or maybe require unsafe access to a field which would disallow overwriting the whole structure? Unsure.

Pin ergonomics

Given above we're using Pin internally but the ergonomics are not great:

(I don't think any of this is news to the lang team)

Non-leakable types

For Rust-compiled-to-wasm the component model has async support now which is, if you squint enough, io-uring like in that you give a region of memory to the host and it fills it in later. Rust's "any type is safe to leak" forces safe bindings to always pass everything by ownership which is a bit of a bummer. Not that adding non-leak types is easy of course, but if we're listing out everything may as well list it out.

where F: AsyncFn(), F(..): Send

We more-or-less can't use AsyncFn* anywhere unless we can bound the return type. A well-known issue but we can add fuel to the fire maybe.

fn(T) is not 'static unless T: 'static

Feels weird to us (shouldn't require T: 'static), but we don't know if it's intentional or not. Would be nice if it weren't the case, but it's also not the end of the world to us.

dyn-compatible async fn

We've got a number of usages of #[async_trait] specifically for dyn-compatibility. Again not an easy ask by any means but like above maybe we can add fuel to the fire.

Esoteric reasons we still have C code in Wasmtime/wit-bindgen

Calling a &mut self method with access to a subset of fields

We've got a giant Store<T> type which is passed everywhere internally within Wasmtime. More and more methods need simultaneous borrows to multiple fields in this type, but in an effort to keep the implementation details private we keep adding more and more methods for various permutations of fields. It'd be nice if we could call "base methods" where each method accesses a disjoint set of fields. Like many above this is a well-known problem in Rust I believe.

Wasm proc macros

Rustc should have more wasm in it :smiling_face_with_horns:

(this is a joke, not a serious ask)

view this post on Zulip Alex Crichton (Aug 06 2025 at 23:35):

that's at least what's on my head right now, and I'm not sure it'd make sense to explicitly talk about all of these during such a meeting. Some I think we could explain our use case more to help design (e.g. &mut self and subsets of fields) but others are just a "yep someone still wants this" (e.g. F(..): Send).

If we do move forward with this list I would also want to compile a similar list which is "all the stuff added to Rust since Wasmtime started which we're very happy to be using". I think it'd be worth outlining all the historical major features too

view this post on Zulip Yosh Wuyts (Aug 07 2025 at 00:37):

I'm a bit intimidated to take up 90m of the lang team's time just for us in the sense that I'm not sure our feedback is worth so much time, but I figure we can collect things first to better gauge if it'll be worth it.

Hah, so - I really wouldn't worry about that. Just from the conversations you and I have had, I know that the time spent with the lang team would be worth it.

view this post on Zulip Yosh Wuyts (Aug 07 2025 at 00:39):

Thank you so much for the list so far btw! These are all great so far!

view this post on Zulip Yosh Wuyts (Aug 07 2025 at 00:40):

Loving the idea of also calling out some of the bigger wins the language has provided - that kind of feedback is also quite rare

view this post on Zulip Pat Hickey (Aug 07 2025 at 01:17):

I’m not sure where the whole “Send is infectious through the whole wasmtime API and we basically can’t stomach supporting non-Send embeddings, they just have to deal with it (usually by lying to the type checker” issue fits into Alex’s list but that’s the biggest one for me. I also don’t really feel like I know how to present that in a way that makes good use of their time. Alex can represent it better than me. I’d be grateful just to listen in.

view this post on Zulip Alex Crichton (Aug 07 2025 at 03:10):

Oh actually now that I look at the calendar for real I would be unable to make that slot as Fermyon has its off-site then, would it be possible to use the slot after?

Also good point Pat that's a good one to include on the list

view this post on Zulip Yosh Wuyts (Aug 07 2025 at 13:08):

will include!

view this post on Zulip Yosh Wuyts (Aug 07 2025 at 13:09):

Messaged the lang team back; I think that means this is going to need to be bumped back to the next planning cycle.

view this post on Zulip Alex Crichton (Aug 07 2025 at 22:13):

Writing down those prior thoughts:

Infectiousness of Send with async

Wasmtime's current async support effectively ends up meaning that we require Send on pretty much everything. There's no way currently to use Wasmtime in a non-Send context or a single-threaded async executor. Unsure what a solution would look like, but it's something we've come up against.

Generic parameters in constant expressions

We've run into this not compiling:

trait A {
    const N: usize;

    fn foo(&self, slice: &[u8; Self::N]);
}

and it'd be a nice simplification of canonical ABI lifting/lowering if were were able to express this

view this post on Zulip Yosh Wuyts (Aug 08 2025 at 16:21):

Alex Crichton said:

Oh actually now that I look at the calendar for real I would be unable to make that slot as Fermyon has its off-site then, would it be possible to use the slot after?

Also good point Pat that's a good one to include on the list

lang team seems happy to push the meeting by a week (still waiting on final confirmation tho) - are y'all able to make ?

view this post on Zulip Alex Crichton (Aug 08 2025 at 16:33):

Works for me :+1:

view this post on Zulip fitzgen (he/him) (Aug 08 2025 at 17:15):

works for me as well

view this post on Zulip fitzgen (he/him) (Aug 08 2025 at 22:30):

another thing to talk about: better language tools for bitpacking enums and arbitrary bit width integers

see CompileKey (soon to be renamed to FuncKey) and wasmparser's RefType and PackedIndex and UnpackedIndex and cranelift_entity's PackedOption

view this post on Zulip Chris Fallin (Aug 11 2025 at 15:09):

bitpacking enums

A few more examples that are interesting: ValueData in Cranelift's DFG, which is a four-way enum; and Operand in regalloc2, which has a bunch of fields and cannot just be divided into arbitrary bitwidth fields (steals bits from some fields when upper bits of the discriminant are in some states for more sub-discriminant)

Also one more topic: representing ownership to avoid dynamic checks. We currently have a bunch of dynamic "is same engine" and "is same store" checks, out of necessity, because our index-based handles could otherwise lead to incorrectness. We would need "generative" or "path-dependent" or "place-based" types/lifetimes to statically encode, in the types, that e.g. an Instance is associated with a particular engine, and ensure only values from the same engine interact; Rust's type system today mostly can't do this. (Gankra's masters thesis contains a neat closure-trick that is technically generative within the scope of a closure, but would be completely unergonomic in our APIs.) I know the Rust community generally is thinking about this; and Niko has a blog post that mentions "place-based lifetimes" that is a step in the direction. I wrote up a random idea last year (but haven't seriously pursued it); in general I'd just be curious if this problem has further thoughts from the lang-team, and emphasize that it occurs in practice and leads to dynamic checks.

view this post on Zulip fitzgen (he/him) (Aug 20 2025 at 18:37):

Another thing to talk about: how to make Pulley and threads work with Rust's memory model

Forcibly disable the threads proposal for Pulley. This is done because I don't believe there's any way that we can, in Rust, implement non-atomic loads and stores in a manner that isn't...
Browse the publicly accessible channels in rust-lang without logging in.

view this post on Zulip Pat Hickey (Aug 27 2025 at 18:07):

topic: x86_64-unknown-none softfloat abi is a problem, can we have an otherwise identical target with the "regular" float abi? or can we stabilize build-std?

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 11:00):

Reminder for Wasmtime maintainers: the meeting with the Rust language team is this Wednesday at . The meeting lasts 90 mins: the first 30 mins are spent reading a doc and writing out questions, which is then followed by 60 mins of discussion.

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 11:01):

I'll send through a hackmd doc later today, which will includes everything posted in this thread so far + other items from individual conversations.

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 11:03):

If anyone has any other items they haven't seen mentioned yet in this thread, you're welcome to share them! - We should have more than plenty to fill out an hour's worth of conversation already though. So don't feel like you have to.

view this post on Zulip Alex Crichton (Sep 29 2025 at 14:22):

Looking forward to it! Also happy to help out with editing the doc too

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 17:36):

First pass of the doc is done: https://hackmd.io/@yoshuawuyts/HkW6fBd2le

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 17:36):

I think we could probably do with some more code examples and links

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 17:36):

I still need to reformat some things too

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 17:37):

@Pat Hickey if you have the time, can I ask you to elaborate on the softfloat target topic in the doc?

view this post on Zulip Pat Hickey (Sep 29 2025 at 17:44):

thats more of a @Chris Fallin / @fitzgen (he/him) topic

view this post on Zulip Chris Fallin (Sep 29 2025 at 17:54):

@Yosh Wuyts So the issue is that we embed Wasmtime in an x86-64 Linux process with very special requirements, namely that it cannot make syscalls; others embed Wasmtime in their own bespoke x86-64 environments with no OS or custom OS functionality. For all these cases, the usual approach would be to compile for x86_64-unknown-none, which is a no_std target. That's all well and good except that that target has an ABI that assumes softfloat: vector registers are not available at all and all FP values go through software implementations of operators. Usually in these environments we've done the legwork to be able to actually use the ordinary hardware float ABI.

So it's a pretty simple mechanical plumbing thing, but basically we end up needing is a custom target.

Where this gets weird/interesting is that custom targets are nightly-only, so our current plan is just to require a nightly compiler, but that sucks, especially in a corporate environment where new things are already seen as suspicious and unstable.

The concrete ask for rustlang as a whole would be to stabilize -Zbuild-std so custom targets can work at the same level as built-in targets for no_std code that uses core/alloc. That may or may not be a lang-team thing but I guess Pat brought it up because it's a real impediment for adoption

view this post on Zulip Ralph (Sep 29 2025 at 18:01):

it is the kind of thing that Microsoft Corporate would like to see, certainly, if an example is required.....

view this post on Zulip fitzgen (he/him) (Sep 29 2025 at 18:02):

I added a paragraph to the doc, feel free to expand/edit it

view this post on Zulip Alex Crichton (Sep 29 2025 at 18:25):

Did a pass and edited some things. Chris/Nick y'all might want to expand on the bitpacking part

view this post on Zulip Alex Crichton (Sep 29 2025 at 18:27):

I also added this to the intro:

Below is a listing of topics that the Wasmtime team has brainstormed about possible discussion points with T-lang. Most of these are centered around things we've run into when implementing Wasmtime itself in Rust. This is, however, also a great opportunity if T-lang would like to pick our own brains about wasm support and how it relates to Rust. We're of course willing to chat about anything related to wasm and development of the standard and such!

view this post on Zulip fitzgen (he/him) (Sep 29 2025 at 19:26):

Alex Crichton said:

Chris/Nick y'all might want to expand on the bitpacking part

done

view this post on Zulip Alex Crichton (Sep 29 2025 at 19:47):

Also, logistics-wise, how will we join?

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 21:18):

Alex Crichton said:

Also, logistics-wise, how will we join?

At the meeting time, join https://meet.jit.si/ferris-rules

Join a WebRTC video conference powered by the Jitsi Videobridge

view this post on Zulip Yosh Wuyts (Sep 29 2025 at 21:18):

(Will take a look at the updated doc tomorrow!)

view this post on Zulip Yosh Wuyts (Sep 30 2025 at 16:30):

@fitzgen (he/him) could I ask you to expand a little on the Pulley + Atomics section? I'm reading the explainer and the links, and I'm missing:

view this post on Zulip Alex Crichton (Sep 30 2025 at 16:31):

oh I can take care of that b/c I added most of that

view this post on Zulip Yosh Wuyts (Sep 30 2025 at 16:31):

ty ty!

view this post on Zulip Yosh Wuyts (Sep 30 2025 at 16:33):

okay, finished reading over the doc! - tysm for all the changes and edits, I think this looks great, and will give us a lot to talk about tomorrow!

view this post on Zulip Yosh Wuyts (Oct 01 2025 at 18:58):

I think the meeting went really well. Thank you all for joining!


Last updated: Dec 06 2025 at 06:05 UTC