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.
For Wasmtime maintainers: can y'all make this date?
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.
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:
becomeOn 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"
&mut TWe 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".
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.
Given above we're using Pin internally but the ergonomics are not great:
self.as_mut().thing(...)mut self: Pin<&mut Self> is a mouthfulunsafe or integration of foreign crates, just a bit awkward(I don't think any of this is news to the lang team)
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(..): SendWe 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: 'staticFeels 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.
async fnWe'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.
setjmp in Rust safely#[export_name] isn't sufficient)&mut self method with access to a subset of fieldsWe'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.
Rustc should have more wasm in it :smiling_face_with_horns:
(this is a joke, not a serious ask)
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
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.
Thank you so much for the list so far btw! These are all great so far!
Loving the idea of also calling out some of the bigger wins the language has provided - that kind of feedback is also quite rare
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.
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
will include!
Messaged the lang team back; I think that means this is going to need to be bumped back to the next planning cycle.
Writing down those prior thoughts:
Send with asyncWasmtime'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.
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
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 ?
Works for me :+1:
works for me as well
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
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.
Another thing to talk about: how to make Pulley and threads work with Rust's memory model
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?
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.
I'll send through a hackmd doc later today, which will includes everything posted in this thread so far + other items from individual conversations.
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.
Looking forward to it! Also happy to help out with editing the doc too
First pass of the doc is done: https://hackmd.io/@yoshuawuyts/HkW6fBd2le
I think we could probably do with some more code examples and links
I still need to reformat some things too
@Pat Hickey if you have the time, can I ask you to elaborate on the softfloat target topic in the doc?
thats more of a @Chris Fallin / @fitzgen (he/him) topic
@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
it is the kind of thing that Microsoft Corporate would like to see, certainly, if an example is required.....
I added a paragraph to the doc, feel free to expand/edit it
Did a pass and edited some things. Chris/Nick y'all might want to expand on the bitpacking part
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!
Alex Crichton said:
Chris/Nick y'all might want to expand on the bitpacking part
done
Also, logistics-wise, how will we join?
Alex Crichton said:
Also, logistics-wise, how will we join?
At the meeting time, join https://meet.jit.si/ferris-rules
(Will take a look at the updated doc tomorrow!)
@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:
oh I can take care of that b/c I added most of that
ty ty!
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!
I think the meeting went really well. Thank you all for joining!
Last updated: Dec 06 2025 at 06:05 UTC