Hi everyone,
I'm trying to setup a "callback" system to handle async computation. I was creating a variant of @Dirk Bäumer's calculator example in which the operands can also be variables:
interface types {
// ...
variant operand {
integer(u32),
variable(string),
}
// ...
}
To resolve the value of a variable requires a callback, which I setup like so:
interface types {
// ...
resource with-operand-value {
value: func(value: u32);
}
// ...
}
in the world there is a function:
world calculator {
use types.{operation, with-operand-value, with-calc-result};
// ...
import resolve-variable: func(name: string, wov: with-operand-value);
// ...
}
and in my Rust code I have a struct ResolveOperandFuture
that implements the GuestWithOperandValue trait -- the impl is pretty broken (it doesn't use the Waker) -- but that's not the question.
The question is, when I try to call this, I invoke resolve_variable
like so...
resolve_variable(&name, WithOperandValue::new(future.clone()));
and I get an error like
error[E0599]: no function or associated item named `new` found for struct `vscode::example::types::WithOperandValue` >
--> src/lib.rs:49:55
Digging more into this, it seems there are two WithOperandValue
structs defined, one for the "exported" resource and one for the "imported" resource.
How can I manage this situation?
Leaving aside the details of the above, the core question is...
Is there a way to define a resource that I implement from Rust and then pass to an imported function?
I'm more interested in that question then in the best way to model async callbacks (given that direct suport for async is not yet available to me), but we could discuss that specific question in a different topic :)
The tl;dr; is "no". An exported resource is a type that's exported and imports cannot revert to exported types
I'm trying to think through how this might be modeled
This feels like a pretty major limitation!
I think you'd have to invert it to have calc
return a resource
I was just going to say that
where you'd have something like step()
and it'd return "no I need this variable" and you feed it back in
I had half a mind to do that already but it felt unnatural
so I was hoping there was another option
OK.
Due to the way resources all work out there's unfortunately not really another option
/me thinks
there'd have to be a major redesign to how resources work at a fundamental level to enable imports to refer to exports
it feels like I basically wind up modeling "poll"
right
and I have to move the "callback management" to the other side
ok
Alex Crichton said:
there'd have to be a major redesign to how resources work at a fundamental level to enable imports to refer to exports
I can sort of see why
or at least, I can imagine it (not knowing the details)
in particular I can see why it'd be simpler to only have the 'dependency edges' going in 1 direciton between components
OK, I'll try that, thanks @Alex Crichton
I think of it as a functor-like thing where every time you instantiate a component it creates brand new types for the exported types, so there's no way for the imports to refer to the future thing which will be the exported resource type
(it occurs to me I could also provide integer handles across the boundary, but now I'm straying into the topic I didn't want to discuss here)
See also https://github.com/WebAssembly/component-model/issues/272 for a discussion of why this limitation exists.
+1 to the integer handles idea; I think that's the best you can do currently if you want to provide a general-purpose callback mechanism.
Last updated: Dec 23 2024 at 13:07 UTC