pchickey edited PR #10610.
pchickey updated PR #10610.
pchickey edited PR #10610:
Based on #10616.
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third :).
<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
pchickey edited PR #10610:
Based on #10616.
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third.
<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
pchickey updated PR #10610.
pchickey edited PR #10610:
Based on #10616.
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third.
Additions to Wasmtime
InstancePrenow has an additionalInstanceTypemember. TheInstanceTyperepresents the type information carried in theLinkerused to typecheck all of theInstancePre's imports. This is accessible by a new accessorinstance_type(&self) -> &InstanceType.Instancehas a new accessorinstance_type(&self, store: impl AsContextMut) -> InstanceType. The store contains all of the information required to construct the InstanceType, so this is just a matter of exposing whats already there.component::types::ComponentFunchas a new methodtypecheck<Params, Returns>(&self, instance_type: &InstanceType) -> Result<()>. The underlying typecheck performed here is the exact same one performed inFunc::typed<Params, Returns>(&self, store: impl AsContextMut) -> Result<()>, except rather than the type information coming out of the store, its provided by the InstanceType.All of these additions are pub interfaces but marked
#[doc(hidden)]to make them "internal", because the prior art was thatInstanceTypeand is internal, and there are no other public interfaces for retrievingInstanceTypeor typechecking, with the sole exception ofFunc::typed. I think that we should consider making these documented public interfaces, but I'll leave that to a future PR unless requested.Changes to wasmtime-wit-bindgen
This test case demonstates the extent of the changes: https://github.com/bytecodealliance/wasmtime/pull/10610/files#diff-0b0815115f3addd488fbf1f032466f210b9fcd29ec42f4b4a777e58f80abba16
- The
{Foo}Indiciesconstructor which is used in theInstancePrepathnew(&Component) -> Result<Self>now has signaturenew(&Component, &InstanceType) -> Result<Self>.- The other constructor
new_instance(impl AsContextMut, &Instance) -> Result<Self>keeps the same signature, because the combination of an Instance and its store are sufficient to create an InstanceType.- The InstanceType is plumbed through to the common
_newinternals.- Each place an export index is retrieved for a function,
.get_export_indexhas been substituted out with.get_export, and the returnedComponentItemis checked to be a ComponentItem::ComponentFunc(func), and thenfunc.typecheckis invoked with the type argument corresponding to theTypedFunctype parameters.<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
pchickey edited PR #10610:
Based on #10616.
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third.
Additions to Wasmtime
InstancePrenow has an additionalInstanceTypemember. TheInstanceTyperepresents the type information carried in theLinkerused to typecheck all of theInstancePre's imports. This is accessible by a new accessorinstance_type(&self) -> &InstanceType.Instancehas a new accessorinstance_type(&self, store: impl AsContextMut) -> InstanceType. The store contains all of the information required to construct the InstanceType, so this is just a matter of exposing whats already there.component::types::ComponentFunchas a new methodtypecheck<Params, Returns>(&self, instance_type: &InstanceType) -> Result<()>. The underlying typecheck performed here is the exact same one performed inFunc::typed<Params, Returns>(&self, store: impl AsContextMut) -> Result<()>, except rather than the type information coming out of the store, its provided by the InstanceType.All of these additions are pub interfaces but marked
#[doc(hidden)]to make them "internal", because the prior art was thatInstanceTypeand is internal, and there are no other public interfaces for retrievingInstanceTypeor typechecking, with the sole exception ofFunc::typed. I think that we should consider making these documented public interfaces, but I'll leave that to a future PR unless requested.Changes to wasmtime-wit-bindgen
This test case demonstates the extent of the changes: https://github.com/bytecodealliance/wasmtime/pull/10610/files#diff-0b0815115f3addd488fbf1f032466f210b9fcd29ec42f4b4a777e58f80abba16
- The
{Foo}Indiciesconstructor which is used in theInstancePrepathnew(&Component) -> Result<Self>now has signaturenew(&Component, &InstanceType) -> Result<Self>.- The other constructor
new_instance(impl AsContextMut, &Instance) -> Result<Self>keeps the same signature, because the combination of an Instance and its store are sufficient to create an InstanceType.- The InstanceType is plumbed through to the common
_newinternals.- Each place an export index is retrieved for a function,
.get_export_indexhas been substituted out with.get_export, and the returnedComponentItemis checked to be a ComponentItem::ComponentFunc(func), and thenfunc.typecheckis invoked with the type argument corresponding to theTypedFunctype parameters.Future work
Each export func is typechecked again in its bindgen
call_{funcname}function, in which theFuncmember owned by the typed instance{Foo}struct is cast to aTypedFuncwith the specific type parameters bindgen keeps track of for each func. Since the{Foo}struct is created from a{Foo}Indices, we can guarantee that the export funcs have been typechecked against a givenLinkerorStore, so we could potentially elide the repeated typecheck there, and make an unchecked cast to TypedFunc instead. (TypedFuncs are not stored in the{Foo}struct at least in part because their type parameters may use&'a ...which only apply to the site of the call, and not to the storage of that member in{Foo}. Thefor<'a>trick only works for trait objects, not concrete types like TypedFunc.)<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
pchickey has marked PR #10610 as ready for review.
pchickey requested dicej for a review on PR #10610.
pchickey requested wasmtime-core-reviewers for a review on PR #10610.
pchickey edited PR #10610:
Based on #10616.
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using {interface-name}Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third.
Additions to Wasmtime
InstancePrenow has an additionalInstanceTypemember. TheInstanceTyperepresents the type information carried in theLinkerused to typecheck all of theInstancePre's imports. This is accessible by a new accessorinstance_type(&self) -> &InstanceType.Instancehas a new accessorinstance_type(&self, store: impl AsContextMut) -> InstanceType. The store contains all of the information required to construct the InstanceType, so this is just a matter of exposing whats already there.component::types::ComponentFunchas a new methodtypecheck<Params, Returns>(&self, instance_type: &InstanceType) -> Result<()>. The underlying typecheck performed here is the exact same one performed inFunc::typed<Params, Returns>(&self, store: impl AsContextMut) -> Result<()>, except rather than the type information coming out of the store, its provided by the InstanceType.All of these additions are pub interfaces but marked
#[doc(hidden)]to make them "internal", because the prior art was thatInstanceTypeand is internal, and there are no other public interfaces for retrievingInstanceTypeor typechecking, with the sole exception ofFunc::typed. I think that we should consider making these documented public interfaces, but I'll leave that to a future PR unless requested.Changes to wasmtime-wit-bindgen
This test case demonstates the extent of the changes: https://github.com/bytecodealliance/wasmtime/pull/10610/files#diff-0b0815115f3addd488fbf1f032466f210b9fcd29ec42f4b4a777e58f80abba16
- The
{Foo}Indiciesconstructor which is used in theInstancePrepathnew(&Component) -> Result<Self>now has signaturenew(&Component, &InstanceType) -> Result<Self>.- The other constructor
new_instance(impl AsContextMut, &Instance) -> Result<Self>keeps the same signature, because the combination of an Instance and its store are sufficient to create an InstanceType.- The InstanceType is plumbed through to the common
_newinternals.- Each place an export index is retrieved for a function,
.get_export_indexhas been substituted out with.get_export, and the returnedComponentItemis checked to be a ComponentItem::ComponentFunc(func), and thenfunc.typecheckis invoked with the type argument corresponding to theTypedFunctype parameters.Future work
Each export func is typechecked again in its bindgen
call_{funcname}function, in which theFuncmember owned by the typed instance{Foo}struct is cast to aTypedFuncwith the specific type parameters bindgen keeps track of for each func. Since the{Foo}struct is created from a{Foo}Indices, we can guarantee that the export funcs have been typechecked against a givenLinkerorStore, so we could potentially elide the repeated typecheck there, and make an unchecked cast to TypedFunc instead. (TypedFuncs are not stored in the{Foo}struct at least in part because their type parameters may use&'a ...which only apply to the site of the call, and not to the storage of that member in{Foo}. Thefor<'a>trick only works for trait objects, not concrete types like TypedFunc.)<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
dicej submitted PR review.
alexcrichton commented on PR #10610:
I'm a bit concerned about https://github.com/bytecodealliance/wasmtime/pull/10616 and the cost implications of having more
Arc-clones on lifting/lowering paths, and after reading over this more I've got a possibilty which I forget if we already talked about and/or whether you tried, so let me know if I sound like a broken record. Could the various*Indicesconstructors take a&InstancePre<T>instead of a&Component? That way we could refactor the internals ofInstancePre<T>to hold whatever is necessary to cheaply create theInstanceType<T>I think?
alexcrichton edited a comment on PR #10610:
I'm a bit concerned about https://github.com/bytecodealliance/wasmtime/pull/10616 and the cost implications of having more
Arc-clones on lifting/lowering paths, and after reading over this more I've got a possibilty which I forget if we already talked about and/or whether you tried, so let me know if I sound like a broken record. Could the various*Indicesconstructors take a&InstancePre<T>instead of a&Component? That way we could refactor the internals ofInstancePre<T>to hold whatever is necessary to cheaply create theInstanceType<'_>I think?
pchickey commented on PR #10610:
Thanks, I'll explore that now!
pchickey updated PR #10610.
pchickey updated PR #10610.
pchickey edited PR #10610.
pchickey edited PR #10610:
Based on #10616.
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using {interface-name}Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third.
Addition to Wasmtime
component::types::ComponentFunchas a new methodtypecheck<Params, Returns>(&self, instance_type: &InstanceType) -> Result<()>. The underlying typecheck performed here is the exact same one performed inFunc::typed<Params, Returns>(&self, store: impl AsContextMut) -> Result<()>, except rather than the type information coming out of the store, its provided by the InstanceType.This addition is a pub interfaces but marked
#[doc(hidden)]to make them "internal", because the prior art was thatInstanceTypeand is internal, and there are no other public interfaces for retrievingInstanceTypeor typechecking, with the sole exception ofFunc::typed. I think that we should consider making these documented public interfaces, but I'll leave that to a future PR unless requested.Changes to wasmtime-wit-bindgen
This test case demonstates the extent of the changes: https://github.com/bytecodealliance/wasmtime/pull/10610/files#diff-0b0815115f3addd488fbf1f032466f210b9fcd29ec42f4b4a777e58f80abba16
- The
{Foo}Indiciesconstructor which is used in theInstancePrepathnew(&Component) -> Result<Self>now has signaturenew(&Component, &InstanceType) -> Result<Self>.- The other constructor
new_instance(impl AsContextMut, &Instance) -> Result<Self>keeps the same signature, because the combination of an Instance and its store are sufficient to create an InstanceType.- The InstanceType is plumbed through to the common
_newinternals.- Each place an export index is retrieved for a function,
.get_export_indexhas been substituted out with.get_export, and the returnedComponentItemis checked to be a ComponentItem::ComponentFunc(func), and thenfunc.typecheckis invoked with the type argument corresponding to theTypedFunctype parameters.Future work
Each export func is typechecked again in its bindgen
call_{funcname}function, in which theFuncmember owned by the typed instance{Foo}struct is cast to aTypedFuncwith the specific type parameters bindgen keeps track of for each func. Since the{Foo}struct is created from a{Foo}Indices, we can guarantee that the export funcs have been typechecked against a givenLinkerorStore, so we could potentially elide the repeated typecheck there, and make an unchecked cast to TypedFunc instead. (TypedFuncs are not stored in the{Foo}struct at least in part because their type parameters may use&'a ...which only apply to the site of the call, and not to the storage of that member in{Foo}. Thefor<'a>trick only works for trait objects, not concrete types like TypedFunc.)<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
alexcrichton submitted PR review.
pchickey edited PR #10610:
Based on #10616.
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using {interface-name}Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third.
Addition to Wasmtime
component::types::ComponentFunchas a new methodtypecheck<Params, Returns>(&self, instance_type: &InstanceType) -> Result<()>. The underlying typecheck performed here is the exact same one performed inFunc::typed<Params, Returns>(&self, store: impl AsContextMut) -> Result<()>, except rather than the type information coming out of the store, its provided by the InstanceType.This addition is a pub interfaces but marked
#[doc(hidden)]to make them "internal", because the prior art was thatInstanceTypeand is internal, and there are no other public interfaces for retrievingInstanceTypeor typechecking, with the sole exception ofFunc::typed. I think that we should consider making these documented public interfaces, but I'll leave that to a future PR unless requested.Changes to wasmtime-wit-bindgen
The
resources-importtest case demonstates the extent of the changes: https://github.com/bytecodealliance/wasmtime/pull/10610/files#diff-0b0815115f3addd488fbf1f032466f210b9fcd29ec42f4b4a777e58f80abba16
- Since typechecking information is available from the InstancePre (thanks to #10616), we can unify the two variations on constructing an Indices struct: there is now a single constructor
fn new<T>(_instance_pre: InstancePre<T>) -> Result<Self>. Deduplicating this eliminates both generated code and complexity in the generator.The new sigular constructor uses
_instance_pre.component()to lookup exports (both their index and their ComponentItem), and_instance_pre.instance_type()is used to typecheck the export.Each place an export index is retrieved for a function,
.get_export_indexhas been substituted out with.get_export, and the returnedComponentItemis checked to be a ComponentItem::ComponentFunc(func), and thenfunc.typecheckis invoked with the type argument corresponding to theTypedFunctype parameters.Future work
Each export func is typechecked again in its bindgen
call_{funcname}function, in which theFuncmember owned by the typed instance{Foo}struct is cast to aTypedFuncwith the specific type parameters bindgen keeps track of for each func. Since the{Foo}struct is created from a{Foo}Indices, we can guarantee that the export funcs have been typechecked against a givenLinkerorStore, so we could potentially elide the repeated typecheck there, and make an unchecked cast to TypedFunc instead. (TypedFuncs are not stored in the{Foo}struct at least in part because their type parameters may use&'a ...which only apply to the site of the call, and not to the storage of that member in{Foo}. Thefor<'a>trick only works for trait objects, not concrete types like TypedFunc.)<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
pchickey edited PR #10610:
Based on #10616.
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using {interface-name}Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third.
Addition to Wasmtime
component::types::ComponentFunchas a new methodtypecheck<Params, Returns>(&self, instance_type: &InstanceType) -> Result<()>. The underlying typecheck performed here is the exact same one performed inFunc::typed<Params, Returns>(&self, store: impl AsContextMut) -> Result<()>, except rather than the type information coming out of the store, its provided by the InstanceType.This addition is a pub interfaces but marked
#[doc(hidden)]to make them "internal", because the prior art was thatInstanceTypeand is internal, and there are no other public interfaces for retrievingInstanceTypeor typechecking, with the sole exception ofFunc::typed. I think that we should consider making these documented public interfaces, but I'll leave that to a future PR unless requested.Changes to wasmtime-wit-bindgen
The
resources-importtest case demonstates the extent of the changes: https://github.com/bytecodealliance/wasmtime/pull/10610/files#diff-0b0815115f3addd488fbf1f032466f210b9fcd29ec42f4b4a777e58f80abba16
- Since typechecking information is available from the InstancePre (thanks to #10616), we can unify the two variations on constructing an Indices struct: there is now a single constructor
fn new<T>(_instance_pre: InstancePre<T>) -> Result<Self>. Deduplicating this eliminates both generated code and complexity in the generator.- The new sigular constructor uses
_instance_pre.component()to lookup exports (both their index and their ComponentItem), and_instance_pre.instance_type()is used to typecheck the export.- Each place an export index is retrieved for a function,
.get_export_indexhas been substituted out with.get_export, and the returnedComponentItemis checked to be a ComponentItem::ComponentFunc(func), and thenfunc.typecheckis invoked with the type argument corresponding to theTypedFunctype parameters.Future work
Each export func is typechecked again in its bindgen
call_{funcname}function, in which theFuncmember owned by the typed instance{Foo}struct is cast to aTypedFuncwith the specific type parameters bindgen keeps track of for each func. Since the{Foo}struct is created from a{Foo}Indices, we can guarantee that the export funcs have been typechecked against a givenLinkerorStore, so we could potentially elide the repeated typecheck there, and make an unchecked cast to TypedFunc instead. (TypedFuncs are not stored in the{Foo}struct at least in part because their type parameters may use&'a ...which only apply to the site of the call, and not to the storage of that member in{Foo}. Thefor<'a>trick only works for trait objects, not concrete types like TypedFunc.)<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
pchickey edited PR #10610:
Based on #10621
Currently, in bindgen-emitted component wrappers, the existence of export functions is checked at the construction of the {interface-name}Indices struct, but each export function is only finally typechecked on their invocation in {interface-name}::call_{func-name}.
The goal of this PR is to typecheck component exports at the construction of Indices. This is desirable because it gives a type error as early as possible - when using {interface-name}Indices by way of {interface-name}Pre, this can be performed with only an InstancePre, where the creation of an InstancePre requires only a Component and Linker, and typechecks all of the Component's imports. So, really, this is about getting exports on parity with imports.
Closes #9155 . I've worked around this with ugly hacks in embeddings for 2 different employers now and I'm not about to do it for a third.
Addition to Wasmtime
component::types::ComponentFunchas a new methodtypecheck<Params, Returns>(&self, instance_type: &InstanceType) -> Result<()>. The underlying typecheck performed here is the exact same one performed inFunc::typed<Params, Returns>(&self, store: impl AsContextMut) -> Result<()>, except rather than the type information coming out of the store, its provided by the InstanceType.This addition is a pub interfaces but marked
#[doc(hidden)]to make them "internal", because the prior art was thatInstanceTypeand is internal, and there are no other public interfaces for retrievingInstanceTypeor typechecking, with the sole exception ofFunc::typed. I think that we should consider making these documented public interfaces, but I'll leave that to a future PR unless requested.Changes to wasmtime-wit-bindgen
The
resources-importtest case demonstates the extent of the changes: https://github.com/bytecodealliance/wasmtime/pull/10610/files#diff-0b0815115f3addd488fbf1f032466f210b9fcd29ec42f4b4a777e58f80abba16
- Since typechecking information is available from the InstancePre (thanks to #10621), we can unify the two variations on constructing an Indices struct: there is now a single constructor
fn new<T>(_instance_pre: InstancePre<T>) -> Result<Self>. Deduplicating this eliminates both generated code and complexity in the generator.- The new sigular constructor uses
_instance_pre.component()to lookup exports (both their index and their ComponentItem), and_instance_pre.instance_type()is used to typecheck the export.- Each place an export index is retrieved for a function,
.get_export_indexhas been substituted out with.get_export, and the returnedComponentItemis checked to be a ComponentItem::ComponentFunc(func), and thenfunc.typecheckis invoked with the type argument corresponding to theTypedFunctype parameters.Future work
Each export func is typechecked again in its bindgen
call_{funcname}function, in which theFuncmember owned by the typed instance{Foo}struct is cast to aTypedFuncwith the specific type parameters bindgen keeps track of for each func. Since the{Foo}struct is created from a{Foo}Indices, we can guarantee that the export funcs have been typechecked against a givenLinkerorStore, so we could potentially elide the repeated typecheck there, and make an unchecked cast to TypedFunc instead. (TypedFuncs are not stored in the{Foo}struct at least in part because their type parameters may use&'a ...which only apply to the site of the call, and not to the storage of that member in{Foo}. Thefor<'a>trick only works for trait objects, not concrete types like TypedFunc.)<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
pchickey commented on PR #10610:
I addressed the concerns above and rewrote the description accordingly.
pchickey edited PR #10610.
pchickey updated PR #10610.
pchickey has enabled auto merge for PR #10610.
pchickey merged PR #10610.
Last updated: Dec 06 2025 at 07:03 UTC