Skip to content

wasmtime-wit-bindgen: Typecheck exports at {Foo}Indices construction #10610

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

Merged
merged 4 commits into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 21 additions & 64 deletions crates/component-macro/tests/expanded/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl<_T> TheWorldPre<_T> {
pub fn new(
instance_pre: wasmtime::component::InstancePre<_T>,
) -> wasmtime::Result<Self> {
let indices = TheWorldIndices::new(instance_pre.component())?;
let indices = TheWorldIndices::new(&instance_pre)?;
Ok(Self { instance_pre, indices })
}
pub fn engine(&self) -> &wasmtime::Engine {
Expand Down Expand Up @@ -82,11 +82,6 @@ pub struct TheWorldIndices {
/// * If you've instantiated the instance yourself already
/// then you can use [`TheWorld::new`].
///
/// * You can also access the guts of instantiation through
/// [`TheWorldIndices::new_instance`] followed
/// by [`TheWorldIndices::load`] to crate an instance of this
/// type.
///
/// These methods are all equivalent to one another and move
/// around the tradeoff of what work is performed when.
///
Expand All @@ -105,29 +100,12 @@ const _: () = {
///
/// This method may fail if the component does not have the
/// required exports.
pub fn new(
component: &wasmtime::component::Component,
pub fn new<_T>(
_instance_pre: &wasmtime::component::InstancePre<_T>,
) -> wasmtime::Result<Self> {
let _component = component;
let interface0 = exports::foo::foo::chars::GuestIndices::new(_component)?;
Ok(TheWorldIndices { interface0 })
}
/// Creates a new instance of [`TheWorldIndices`] from an
/// instantiated component.
///
/// This method of creating a [`TheWorld`] will perform string
/// lookups for all exports when this method is called. This
/// will only succeed if the provided instance matches the
/// requirements of [`TheWorld`].
pub fn new_instance(
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<Self> {
let _instance = instance;
let interface0 = exports::foo::foo::chars::GuestIndices::new_instance(
&mut store,
_instance,
)?;
let _component = _instance_pre.component();
let _instance_type = _instance_pre.instance_type();
let interface0 = exports::foo::foo::chars::GuestIndices::new(_instance_pre)?;
Ok(TheWorldIndices { interface0 })
}
/// Uses the indices stored in `self` to load an instance
Expand All @@ -140,6 +118,7 @@ const _: () = {
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<TheWorld> {
let _ = &mut store;
let _instance = instance;
let interface0 = self.interface0.load(&mut store, &_instance)?;
Ok(TheWorld { interface0 })
Expand All @@ -149,21 +128,21 @@ const _: () = {
/// Convenience wrapper around [`TheWorldPre::new`] and
/// [`TheWorldPre::instantiate`].
pub fn instantiate<_T>(
mut store: impl wasmtime::AsContextMut<Data = _T>,
store: impl wasmtime::AsContextMut<Data = _T>,
component: &wasmtime::component::Component,
linker: &wasmtime::component::Linker<_T>,
) -> wasmtime::Result<TheWorld> {
let pre = linker.instantiate_pre(component)?;
TheWorldPre::new(pre)?.instantiate(store)
}
/// Convenience wrapper around [`TheWorldIndices::new_instance`] and
/// Convenience wrapper around [`TheWorldIndices::new`] and
/// [`TheWorldIndices::load`].
pub fn new(
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<TheWorld> {
let indices = TheWorldIndices::new_instance(&mut store, instance)?;
indices.load(store, instance)
let indices = TheWorldIndices::new(&instance.instance_pre(&store))?;
indices.load(&mut store, instance)
}
pub fn add_to_linker<T, U>(
linker: &mut wasmtime::component::Linker<T>,
Expand Down Expand Up @@ -279,45 +258,21 @@ pub mod exports {
///
/// This constructor can be used to front-load string lookups to find exports
/// within a component.
pub fn new(
component: &wasmtime::component::Component,
pub fn new<_T>(
_instance_pre: &wasmtime::component::InstancePre<_T>,
) -> wasmtime::Result<GuestIndices> {
let instance = component
let instance = _instance_pre
.component()
.get_export_index(None, "foo:foo/chars")
.ok_or_else(|| {
anyhow::anyhow!(
"no exported instance named `foo:foo/chars`"
)
})?;
Self::_new(|name| {
component.get_export_index(Some(&instance), name)
})
}
/// This constructor is similar to [`GuestIndices::new`] except that it
/// performs string lookups after instantiation time.
pub fn new_instance(
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<GuestIndices> {
let instance_export = instance
.get_export_index(&mut store, None, "foo:foo/chars")
.ok_or_else(|| {
anyhow::anyhow!(
"no exported instance named `foo:foo/chars`"
)
})?;
Self::_new(|name| {
instance
.get_export_index(&mut store, Some(&instance_export), name)
})
}
fn _new(
mut lookup: impl FnMut(
&str,
) -> Option<wasmtime::component::ComponentExportIndex>,
) -> wasmtime::Result<GuestIndices> {
let mut lookup = move |name| {
lookup(name)
_instance_pre
.component()
.get_export_index(Some(&instance), name)
.ok_or_else(|| {
anyhow::anyhow!(
"instance export `foo:foo/chars` does \
Expand All @@ -338,9 +293,11 @@ pub mod exports {
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<Guest> {
let _instance = instance;
let _instance_pre = _instance.instance_pre(&store);
let _instance_type = _instance_pre.instance_type();
let mut store = store.as_context_mut();
let _ = &mut store;
let _instance = instance;
let take_char = *_instance
.get_typed_func::<(char,), ()>(&mut store, &self.take_char)?
.func();
Expand Down
85 changes: 21 additions & 64 deletions crates/component-macro/tests/expanded/char_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl<_T> TheWorldPre<_T> {
pub fn new(
instance_pre: wasmtime::component::InstancePre<_T>,
) -> wasmtime::Result<Self> {
let indices = TheWorldIndices::new(instance_pre.component())?;
let indices = TheWorldIndices::new(&instance_pre)?;
Ok(Self { instance_pre, indices })
}
pub fn engine(&self) -> &wasmtime::Engine {
Expand Down Expand Up @@ -85,11 +85,6 @@ pub struct TheWorldIndices {
/// * If you've instantiated the instance yourself already
/// then you can use [`TheWorld::new`].
///
/// * You can also access the guts of instantiation through
/// [`TheWorldIndices::new_instance`] followed
/// by [`TheWorldIndices::load`] to crate an instance of this
/// type.
///
/// These methods are all equivalent to one another and move
/// around the tradeoff of what work is performed when.
///
Expand All @@ -108,29 +103,12 @@ const _: () = {
///
/// This method may fail if the component does not have the
/// required exports.
pub fn new(
component: &wasmtime::component::Component,
pub fn new<_T>(
_instance_pre: &wasmtime::component::InstancePre<_T>,
) -> wasmtime::Result<Self> {
let _component = component;
let interface0 = exports::foo::foo::chars::GuestIndices::new(_component)?;
Ok(TheWorldIndices { interface0 })
}
/// Creates a new instance of [`TheWorldIndices`] from an
/// instantiated component.
///
/// This method of creating a [`TheWorld`] will perform string
/// lookups for all exports when this method is called. This
/// will only succeed if the provided instance matches the
/// requirements of [`TheWorld`].
pub fn new_instance(
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<Self> {
let _instance = instance;
let interface0 = exports::foo::foo::chars::GuestIndices::new_instance(
&mut store,
_instance,
)?;
let _component = _instance_pre.component();
let _instance_type = _instance_pre.instance_type();
let interface0 = exports::foo::foo::chars::GuestIndices::new(_instance_pre)?;
Ok(TheWorldIndices { interface0 })
}
/// Uses the indices stored in `self` to load an instance
Expand All @@ -143,6 +121,7 @@ const _: () = {
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<TheWorld> {
let _ = &mut store;
let _instance = instance;
let interface0 = self.interface0.load(&mut store, &_instance)?;
Ok(TheWorld { interface0 })
Expand All @@ -152,7 +131,7 @@ const _: () = {
/// Convenience wrapper around [`TheWorldPre::new`] and
/// [`TheWorldPre::instantiate_async`].
pub async fn instantiate_async<_T>(
mut store: impl wasmtime::AsContextMut<Data = _T>,
store: impl wasmtime::AsContextMut<Data = _T>,
component: &wasmtime::component::Component,
linker: &wasmtime::component::Linker<_T>,
) -> wasmtime::Result<TheWorld>
Expand All @@ -162,14 +141,14 @@ const _: () = {
let pre = linker.instantiate_pre(component)?;
TheWorldPre::new(pre)?.instantiate_async(store).await
}
/// Convenience wrapper around [`TheWorldIndices::new_instance`] and
/// Convenience wrapper around [`TheWorldIndices::new`] and
/// [`TheWorldIndices::load`].
pub fn new(
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<TheWorld> {
let indices = TheWorldIndices::new_instance(&mut store, instance)?;
indices.load(store, instance)
let indices = TheWorldIndices::new(&instance.instance_pre(&store))?;
indices.load(&mut store, instance)
}
pub fn add_to_linker<T, U>(
linker: &mut wasmtime::component::Linker<T>,
Expand Down Expand Up @@ -295,45 +274,21 @@ pub mod exports {
///
/// This constructor can be used to front-load string lookups to find exports
/// within a component.
pub fn new(
component: &wasmtime::component::Component,
pub fn new<_T>(
_instance_pre: &wasmtime::component::InstancePre<_T>,
) -> wasmtime::Result<GuestIndices> {
let instance = component
let instance = _instance_pre
.component()
.get_export_index(None, "foo:foo/chars")
.ok_or_else(|| {
anyhow::anyhow!(
"no exported instance named `foo:foo/chars`"
)
})?;
Self::_new(|name| {
component.get_export_index(Some(&instance), name)
})
}
/// This constructor is similar to [`GuestIndices::new`] except that it
/// performs string lookups after instantiation time.
pub fn new_instance(
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<GuestIndices> {
let instance_export = instance
.get_export_index(&mut store, None, "foo:foo/chars")
.ok_or_else(|| {
anyhow::anyhow!(
"no exported instance named `foo:foo/chars`"
)
})?;
Self::_new(|name| {
instance
.get_export_index(&mut store, Some(&instance_export), name)
})
}
fn _new(
mut lookup: impl FnMut(
&str,
) -> Option<wasmtime::component::ComponentExportIndex>,
) -> wasmtime::Result<GuestIndices> {
let mut lookup = move |name| {
lookup(name)
_instance_pre
.component()
.get_export_index(Some(&instance), name)
.ok_or_else(|| {
anyhow::anyhow!(
"instance export `foo:foo/chars` does \
Expand All @@ -354,9 +309,11 @@ pub mod exports {
mut store: impl wasmtime::AsContextMut,
instance: &wasmtime::component::Instance,
) -> wasmtime::Result<Guest> {
let _instance = instance;
let _instance_pre = _instance.instance_pre(&store);
let _instance_type = _instance_pre.instance_type();
let mut store = store.as_context_mut();
let _ = &mut store;
let _instance = instance;
let take_char = *_instance
.get_typed_func::<(char,), ()>(&mut store, &self.take_char)?
.func();
Expand Down
Loading