Split the ComponentValue trait into... components (#4236)
This commit splits the current `ComponentValue` trait into three separate traits: * `ComponentType` - contains size/align/typecheck information in addition to the "lower" representation. * `Lift` - only contains `lift` and `load` * `Lower` - only contains `lower` and `store` When describing the original implementation of host functions to Nick he immediately pointed out this superior solution to the traits involved with Wasmtime's support for typed parameters/returns in exported and imported functions. Instead of having dynamic errors at runtime for things like "you can't lift a `String`" that's instead a static compile-time error now. While I was doing this split I also refactored the `ComponentParams` trait a bit to have `ComponentType` as a supertrait instead of a subtype which made its implementations a bit more compact. Additionally its impl blocks were folded into the existing tuple impl blocks.
This commit is contained in:
@@ -196,8 +196,8 @@ impl Func {
|
||||
/// ```
|
||||
pub fn typed<Params, Return, S>(&self, store: S) -> Result<TypedFunc<Params, Return>>
|
||||
where
|
||||
Params: ComponentParams,
|
||||
Return: ComponentValue,
|
||||
Params: ComponentParams + Lower,
|
||||
Return: Lift,
|
||||
S: AsContext,
|
||||
{
|
||||
self.typecheck::<Params, Return>(store.as_context().0)?;
|
||||
@@ -206,16 +206,15 @@ impl Func {
|
||||
|
||||
fn typecheck<Params, Return>(&self, store: &StoreOpaque) -> Result<()>
|
||||
where
|
||||
Params: ComponentParams,
|
||||
Return: ComponentValue,
|
||||
Params: ComponentParams + Lower,
|
||||
Return: Lift,
|
||||
{
|
||||
let data = &store[self.0];
|
||||
let ty = &data.types[data.ty];
|
||||
|
||||
Params::typecheck(&ty.params, &data.types, Op::Lower)
|
||||
Params::typecheck_params(&ty.params, &data.types)
|
||||
.context("type mismatch with parameters")?;
|
||||
Return::typecheck(&ty.result, &data.types, Op::Lift)
|
||||
.context("type mismatch with result")?;
|
||||
Return::typecheck(&ty.result, &data.types).context("type mismatch with result")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::component::func::{MAX_STACK_PARAMS, MAX_STACK_RESULTS};
|
||||
use crate::component::{ComponentParams, ComponentValue, Memory, MemoryMut, Op, Options};
|
||||
use crate::component::{ComponentParams, ComponentType, Lift, Lower, Memory, MemoryMut, Options};
|
||||
use crate::{AsContextMut, StoreContextMut, ValRaw};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use std::any::Any;
|
||||
@@ -46,8 +46,8 @@ impl HostFunc {
|
||||
fn new<F, P, R>(func: F, entrypoint: VMLoweringCallee) -> Arc<HostFunc>
|
||||
where
|
||||
F: Send + Sync + 'static,
|
||||
P: ComponentParams,
|
||||
R: ComponentValue,
|
||||
P: ComponentParams + Lift,
|
||||
R: Lower,
|
||||
{
|
||||
Arc::new(HostFunc {
|
||||
entrypoint,
|
||||
@@ -71,12 +71,12 @@ impl HostFunc {
|
||||
|
||||
fn typecheck<P, R>(ty: FuncTypeIndex, types: &ComponentTypes) -> Result<()>
|
||||
where
|
||||
P: ComponentParams,
|
||||
R: ComponentValue,
|
||||
P: ComponentParams + Lift,
|
||||
R: Lower,
|
||||
{
|
||||
let ty = &types[ty];
|
||||
P::typecheck(&ty.params, types, Op::Lift).context("type mismatch with parameters")?;
|
||||
R::typecheck(&ty.result, types, Op::Lower).context("type mismatch with result")?;
|
||||
P::typecheck_params(&ty.params, types).context("type mismatch with parameters")?;
|
||||
R::typecheck(&ty.result, types).context("type mismatch with result")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -110,8 +110,8 @@ unsafe fn call_host<T, Params, Return, F>(
|
||||
closure: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
Params: ComponentValue,
|
||||
Return: ComponentValue,
|
||||
Params: Lift,
|
||||
Return: Lower,
|
||||
F: FnOnce(StoreContextMut<'_, T>, Params) -> Result<Return>,
|
||||
{
|
||||
/// Representation of arguments to this function when a return pointer is in
|
||||
@@ -227,7 +227,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_inbounds<T: ComponentValue>(memory: &[u8], ptr: &ValRaw) -> Result<usize> {
|
||||
fn validate_inbounds<T: ComponentType>(memory: &[u8], ptr: &ValRaw) -> Result<usize> {
|
||||
// FIXME: needs memory64 support
|
||||
let ptr = usize::try_from(ptr.get_u32())?;
|
||||
let end = match ptr.checked_add(T::size()) {
|
||||
@@ -271,8 +271,8 @@ macro_rules! impl_into_component_func {
|
||||
impl<T, F, $($args,)* R> IntoComponentFunc<T, ($($args,)*), R> for F
|
||||
where
|
||||
F: Fn($($args),*) -> Result<R> + Send + Sync + 'static,
|
||||
($($args,)*): ComponentParams + ComponentValue,
|
||||
R: ComponentValue,
|
||||
($($args,)*): ComponentParams + Lift,
|
||||
R: Lower,
|
||||
{
|
||||
extern "C" fn entrypoint(
|
||||
cx: *mut VMOpaqueContext,
|
||||
@@ -307,8 +307,8 @@ macro_rules! impl_into_component_func {
|
||||
impl<T, F, $($args,)* R> IntoComponentFunc<T, (StoreContextMut<'_, T>, $($args,)*), R> for F
|
||||
where
|
||||
F: Fn(StoreContextMut<'_, T>, $($args),*) -> Result<R> + Send + Sync + 'static,
|
||||
($($args,)*): ComponentParams + ComponentValue,
|
||||
R: ComponentValue,
|
||||
($($args,)*): ComponentParams + Lift,
|
||||
R: Lower,
|
||||
{
|
||||
extern "C" fn entrypoint(
|
||||
cx: *mut VMOpaqueContext,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
use crate::component::func::HostFunc;
|
||||
use crate::component::{Component, ComponentParams, ComponentValue, Func, TypedFunc};
|
||||
use crate::component::{Component, ComponentParams, Func, Lift, Lower, TypedFunc};
|
||||
use crate::instance::OwnedImports;
|
||||
use crate::store::{StoreOpaque, Stored};
|
||||
use crate::{AsContextMut, Module, StoreContext, StoreContextMut};
|
||||
@@ -86,8 +86,8 @@ impl Instance {
|
||||
name: &str,
|
||||
) -> Result<TypedFunc<Params, Results>>
|
||||
where
|
||||
Params: ComponentParams,
|
||||
Results: ComponentValue,
|
||||
Params: ComponentParams + Lower,
|
||||
Results: Lift,
|
||||
S: AsContextMut,
|
||||
{
|
||||
let f = self
|
||||
|
||||
@@ -11,7 +11,8 @@ mod matching;
|
||||
mod store;
|
||||
pub use self::component::Component;
|
||||
pub use self::func::{
|
||||
ComponentParams, ComponentValue, Func, IntoComponentFunc, Op, TypedFunc, WasmList, WasmStr,
|
||||
ComponentParams, ComponentType, Func, IntoComponentFunc, Lift, Lower, TypedFunc, WasmList,
|
||||
WasmStr,
|
||||
};
|
||||
pub use self::instance::{Instance, InstancePre};
|
||||
pub use self::linker::Linker;
|
||||
|
||||
@@ -158,10 +158,6 @@ fn typecheck() -> Result<()> {
|
||||
assert!(thunk.typed::<(u32,), (), _>(&store).is_err());
|
||||
assert!(thunk.typed::<(), (), _>(&store).is_ok());
|
||||
assert!(take_string.typed::<(), (), _>(&store).is_err());
|
||||
assert!(take_string.typed::<(), String, _>(&store).is_err());
|
||||
assert!(take_string
|
||||
.typed::<(String, String), String, _>(&store)
|
||||
.is_err());
|
||||
assert!(take_string.typed::<(String,), (), _>(&store).is_ok());
|
||||
assert!(take_string.typed::<(&str,), (), _>(&store).is_ok());
|
||||
assert!(take_string.typed::<(&[u8],), (), _>(&store).is_err());
|
||||
@@ -175,11 +171,7 @@ fn typecheck() -> Result<()> {
|
||||
assert!(ret_tuple1.typed::<(), (u32,), _>(&store).is_ok());
|
||||
assert!(ret_tuple1.typed::<(), u32, _>(&store).is_err());
|
||||
assert!(ret_string.typed::<(), (), _>(&store).is_err());
|
||||
assert!(ret_string.typed::<(), String, _>(&store).is_err());
|
||||
assert!(ret_string.typed::<(), &str, _>(&store).is_err());
|
||||
assert!(ret_string.typed::<(), WasmStr, _>(&store).is_ok());
|
||||
assert!(ret_list_u8.typed::<(), &[u8], _>(&store).is_err());
|
||||
assert!(ret_list_u8.typed::<(), Vec<u8>, _>(&store).is_err());
|
||||
assert!(ret_list_u8.typed::<(), WasmList<u16>, _>(&store).is_err());
|
||||
assert!(ret_list_u8.typed::<(), WasmList<i8>, _>(&store).is_err());
|
||||
assert!(ret_list_u8.typed::<(), WasmList<u8>, _>(&store).is_ok());
|
||||
|
||||
Reference in New Issue
Block a user