-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for Interface Types in wasmtime API #677
Comments
Oh I should also mention that a bare minimum I'm expecting of any future support of interface types in wasmtime is to actually have tests. To that end the
Notably I do not want to hook up |
Would the API instability affect users of the I don't know what all the challenges will be, but with that said, my instinct is that making On the topic of tests, For wasi-common's tests I'm considering an approach where we check in the compiled wasm files (or maybe the corresponding wat files) so that we can run the tests without having all the tools installed, but then have a way for people who do have the tools installed to use them and/or regenerate the compiled files. Would that work for the wasm-bindgen parts? |
I think this is a good plan! In particular, I agree with the crate organization, and in particular putting this into the |
How settled is it for ".wit" to mean ".wat + interface types"? If it's not settled yet, one option would be to just continue to use ".wat" for files that contain interface types annotations, because the annotation syntax is on track to become part of the .wat syntax. That would also avoid the ambiguity with ".wit" meaning instance type, which happens to be the "wit" that "witx" is named after. |
It depends on what the crate is doing, and it also sort of depends on the idioms we expect users to have. The breakage would be of the form: let x: wasmtime::ValType = ...;
match x {
// we'll add variants to this over time, so exhaustive matches will break
}
let y: wasmtime::Val = ...;
match y {
// we'll add variants to this over time, so exhaustive matches will break
} We could encourage users to user helper methods though (perhaps like
I think I agree with this, so I think that an initial implementation should push really hard on fleshing out the laziness story. Only if something truly and fundamentally is incompatible do I think it should be postponed for later.
Heh I would personally still not be very comfortable checking in The downside of this approach would be, though:
Overall I don't actually think we'll need to use
Not settled in the least. I randomly made a decision to use I think I like the idea of In general though none of this really matters internally in The general idea is that the |
To elaborate on the wasm-bindgen thing and |
This seems like a very good thing to have and encourage the use of regardless: my intuition is that in the majority of cases you know the type contained in the Val. |
My thought is that adding enum values is pretty mild in terms of API breakage; the error messages are clear, and the fixes if you don't care about the new values are straightforward. I don't think |
Great write up! I think this makes a lot of sense. Here's some thoughts I have regarding interface types and the impact on the C embedding API. In addition to expanding It would be really nice if the embedding API supported a concept of a "host string encoding" enumeration that could be set when creating the engine. The data of More importantly, this would control the source encoding for the For example, strings are stored as UTF-16 in .NET. I would really like to avoid having to allocate a UTF-8 version of a string just to pass it to |
Oh interesting, @peterhuene do you have links to that discussion about That's a good point about encodings, although I would initally sort of hope that we could preserve "utf-8 everywhere" as long as possible, but not with copies. A |
It was this comment that reminded me of the push-back against adding a 128-bit type to the union, although I incorrectly recalled the intention to keep it word-sized (it's 64-bit currently, so only word-sized for 64-bit hosts). I was more talking about the union and not Could you walk me through how you envision I might be missing a huge thing here, but if we keep the C API UTF-8 only, I don't see a way around a UTF-16 native host from having to allocate a temporary string to the give the API and then get it copied into a memory from the interface types implementation. |
Allowing host Unicode encodings does sound like it fits really well with the contents being lazy -- transcoding can happen at the point where we would otherwise copy, so that we never transcode into a temporary buffer. |
Thanks for the pointer! I'm somewhat hesitant to try to tackle the C API given that though. If the proposed C API doesn't want to tackle I was thinking basically what you think I'm thinking, where a I'm sort of hoping though that we can avoid getting hung up on too many details and get something bare-bones working. It surely can't be worse than what we have today, and ideally an implementation to iterate on would help us figure out better ways to implement it as well as perhaps ways to iterate the spec itself. |
Let me ask a simple question then: if I am a host that needs to pass a Wasm-memory-address and length pair to an interface types definition of a function that takes a "string", how do I do that? I can't allocate anything in the Wasm memory to give you; that requires an implementation of interface types in the host and not the runtime. |
Yeah that's where my thinking breaks down really quickly :) I haven't really fully thought through all the implications of everything. The absolute easiest thing to do is to require everything to be a bare and owned |
I'm also saying you can't return an address into the memory for wasm-to-host, either. The adapter may free the string in the WebAssembly memory and the implementation of the free function may zero the memory or something else. It has to give back at least a copy of the data out of the WebAssembly memory for the I don't want to get too caught up in this discussion such that it hinders progress on moving forward on an implementation. To wit, I'm fine with keeping the initial implementation of strings coming in and out of the host (including the Rust API) as UTF-8 provided we look forward to an implementation that would prevent hosts with different native string representations from having to create temporary allocations to make string types work (i.e. perhaps the idea of a host encoding or per-string encoding in the C API, with only support for UTF-8 initially). |
The API (C++ or Rust) has major deficiency, is late-binding which causing us extend the wasm_val_t with custom types. Each time we are trying to use API's |
Is this an appropriate issue in which to discuss using Interface Types for bindings to host functions, as well? For instance, it should be possible to export a Rust function directly to WebAssembly without writing a manual wrapper using (Eventually, that will need to include support for opaque reference types.) |
I think that falls a bit under what @yurydelendik was mentioning moreso than interface types. You should already in theory be able to do that for integers/floats and with interface types you should just also be able to do that with interface types. I think there's basically an underlying feature request of creating an |
@alexcrichton I'm not sure how it fits into the current plans (per #1271) but I would like to volunteer to continue the work you started with #1013. I spent some time going through the source to get an idea of what is involved and have already started adding some of the missing instructions (from instr.md) in a local branch (not published yet). I might need guidance at various points (around strings, compilation, etc.) but I have time to focus on it and I've been looking for something more substantial to work on. |
@darinmorrison that'd be awesome, and I'd be happy to help! I think the TODO list on that PR covers pretty well the major two remaining bits, and I'd probably recommend tackling the first two earlier rather than later to ensure that all the various integration points are largely working before an interpreter becomes more fleshed out. Feel free to ping me on zulip or here if you've got questions though! |
This commit temporarily removes support for interface types from the `wasmtime` CLI and removes the `wasmtime-interface-types` crate. An error is now printed for any input wasm modules that have wasm interface types sections to indicate that support has been removed and references to two issues are printed as well: * bytecodealliance#677 - tracking work for re-adding interface types support * bytecodealliance#1271 - rationale for removal and links to other discussions Closes bytecodealliance#1271
@alexcrichton , based on the last comment here #1289 it looks like @darinmorrison is not able to continue on this work. I can't even begin to fathom how all this works, nor do I have the capacity right now to work on things. I'm justing pinging it here so that the "interface types" work doesn't disappear. Its important :D |
I don't think that interface types are the place to push UTF-8. Ultimately it's up to the languages, not the bytecode. No one will choose which encoding to used based on what interface types do, they'll choose based on what the languages involved do. Supporting more Unicode encodings means removing redundant copies, it's as simple as that. It won't lead to some dystopia where everyone is switching to UTF-16 because it wasn't barred up enough. |
Note that when it comes to Interface Types, we'll implement what gets standardized, so if the Interface Types proposal ends up only supporting UTF-8, then we'll only implement that. I.e., arguments for additional encoding should be made to the WebAssembly CG, not here. |
Thanks, I left a comment on their repository saying the same thing. |
Sorry for the uninformed question, but how can I enable interface types at the moment? Do I need the wasm-interface-types crate? Or is it a total no-go atm? |
Unfortuantely at this time there's not a prototype or a switch to turn on. This is not implemented, so testing this out (or even playing around with it) will have to wait until someone implements this. |
@alexcrichton Just out of curiosity, what is needs to be implemented for interface types to be supported? Is there a set of issues / roadmap / milestone we can refer to? Or is just a matter of reading through the spec and implementing the appropriate features in accordance with wasmtime's API? |
I'm not aware of a milestone as-is at this time. The main blocker is still planning work to happen on this. There's a number of moving parts, though, especially in that the specification itself is not stable and is a moving target. This will likely be an effort that's much larger than simply implementing the current state of the specification in wasmtime itself. |
Is it possible to use some temporary workaround? For example witx? (especially after #2659 has been merged) |
Yes it's definitely true that working with raw pointers and such is painful and error-prone today. We're working on exactly what you're thinking, though, which is a system to use |
Looking forward to a working prototype of what you've mentioned! |
Status update? |
Is this project relevant here? |
When running wasmtime in Rust I get an error saying support for interface types has been temorarily removed.
I had a scan through the comments here on how to re-add support, but didn't see any solution. |
Native support for Interface Types will be re-added to Wasmtime together
with support for WebAssembly Components in the not-too-distant future. For
now, wit-bindgen <https://github.com/bytecodealliance/wit-bindgen>
(formerly known as wai-bindgen / witx-bindgen) is the right way to use
Interface Types, though note that the details of the IDL and the bindings
are still changing in breaking ways.
@radu-matei recently published an excellent blog post
<https://radu-matei.com/blog/intro-wasm-components/> describing how
Components work and how to use wit-bindgen and other tools to work with
them.
|
Can someone please write some example on how to use |
I dont think you can do that yet because component model implementation is still ongoing #4185 |
This is quite an old issue at this point and the component model is effectively fully supported in Wasmtime right now, so I'm going to close this. |
I'd like to open this as a sort of meta-issue about supporting WebAssembly Interface Types in the
wasmtime
crate and API. The current support via thecrates/interface-types
crate for the purpose of this issue can be basically ignored. It doesn't fit into thewasmtime
crate API at all, it's outdated, and it's not how I think we want the API to look long-term.The Interface Types proposal has settled a bit more on design lately, where the general idea is that there are a set of adapter types which adapter functions can use. The actual interface of a wasm module will be the adapter functions imported/exported, rather than the core wasm imports/exports.
For some more background, I've got a number of Rust projects supporting the current snapshot of the wasm interface types proposal:
wit-parser
- an analogue ofwasmparser
but for the interface types binary format.wit-text
- an analogue ofwat
, but for the interface types text format.wit-validator
- a crate which performs simple validation of the wasm interface types section of a module, if presentwasm-bindgen
has now been updated to use these crates and emit wasm interface types modules compatible with the current proposal. This support hasn't been published, though, and I'd like to hold off until there's support inwasmtime
itself.I've been thinking today about how best to integrate interface types into the
wasmtime
set of crates. There's a lot of moving pieces and lot of possibilities for how this can work, but I'd like to make a concrete proposal about how this could be integrated. This is going to be a pretty big change, though, so I'd want to be sure to get buy-in from relevant folks before moving forward.The general gist of what I'm thinking is:
wasmtime
crate doesn't actually change a whole lot, but theValType
andVal
enumerations are extended with all types from the interface types proposal. This namely means signed/unsigned 8-64 bit integers as well as a string type will show up.wasmtime
modules/instances change depending on the presence of the wasm interface types section.wasm_val_t
type would have a few new codes forwasm_valkind_t
and the union would have a few more items packed inside of it. I haven't thought a huge amount about the ownership of strings and such, but I'm assuming that we can think of something pretty reasonable here.wasmtime
executable would use thewit_text
crate to parse input files, which would parse any of*.wat
,*.wasm
, or*.wit
files.After these changes are implemented then the
crates/interface-types
crate would just be deleted, since it is no longer needed. The Python/Rust extensions would be updated to use thewasmtime
crate directly, and would provide all necessary mappings for strings/etc. Additionally the .NET extension could be updated with more support since this would all be present in the C API.Some questions I've wanted to make sure we've got covered when landing all this are:
How will future interface types changes affect this design?
Given this setup the only public-facing change to the design of interface types will be the set of supported types/values. Otherwise I think everything else can be internal changes (yay!) which we take care of one way or another.
How will adapters get implemented today?
I'm thinking that we'll basically just have an "interpreter" for all adapter instructions. Eventually we can get fancier with more JIT-like support but I'd like to get the bare-bones up and running first.
What about the laziness of types?
One of the ideas in the interface types proposal is that adapter instructions are often lazy to minimize copying data between various locations. This'll all boil down to the
Val::String
representation I think. For now I'm imagaining something likeVal::String
holding a memory reference, pointer, and length. That way when requested you can read off the entire string, or if you want you could get raw access and peek at the bytes yourself. I'm not really 100% sure how this will work though, but I'm also assuming that it's ok to "cop out" in the interim and "just useString
" to see how far it gets us.This is something I'm particularly curious to hear feedback on though. Especially as more and more types come into the interface types proposal, this is going to get more and more important. For example it'd be pretty awesome if we could start now defining wasi APIs in terms of interface types, but this is all likely a good ways off so perhaps a bit premature to worry about this.
What about linking modules together?
I'm not even gonna try to approach this in a first pass. The main interesting thing here is that if you link together two wasm modules using wasm interface types you can ideally create a highly-optimized adapter function in the middle of the two. I don't plan to tackle this in our initial support though, and while this should work one way or another, it'll likely be relatively slow and copy/allocation-heavy.
Is
wasmtime
the right crate to put this in wrt stability?Interface types and its proposal are pretty unstable, with lots going to change now and in the future. Is it ok to now hook up the interface types proposal into the public API of
wasmtime
? That will be a continued source of instability for consumers of the API (new type variants basically). I'm hoping that new types don't come along all that often, and I'm also hoping that stability isn't necessarily paramount in thewasmtime
crate yet that this is ok.I don't really have many other alternatives though of how to integrate interface types into the wasmtime project. So if others think that interface types are too unstable to go into the
wasmtime
crate, now would be a good time to discuss that, as well as possible mitigations :)The text was updated successfully, but these errors were encountered: