Repository: bytecodealliance/wasmtime
Pull request #5723 (2023-02-06 20:57:08)

Cranelift: Only build iconst for ints <= 64 bits
I audited the egraph "algebraic" optimization rules for any which construct an `iconst` on the right-hand side of the rule. In these cases we need to constrain the type passed to `iconst` to be both `fits_in_64` and `ty_int`, because `iconst` is not defined on other types.

If there's some reason why `icmp` is already constrained to <=64 bits, I'd prefer to add comments explaining why instead of adding constraints to the rules.

jameysharp: I think this should be back-ported for the upcoming release, once we've validated this change, even though we haven't received any bug reports about these rules. I don't think it needs to be backported further since this will be the first release with e-graph optimization on by default.

Patch:
diff --git a/cranelift/codegen/src/opts/algebraic.isle b/cranelift/codegen/src/opts/algebraic.isle
index 888dd51bb..061c61c51 100644
--- a/cranelift/codegen/src/opts/algebraic.isle
+++ b/cranelift/codegen/src/opts/algebraic.isle
@@ -101,7 +101,7 @@
       (subsume x))
 
 ;; x ^ x == 0.
-(rule (simplify (bxor (fits_in_64 ty) x x))
+(rule (simplify (bxor (fits_in_64 (ty_int ty)) x x))
       (subsume (iconst ty (imm64 0))))
 
 ;; x ^ not(x) == not(x) ^ x == -1.
@@ -167,6 +167,9 @@
       (iadd ty x x))
 
 ;; x*c == x<<log2(c) when c is a power of two.
+;; Note that the type of `iconst` must be the same as the type of `imul`,
+;; so these rules can only fire in situations where it's safe to construct an
+;; `iconst` of that type.
 (rule (simplify (imul ty x (iconst _ (imm64_power_of_two c))))
       (ishl ty x (iconst ty (imm64 c))))
 (rule (simplify (imul ty (iconst _ (imm64_power_of_two c)) x))
@@ -252,34 +255,34 @@
 ;; `x == x` is always true for integers; `x != x` is false. Strict
 ;; inequalities are false, and loose inequalities are true.
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.Equal) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.Equal) x x))
       (iconst ty (imm64 1)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.NotEqual) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.NotEqual) x x))
       (iconst ty (imm64 0)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.UnsignedGreaterThan) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.UnsignedGreaterThan) x x))
       (iconst ty (imm64 0)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.UnsignedGreaterThanOrEqual) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.UnsignedGreaterThanOrEqual) x x))
       (iconst ty (imm64 1)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.SignedGreaterThan) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.SignedGreaterThan) x x))
       (iconst ty (imm64 0)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.SignedGreaterThanOrEqual) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.SignedGreaterThanOrEqual) x x))
       (iconst ty (imm64 1)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.UnsignedLessThan) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.UnsignedLessThan) x x))
       (iconst ty (imm64 0)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.UnsignedLessThanOrEqual) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.UnsignedLessThanOrEqual) x x))
       (iconst ty (imm64 1)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.SignedLessThan) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.SignedLessThan) x x))
       (iconst ty (imm64 0)))
 (rule (simplify
-       (icmp (ty_int ty) (IntCC.SignedLessThanOrEqual) x x))
+       (icmp (fits_in_64 (ty_int ty)) (IntCC.SignedLessThanOrEqual) x x))
       (iconst ty (imm64 1)))
 
 ;; (x ^ -1) can be replaced with the `bnot` instruction
diff --git a/crates/fuzzing/src/generators/component_types.rs b/crates/fuzzing/src/generators/component_types.rs
index 05a008ab3..4c99ee3f9 100644
--- a/crates/fuzzing/src/generators/component_types.rs
+++ b/crates/fuzzing/src/generators/component_types.rs
@@ -173,7 +173,7 @@ macro_rules! define_static_api_test {
             let mut store: Store<Box<dyn Any>> = Store::new(&engine, Box::new(()));
             let instance = linker.instantiate(&mut store, &component).unwrap();
             let func = instance
-                .get_typed_func::<($($param,)*), R, _>(&mut store, EXPORT_FUNCTION)
+                .get_typed_func::<($($param,)*), R>(&mut store, EXPORT_FUNCTION)
                 .unwrap();
 
             while input.arbitrary()? {
diff --git a/crates/wasmtime/src/component/func.rs b/crates/wasmtime/src/component/func.rs
index 69f6817a4..9a311a469 100644
--- a/crates/wasmtime/src/component/func.rs
+++ b/crates/wasmtime/src/component/func.rs
@@ -185,7 +185,7 @@ impl Func {
     /// # use wasmtime::component::Func;
     /// # use wasmtime::Store;
     /// # fn foo(func: &Func, store: &mut Store<()>) -> anyhow::Result<()> {
-    /// let typed = func.typed::<(), (), _>(&store)?;
+    /// let typed = func.typed::<(), ()>(&store)?;
     /// typed.call(store, ())?;
     /// # Ok(())
     /// # }
@@ -198,7 +198,7 @@ impl Func {
     /// # use wasmtime::component::Func;
     /// # use wasmtime::Store;
     /// # fn foo(func: &Func, mut store: Store<()>) -> anyhow::Result<()> {
-    /// let typed = func.typed::<(&str,), (String,), _>(&store)?;
+    /// let typed = func.typed::<(&str,), (String,)>(&store)?;
     /// let ret = typed.call(&mut store, ("Hello, ",))?.0;
     /// println!("returned string was: {}", ret);
     /// # Ok(())
@@ -211,17 +211,16 @@ impl Func {
     /// # use wasmtime::component::Func;
     /// # use wasmtime::Store;
     /// # fn foo(func: &Func, mut store: Store<()>) -> anyhow::Result<()> {
-    /// let typed = func.typed::<(u32, Option<&str>, &[u8]), (bool,), _>(&store)?;
+    /// let typed = func.typed::<(u32, Option<&str>, &[u8]), (bool,)>(&store)?;
     /// let ok: bool = typed.call(&mut store, (1, Some("hello"), b"bytes!"))?.0;
     /// println!("return value was: {ok}");
     /// # Ok(())
     /// # }
     /// ```
-    pub fn typed<Params, Return, S>(&self, store: S) -> Result<TypedFunc<Params, Return>>
+    pub fn typed<Params, Return>(&self, store: impl AsContext) -> Result<TypedFunc<Params, Return>>
     where
         Params: ComponentNamedList + Lower,
         Return: ComponentNamedList + Lift,
-        S: AsContext,
     {
         self._typed(store.as_context().0)
     }
diff --git a/crates/wasmtime/src/component/instance.rs b/crates/wasmtime/src/component/instance.rs
index 5c00b8bc3..39853e330 100644
--- a/crates/wasmtime/src/component/instance.rs
+++ b/crates/wasmtime/src/component/instance.rs
@@ -85,20 +85,19 @@ impl Instance {
     /// # Panics
     ///
     /// Panics if `store` does not own this instance.
-    pub fn get_typed_func<Params, Results, S>(
+    pub fn get_typed_func<Params, Results>(
         &self,
-        mut store: S,
+        mut store: impl AsContextMut,
         name: &str,
     ) -> Result<TypedFunc<Params, Results>>
     where
         Params: ComponentNamedList + Lower,
         Results: ComponentNamedList + Lift,
-        S: AsContextMut,
     {
         let f = self
             .get_func(store.as_context_mut(), name)
             .ok_or_else(|| anyhow!("failed to find function export `{}`", name))?;
-        Ok(f.typed::<Params, Results, _>(store)
+        Ok(f.typed::<Params, Results>(store)
             .with_context(|| format!("failed to convert function `{}` to given type", name))?)
     }
 
diff --git a/winch/src/compile.rs b/winch/src/compile.rs
index 0f1c49239..657380104 100644
--- a/winch/src/compile.rs
+++ b/winch/src/compile.rs
@@ -56,7 +56,7 @@ fn compile(
 ) -> Result<()> {
     let index = module.func_index(f.0);
     let sig = types
-        .func_type_at(index.as_u32())
+        .function_at(index.as_u32())
         .expect(&format!("function type at index {:?}", index.as_u32()));
     let FunctionBodyData { body, validator } = f.1;
     let validator = validator.into_validator(Default::default());
@@ -64,6 +64,7 @@ fn compile(
         .compile_function(&sig, &body, validator)
         .expect("Couldn't compile function");
 
+    println!("Disassembly for function: {}", index.as_u32());
     disasm(buffer.data(), isa)?
         .iter()
         .for_each(|s| println!("{}", s));


Test patch:
diff --git a/tests/all/component_model/aot.rs b/tests/all/component_model/aot.rs
index e91eb8690..2a86655a8 100644
--- a/tests/all/component_model/aot.rs
+++ b/tests/all/component_model/aot.rs
@@ -62,7 +62,7 @@ fn mildly_more_interesting() -> Result<()> {
     let component = unsafe { Component::deserialize(&engine, &component)? };
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(), (u32,), _>(&mut store, "a")?;
+    let func = instance.get_typed_func::<(), (u32,)>(&mut store, "a")?;
     assert_eq!(func.call(&mut store, ())?, (103,));
 
     Ok(())
diff --git a/tests/all/component_model/async.rs b/tests/all/component_model/async.rs
index 816a02f1e..01c7341a6 100644
--- a/tests/all/component_model/async.rs
+++ b/tests/all/component_model/async.rs
@@ -28,13 +28,13 @@ async fn smoke() -> Result<()> {
         .instantiate_async(&mut store, &component)
         .await?;
 
-    let thunk = instance.get_typed_func::<(), (), _>(&mut store, "thunk")?;
+    let thunk = instance.get_typed_func::<(), ()>(&mut store, "thunk")?;
 
     thunk.call_async(&mut store, ()).await?;
     thunk.post_return_async(&mut store).await?;
 
     let err = instance
-        .get_typed_func::<(), (), _>(&mut store, "thunk-trap")?
+        .get_typed_func::<(), ()>(&mut store, "thunk-trap")?
         .call_async(&mut store, ())
         .await
         .unwrap_err();
@@ -79,7 +79,7 @@ async fn smoke_func_wrap() -> Result<()> {
 
     let instance = linker.instantiate_async(&mut store, &component).await?;
 
-    let thunk = instance.get_typed_func::<(), (), _>(&mut store, "thunk")?;
+    let thunk = instance.get_typed_func::<(), ()>(&mut store, "thunk")?;
 
     thunk.call_async(&mut store, ()).await?;
     thunk.post_return_async(&mut store).await?;
diff --git a/tests/all/component_model/func.rs b/tests/all/component_model/func.rs
index 6751be24c..f36e703b7 100644
--- a/tests/all/component_model/func.rs
+++ b/tests/all/component_model/func.rs
@@ -31,10 +31,10 @@ fn thunks() -> Result<()> {
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
     instance
-        .get_typed_func::<(), (), _>(&mut store, "thunk")?
+        .get_typed_func::<(), ()>(&mut store, "thunk")?
         .call_and_post_return(&mut store, ())?;
     let err = instance
-        .get_typed_func::<(), (), _>(&mut store, "thunk-trap")?
+        .get_typed_func::<(), ()>(&mut store, "thunk-trap")?
         .call(&mut store, ())
         .unwrap_err();
     assert_eq!(err.downcast::<Trap>()?, Trap::UnreachableCodeReached);
@@ -96,34 +96,30 @@ fn typecheck() -> Result<()> {
     let ret_tuple1 = instance.get_func(&mut store, "ret-tuple1").unwrap();
     let ret_string = instance.get_func(&mut store, "ret-string").unwrap();
     let ret_list_u8 = instance.get_func(&mut store, "ret-list-u8").unwrap();
-    assert!(thunk.typed::<(), (u32,), _>(&store).is_err());
-    assert!(thunk.typed::<(u32,), (), _>(&store).is_err());
-    assert!(thunk.typed::<(), (), _>(&store).is_ok());
-    assert!(tuple_thunk.typed::<(), (), _>(&store).is_err());
-    assert!(tuple_thunk.typed::<((),), (), _>(&store).is_err());
-    assert!(tuple_thunk.typed::<((),), ((),), _>(&store).is_ok());
-    assert!(take_string.typed::<(), (), _>(&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());
-    assert!(take_two_args.typed::<(), (), _>(&store).is_err());
-    assert!(take_two_args
-        .typed::<(i32, &[u8]), (u32,), _>(&store)
-        .is_err());
-    assert!(take_two_args.typed::<(u32, &[u8]), (), _>(&store).is_err());
-    assert!(take_two_args.typed::<(i32, &[u8]), (), _>(&store).is_ok());
-    assert!(ret_tuple.typed::<(), (), _>(&store).is_err());
-    assert!(ret_tuple.typed::<(), (u8,), _>(&store).is_err());
-    assert!(ret_tuple.typed::<(), (u8, i8), _>(&store).is_ok());
-    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::<(), (WasmStr,), _>(&store).is_ok());
-    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());
+    assert!(thunk.typed::<(), (u32,)>(&store).is_err());
+    assert!(thunk.typed::<(u32,), ()>(&store).is_err());
+    assert!(thunk.typed::<(), ()>(&store).is_ok());
+    assert!(tuple_thunk.typed::<(), ()>(&store).is_err());
+    assert!(tuple_thunk.typed::<((),), ()>(&store).is_err());
+    assert!(tuple_thunk.typed::<((),), ((),)>(&store).is_ok());
+    assert!(take_string.typed::<(), ()>(&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());
+    assert!(take_two_args.typed::<(), ()>(&store).is_err());
+    assert!(take_two_args.typed::<(i32, &[u8]), (u32,)>(&store).is_err());
+    assert!(take_two_args.typed::<(u32, &[u8]), ()>(&store).is_err());
+    assert!(take_two_args.typed::<(i32, &[u8]), ()>(&store).is_ok());
+    assert!(ret_tuple.typed::<(), ()>(&store).is_err());
+    assert!(ret_tuple.typed::<(), (u8,)>(&store).is_err());
+    assert!(ret_tuple.typed::<(), (u8, i8)>(&store).is_ok());
+    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::<(), (WasmStr,)>(&store).is_ok());
+    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());
 
     Ok(())
 }
@@ -198,68 +194,68 @@ fn integers() -> Result<()> {
 
     // Passing in 100 is valid for all primitives
     instance
-        .get_typed_func::<(u8,), (), _>(&mut store, "take-u8")?
+        .get_typed_func::<(u8,), ()>(&mut store, "take-u8")?
         .call_and_post_return(&mut store, (100,))?;
     instance
-        .get_typed_func::<(i8,), (), _>(&mut store, "take-s8")?
+        .get_typed_func::<(i8,), ()>(&mut store, "take-s8")?
         .call_and_post_return(&mut store, (100,))?;
     instance
-        .get_typed_func::<(u16,), (), _>(&mut store, "take-u16")?
+        .get_typed_func::<(u16,), ()>(&mut store, "take-u16")?
         .call_and_post_return(&mut store, (100,))?;
     instance
-        .get_typed_func::<(i16,), (), _>(&mut store, "take-s16")?
+        .get_typed_func::<(i16,), ()>(&mut store, "take-s16")?
         .call_and_post_return(&mut store, (100,))?;
     instance
-        .get_typed_func::<(u32,), (), _>(&mut store, "take-u32")?
+        .get_typed_func::<(u32,), ()>(&mut store, "take-u32")?
         .call_and_post_return(&mut store, (100,))?;
     instance
-        .get_typed_func::<(i32,), (), _>(&mut store, "take-s32")?
+        .get_typed_func::<(i32,), ()>(&mut store, "take-s32")?
         .call_and_post_return(&mut store, (100,))?;
     instance
-        .get_typed_func::<(u64,), (), _>(&mut store, "take-u64")?
+        .get_typed_func::<(u64,), ()>(&mut store, "take-u64")?
         .call_and_post_return(&mut store, (100,))?;
     instance
-        .get_typed_func::<(i64,), (), _>(&mut store, "take-s64")?
+        .get_typed_func::<(i64,), ()>(&mut store, "take-s64")?
         .call_and_post_return(&mut store, (100,))?;
 
     // This specific wasm instance traps if any value other than 100 is passed
     new_instance(&mut store)?
-        .get_typed_func::<(u8,), (), _>(&mut store, "take-u8")?
+        .get_typed_func::<(u8,), ()>(&mut store, "take-u8")?
         .call(&mut store, (101,))
         .unwrap_err()
         .downcast::<Trap>()?;
     new_instance(&mut store)?
-        .get_typed_func::<(i8,), (), _>(&mut store, "take-s8")?
+        .get_typed_func::<(i8,), ()>(&mut store, "take-s8")?
         .call(&mut store, (101,))
         .unwrap_err()
         .downcast::<Trap>()?;
     new_instance(&mut store)?
-        .get_typed_func::<(u16,), (), _>(&mut store, "take-u16")?
+        .get_typed_func::<(u16,), ()>(&mut store, "take-u16")?
         .call(&mut store, (101,))
         .unwrap_err()
         .downcast::<Trap>()?;
     new_instance(&mut store)?
-        .get_typed_func::<(i16,), (), _>(&mut store, "take-s16")?
+        .get_typed_func::<(i16,), ()>(&mut store, "take-s16")?
         .call(&mut store, (101,))
         .unwrap_err()
         .downcast::<Trap>()?;
     new_instance(&mut store)?
-        .get_typed_func::<(u32,), (), _>(&mut store, "take-u32")?
+        .get_typed_func::<(u32,), ()>(&mut store, "take-u32")?
         .call(&mut store, (101,))
         .unwrap_err()
         .downcast::<Trap>()?;
     new_instance(&mut store)?
-        .get_typed_func::<(i32,), (), _>(&mut store, "take-s32")?
+        .get_typed_func::<(i32,), ()>(&mut store, "take-s32")?
         .call(&mut store, (101,))
         .unwrap_err()
         .downcast::<Trap>()?;
     new_instance(&mut store)?
-        .get_typed_func::<(u64,), (), _>(&mut store, "take-u64")?
+        .get_typed_func::<(u64,), ()>(&mut store, "take-u64")?
         .call(&mut store, (101,))
         .unwrap_err()
         .downcast::<Trap>()?;
     new_instance(&mut store)?
-        .get_typed_func::<(i64,), (), _>(&mut store, "take-s64")?
+        .get_typed_func::<(i64,), ()>(&mut store, "take-s64")?
         .call(&mut store, (101,))
         .unwrap_err()
         .downcast::<Trap>()?;
@@ -267,49 +263,49 @@ fn integers() -> Result<()> {
     // Zero can be returned as any integer
     assert_eq!(
         instance
-            .get_typed_func::<(), (u8,), _>(&mut store, "ret-u8")?
+            .get_typed_func::<(), (u8,)>(&mut store, "ret-u8")?
             .call_and_post_return(&mut store, ())?,
         (0,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i8,), _>(&mut store, "ret-s8")?
+            .get_typed_func::<(), (i8,)>(&mut store, "ret-s8")?
             .call_and_post_return(&mut store, ())?,
         (0,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (u16,), _>(&mut store, "ret-u16")?
+            .get_typed_func::<(), (u16,)>(&mut store, "ret-u16")?
             .call_and_post_return(&mut store, ())?,
         (0,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i16,), _>(&mut store, "ret-s16")?
+            .get_typed_func::<(), (i16,)>(&mut store, "ret-s16")?
             .call_and_post_return(&mut store, ())?,
         (0,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (u32,), _>(&mut store, "ret-u32")?
+            .get_typed_func::<(), (u32,)>(&mut store, "ret-u32")?
             .call_and_post_return(&mut store, ())?,
         (0,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i32,), _>(&mut store, "ret-s32")?
+            .get_typed_func::<(), (i32,)>(&mut store, "ret-s32")?
             .call_and_post_return(&mut store, ())?,
         (0,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (u64,), _>(&mut store, "ret-u64")?
+            .get_typed_func::<(), (u64,)>(&mut store, "ret-u64")?
             .call_and_post_return(&mut store, ())?,
         (0,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i64,), _>(&mut store, "ret-s64")?
+            .get_typed_func::<(), (i64,)>(&mut store, "ret-s64")?
             .call_and_post_return(&mut store, ())?,
         (0,)
     );
@@ -317,49 +313,49 @@ fn integers() -> Result<()> {
     // Returning -1 should reinterpret the bytes as defined by each type.
     assert_eq!(
         instance
-            .get_typed_func::<(), (u8,), _>(&mut store, "retm1-u8")?
+            .get_typed_func::<(), (u8,)>(&mut store, "retm1-u8")?
             .call_and_post_return(&mut store, ())?,
         (0xff,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i8,), _>(&mut store, "retm1-s8")?
+            .get_typed_func::<(), (i8,)>(&mut store, "retm1-s8")?
             .call_and_post_return(&mut store, ())?,
         (-1,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (u16,), _>(&mut store, "retm1-u16")?
+            .get_typed_func::<(), (u16,)>(&mut store, "retm1-u16")?
             .call_and_post_return(&mut store, ())?,
         (0xffff,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i16,), _>(&mut store, "retm1-s16")?
+            .get_typed_func::<(), (i16,)>(&mut store, "retm1-s16")?
             .call_and_post_return(&mut store, ())?,
         (-1,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (u32,), _>(&mut store, "retm1-u32")?
+            .get_typed_func::<(), (u32,)>(&mut store, "retm1-u32")?
             .call_and_post_return(&mut store, ())?,
         (0xffffffff,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i32,), _>(&mut store, "retm1-s32")?
+            .get_typed_func::<(), (i32,)>(&mut store, "retm1-s32")?
             .call_and_post_return(&mut store, ())?,
         (-1,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (u64,), _>(&mut store, "retm1-u64")?
+            .get_typed_func::<(), (u64,)>(&mut store, "retm1-u64")?
             .call_and_post_return(&mut store, ())?,
         (0xffffffff_ffffffff,)
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i64,), _>(&mut store, "retm1-s64")?
+            .get_typed_func::<(), (i64,)>(&mut store, "retm1-s64")?
             .call_and_post_return(&mut store, ())?,
         (-1,)
     );
@@ -368,37 +364,37 @@ fn integers() -> Result<()> {
     let ret: u32 = 100000;
     assert_eq!(
         instance
-            .get_typed_func::<(), (u8,), _>(&mut store, "retbig-u8")?
+            .get_typed_func::<(), (u8,)>(&mut store, "retbig-u8")?
             .call_and_post_return(&mut store, ())?,
         (ret as u8,),
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i8,), _>(&mut store, "retbig-s8")?
+            .get_typed_func::<(), (i8,)>(&mut store, "retbig-s8")?
             .call_and_post_return(&mut store, ())?,
         (ret as i8,),
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (u16,), _>(&mut store, "retbig-u16")?
+            .get_typed_func::<(), (u16,)>(&mut store, "retbig-u16")?
             .call_and_post_return(&mut store, ())?,
         (ret as u16,),
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i16,), _>(&mut store, "retbig-s16")?
+            .get_typed_func::<(), (i16,)>(&mut store, "retbig-s16")?
             .call_and_post_return(&mut store, ())?,
         (ret as i16,),
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (u32,), _>(&mut store, "retbig-u32")?
+            .get_typed_func::<(), (u32,)>(&mut store, "retbig-u32")?
             .call_and_post_return(&mut store, ())?,
         (ret,),
     );
     assert_eq!(
         instance
-            .get_typed_func::<(), (i32,), _>(&mut store, "retbig-s32")?
+            .get_typed_func::<(), (i32,)>(&mut store, "retbig-s32")?
             .call_and_post_return(&mut store, ())?,
         (ret as i32,),
     );
@@ -430,19 +426,19 @@ fn type_layers() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     instance
-        .get_typed_func::<(Box<u32>,), (), _>(&mut store, "take-u32")?
+        .get_typed_func::<(Box<u32>,), ()>(&mut store, "take-u32")?
         .call_and_post_return(&mut store, (Box::new(2),))?;
     instance
-        .get_typed_func::<(&u32,), (), _>(&mut store, "take-u32")?
+        .get_typed_func::<(&u32,), ()>(&mut store, "take-u32")?
         .call_and_post_return(&mut store, (&2,))?;
     instance
-        .get_typed_func::<(Rc<u32>,), (), _>(&mut store, "take-u32")?
+        .get_typed_func::<(Rc<u32>,), ()>(&mut store, "take-u32")?
         .call_and_post_return(&mut store, (Rc::new(2),))?;
     instance
-        .get_typed_func::<(Arc<u32>,), (), _>(&mut store, "take-u32")?
+        .get_typed_func::<(Arc<u32>,), ()>(&mut store, "take-u32")?
         .call_and_post_return(&mut store, (Arc::new(2),))?;
     instance
-        .get_typed_func::<(&Box<Arc<Rc<u32>>>,), (), _>(&mut store, "take-u32")?
+        .get_typed_func::<(&Box<Arc<Rc<u32>>>,), ()>(&mut store, "take-u32")?
         .call_and_post_return(&mut store, (&Box::new(Arc::new(Rc::new(2))),))?;
 
     Ok(())
@@ -491,10 +487,10 @@ fn floats() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let f32_to_u32 = instance.get_typed_func::<(f32,), (u32,), _>(&mut store, "f32-to-u32")?;
-    let f64_to_u64 = instance.get_typed_func::<(f64,), (u64,), _>(&mut store, "f64-to-u64")?;
-    let u32_to_f32 = instance.get_typed_func::<(u32,), (f32,), _>(&mut store, "u32-to-f32")?;
-    let u64_to_f64 = instance.get_typed_func::<(u64,), (f64,), _>(&mut store, "u64-to-f64")?;
+    let f32_to_u32 = instance.get_typed_func::<(f32,), (u32,)>(&mut store, "f32-to-u32")?;
+    let f64_to_u64 = instance.get_typed_func::<(f64,), (u64,)>(&mut store, "f64-to-u64")?;
+    let u32_to_f32 = instance.get_typed_func::<(u32,), (f32,)>(&mut store, "u32-to-f32")?;
+    let u64_to_f64 = instance.get_typed_func::<(u64,), (f64,)>(&mut store, "u64-to-f64")?;
 
     assert_eq!(f32_to_u32.call(&mut store, (1.0,))?, (1.0f32.to_bits(),));
     f32_to_u32.post_return(&mut store)?;
@@ -558,8 +554,8 @@ fn bools() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let u32_to_bool = instance.get_typed_func::<(u32,), (bool,), _>(&mut store, "u32-to-bool")?;
-    let bool_to_u32 = instance.get_typed_func::<(bool,), (u32,), _>(&mut store, "bool-to-u32")?;
+    let u32_to_bool = instance.get_typed_func::<(u32,), (bool,)>(&mut store, "u32-to-bool")?;
+    let bool_to_u32 = instance.get_typed_func::<(bool,), (u32,)>(&mut store, "bool-to-u32")?;
 
     assert_eq!(bool_to_u32.call(&mut store, (false,))?, (0,));
     bool_to_u32.post_return(&mut store)?;
@@ -597,8 +593,8 @@ fn chars() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let u32_to_char = instance.get_typed_func::<(u32,), (char,), _>(&mut store, "u32-to-char")?;
-    let char_to_u32 = instance.get_typed_func::<(char,), (u32,), _>(&mut store, "char-to-u32")?;
+    let u32_to_char = instance.get_typed_func::<(u32,), (char,)>(&mut store, "u32-to-char")?;
+    let char_to_u32 = instance.get_typed_func::<(char,), (u32,)>(&mut store, "char-to-u32")?;
 
     let mut roundtrip = |x: char| -> Result<()> {
         assert_eq!(char_to_u32.call(&mut store, (x,))?, (x as u32,));
@@ -617,7 +613,7 @@ fn chars() -> Result<()> {
     let u32_to_char = |store: &mut Store<()>| {
         Linker::new(&engine)
             .instantiate(&mut *store, &component)?
-            .get_typed_func::<(u32,), (char,), _>(&mut *store, "u32-to-char")
+            .get_typed_func::<(u32,), (char,)>(&mut *store, "u32-to-char")
     };
     let err = u32_to_char(&mut store)?
         .call(&mut store, (0xd800,))
@@ -679,12 +675,12 @@ fn tuple_result() -> Result<()> {
 
     let input = (-1, 100, 3.0, 100.0);
     let output = instance
-        .get_typed_func::<(i8, u16, f32, f64), ((i8, u16, f32, f64),), _>(&mut store, "tuple")?
+        .get_typed_func::<(i8, u16, f32, f64), ((i8, u16, f32, f64),)>(&mut store, "tuple")?
         .call_and_post_return(&mut store, input)?;
     assert_eq!((input,), output);
 
     let invalid_func =
-        instance.get_typed_func::<(), ((i8, u16, f32, f64),), _>(&mut store, "invalid")?;
+        instance.get_typed_func::<(), ((i8, u16, f32, f64),)>(&mut store, "invalid")?;
     let err = invalid_func.call(&mut store, ()).err().unwrap();
     assert!(
         err.to_string().contains("pointer out of bounds of memory"),
@@ -760,13 +756,13 @@ fn strings() -> Result<()> {
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
     let list8_to_str =
-        instance.get_typed_func::<(&[u8],), (WasmStr,), _>(&mut store, "list8-to-str")?;
+        instance.get_typed_func::<(&[u8],), (WasmStr,)>(&mut store, "list8-to-str")?;
     let str_to_list8 =
-        instance.get_typed_func::<(&str,), (WasmList<u8>,), _>(&mut store, "str-to-list8")?;
+        instance.get_typed_func::<(&str,), (WasmList<u8>,)>(&mut store, "str-to-list8")?;
     let list16_to_str =
-        instance.get_typed_func::<(&[u16],), (WasmStr,), _>(&mut store, "list16-to-str")?;
+        instance.get_typed_func::<(&[u16],), (WasmStr,)>(&mut store, "list16-to-str")?;
     let str_to_list16 =
-        instance.get_typed_func::<(&str,), (WasmList<u16>,), _>(&mut store, "str-to-list16")?;
+        instance.get_typed_func::<(&str,), (WasmList<u16>,)>(&mut store, "str-to-list16")?;
 
     let mut roundtrip = |x: &str| -> Result<()> {
         let ret = list8_to_str.call(&mut store, (x.as_bytes(),))?.0;
@@ -913,7 +909,7 @@ fn many_parameters() -> Result<()> {
         &[bool],
         &[char],
         &[&str],
-    ), (WasmList<u8>, u32), _>(&mut store, "many-param")?;
+    ), (WasmList<u8>, u32)>(&mut store, "many-param")?;
 
     let input = (
         -100,
@@ -1095,7 +1091,7 @@ fn some_traps() -> Result<()> {
 
     // This should fail when calling the allocator function for the argument
     let err = instance(&mut store)?
-        .get_typed_func::<(&[u8],), (), _>(&mut store, "take-list-unreachable")?
+        .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-unreachable")?
         .call(&mut store, (&[],))
         .unwrap_err()
         .downcast::<Trap>()?;
@@ -1103,7 +1099,7 @@ fn some_traps() -> Result<()> {
 
     // This should fail when calling the allocator function for the argument
     let err = instance(&mut store)?
-        .get_typed_func::<(&str,), (), _>(&mut store, "take-string-unreachable")?
+        .get_typed_func::<(&str,), ()>(&mut store, "take-string-unreachable")?
         .call(&mut store, ("",))
         .unwrap_err()
         .downcast::<Trap>()?;
@@ -1112,7 +1108,7 @@ fn some_traps() -> Result<()> {
     // This should fail when calling the allocator function for the space
     // to store the arguments (before arguments are even lowered)
     let err = instance(&mut store)?
-        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), (), _>(
+        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
             &mut store,
             "take-many-unreachable",
         )?
@@ -1137,27 +1133,27 @@ fn some_traps() -> Result<()> {
         );
     }
     let err = instance(&mut store)?
-        .get_typed_func::<(&[u8],), (), _>(&mut store, "take-list-base-oob")?
+        .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")?
         .call(&mut store, (&[],))
         .unwrap_err();
     assert_oob(&err);
     let err = instance(&mut store)?
-        .get_typed_func::<(&[u8],), (), _>(&mut store, "take-list-base-oob")?
+        .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")?
         .call(&mut store, (&[1],))
         .unwrap_err();
     assert_oob(&err);
     let err = instance(&mut store)?
-        .get_typed_func::<(&str,), (), _>(&mut store, "take-string-base-oob")?
+        .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")?
         .call(&mut store, ("",))
         .unwrap_err();
     assert_oob(&err);
     let err = instance(&mut store)?
-        .get_typed_func::<(&str,), (), _>(&mut store, "take-string-base-oob")?
+        .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")?
         .call(&mut store, ("x",))
         .unwrap_err();
     assert_oob(&err);
     let err = instance(&mut store)?
-        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), (), _>(
+        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
             &mut store,
             "take-many-base-oob",
         )?
@@ -1169,29 +1165,29 @@ fn some_traps() -> Result<()> {
     // end of memory that empty things are fine, but larger things are not.
 
     instance(&mut store)?
-        .get_typed_func::<(&[u8],), (), _>(&mut store, "take-list-end-oob")?
+        .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
         .call_and_post_return(&mut store, (&[],))?;
     instance(&mut store)?
-        .get_typed_func::<(&[u8],), (), _>(&mut store, "take-list-end-oob")?
+        .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
         .call_and_post_return(&mut store, (&[1, 2, 3, 4],))?;
     let err = instance(&mut store)?
-        .get_typed_func::<(&[u8],), (), _>(&mut store, "take-list-end-oob")?
+        .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
         .call(&mut store, (&[1, 2, 3, 4, 5],))
         .unwrap_err();
     assert_oob(&err);
     instance(&mut store)?
-        .get_typed_func::<(&str,), (), _>(&mut store, "take-string-end-oob")?
+        .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
         .call_and_post_return(&mut store, ("",))?;
     instance(&mut store)?
-        .get_typed_func::<(&str,), (), _>(&mut store, "take-string-end-oob")?
+        .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
         .call_and_post_return(&mut store, ("abcd",))?;
     let err = instance(&mut store)?
-        .get_typed_func::<(&str,), (), _>(&mut store, "take-string-end-oob")?
+        .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
         .call(&mut store, ("abcde",))
         .unwrap_err();
     assert_oob(&err);
     let err = instance(&mut store)?
-        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), (), _>(
+        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
             &mut store,
             "take-many-end-oob",
         )?
@@ -1203,7 +1199,7 @@ fn some_traps() -> Result<()> {
     // arguments, is in-bounds but then all further allocations, such as for
     // each individual string, are all out of bounds.
     let err = instance(&mut store)?
-        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), (), _>(
+        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
             &mut store,
             "take-many-second-oob",
         )?
@@ -1211,7 +1207,7 @@ fn some_traps() -> Result<()> {
         .unwrap_err();
     assert_oob(&err);
     let err = instance(&mut store)?
-        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), (), _>(
+        .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
             &mut store,
             "take-many-second-oob",
         )?
@@ -1267,7 +1263,7 @@ fn char_bool_memory() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(u32, u32), (bool, char), _>(&mut store, "ret-tuple")?;
+    let func = instance.get_typed_func::<(u32, u32), (bool, char)>(&mut store, "ret-tuple")?;
 
     let ret = func.call(&mut store, (0, 'a' as u32))?;
     assert_eq!(ret, (false, 'a'));
@@ -1337,10 +1333,10 @@ fn string_list_oob() -> Result<()> {
     let mut store = Store::new(&engine, ());
     let ret_list_u8 = Linker::new(&engine)
         .instantiate(&mut store, &component)?
-        .get_typed_func::<(), (WasmList<u8>,), _>(&mut store, "ret-list-u8")?;
+        .get_typed_func::<(), (WasmList<u8>,)>(&mut store, "ret-list-u8")?;
     let ret_string = Linker::new(&engine)
         .instantiate(&mut store, &component)?
-        .get_typed_func::<(), (WasmStr,), _>(&mut store, "ret-string")?;
+        .get_typed_func::<(), (WasmStr,)>(&mut store, "ret-string")?;
 
     let err = ret_list_u8.call(&mut store, ()).err().unwrap();
     assert!(err.to_string().contains("out of bounds"), "{}", err);
@@ -1394,7 +1390,7 @@ fn tuples() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let foo = instance.get_typed_func::<((i32, f64), (i8,)), ((u16,),), _>(&mut store, "foo")?;
+    let foo = instance.get_typed_func::<((i32, f64), (i8,)), ((u16,),)>(&mut store, "foo")?;
     assert_eq!(foo.call(&mut store, ((0, 1.0), (2,)))?, ((3,),));
 
     Ok(())
@@ -1497,14 +1493,14 @@ fn option() -> Result<()> {
     let linker = Linker::new(&engine);
     let instance = linker.instantiate(&mut store, &component)?;
     let option_unit_to_u32 =
-        instance.get_typed_func::<(Option<()>,), (u32,), _>(&mut store, "option-unit-to-u32")?;
+        instance.get_typed_func::<(Option<()>,), (u32,)>(&mut store, "option-unit-to-u32")?;
     assert_eq!(option_unit_to_u32.call(&mut store, (None,))?, (0,));
     option_unit_to_u32.post_return(&mut store)?;
     assert_eq!(option_unit_to_u32.call(&mut store, (Some(()),))?, (1,));
     option_unit_to_u32.post_return(&mut store)?;
 
-    let option_u8_to_tuple = instance
-        .get_typed_func::<(Option<u8>,), (u32, u32), _>(&mut store, "option-u8-to-tuple")?;
+    let option_u8_to_tuple =
+        instance.get_typed_func::<(Option<u8>,), (u32, u32)>(&mut store, "option-u8-to-tuple")?;
     assert_eq!(option_u8_to_tuple.call(&mut store, (None,))?, (0, 0));
     option_u8_to_tuple.post_return(&mut store)?;
     assert_eq!(option_u8_to_tuple.call(&mut store, (Some(0),))?, (1, 0));
@@ -1512,8 +1508,8 @@ fn option() -> Result<()> {
     assert_eq!(option_u8_to_tuple.call(&mut store, (Some(100),))?, (1, 100));
     option_u8_to_tuple.post_return(&mut store)?;
 
-    let option_u32_to_tuple = instance
-        .get_typed_func::<(Option<u32>,), (u32, u32), _>(&mut store, "option-u32-to-tuple")?;
+    let option_u32_to_tuple =
+        instance.get_typed_func::<(Option<u32>,), (u32, u32)>(&mut store, "option-u32-to-tuple")?;
     assert_eq!(option_u32_to_tuple.call(&mut store, (None,))?, (0, 0));
     option_u32_to_tuple.post_return(&mut store)?;
     assert_eq!(option_u32_to_tuple.call(&mut store, (Some(0),))?, (1, 0));
@@ -1524,10 +1520,8 @@ fn option() -> Result<()> {
     );
     option_u32_to_tuple.post_return(&mut store)?;
 
-    let option_string_to_tuple = instance.get_typed_func::<(Option<&str>,), (u32, WasmStr), _>(
-        &mut store,
-        "option-string-to-tuple",
-    )?;
+    let option_string_to_tuple = instance
+        .get_typed_func::<(Option<&str>,), (u32, WasmStr)>(&mut store, "option-string-to-tuple")?;
     let (a, b) = option_string_to_tuple.call(&mut store, (None,))?;
     assert_eq!(a, 0);
     assert_eq!(b.to_str(&store)?, "");
@@ -1543,7 +1537,7 @@ fn option() -> Result<()> {
 
     let instance = linker.instantiate(&mut store, &component)?;
     let to_option_unit =
-        instance.get_typed_func::<(u32,), (Option<()>,), _>(&mut store, "to-option-unit")?;
+        instance.get_typed_func::<(u32,), (Option<()>,)>(&mut store, "to-option-unit")?;
     assert_eq!(to_option_unit.call(&mut store, (0,))?, (None,));
     to_option_unit.post_return(&mut store)?;
     assert_eq!(to_option_unit.call(&mut store, (1,))?, (Some(()),));
@@ -1553,7 +1547,7 @@ fn option() -> Result<()> {
 
     let instance = linker.instantiate(&mut store, &component)?;
     let to_option_u8 =
-        instance.get_typed_func::<(u32, u32), (Option<u8>,), _>(&mut store, "to-option-u8")?;
+        instance.get_typed_func::<(u32, u32), (Option<u8>,)>(&mut store, "to-option-u8")?;
     assert_eq!(to_option_u8.call(&mut store, (0x00_00, 0))?, (None,));
     to_option_u8.post_return(&mut store)?;
     assert_eq!(to_option_u8.call(&mut store, (0x00_01, 0))?, (Some(0),));
@@ -1564,7 +1558,7 @@ fn option() -> Result<()> {
 
     let instance = linker.instantiate(&mut store, &component)?;
     let to_option_u32 =
-        instance.get_typed_func::<(u32, u32), (Option<u32>,), _>(&mut store, "to-option-u32")?;
+        instance.get_typed_func::<(u32, u32), (Option<u32>,)>(&mut store, "to-option-u32")?;
     assert_eq!(to_option_u32.call(&mut store, (0, 0))?, (None,));
     to_option_u32.post_return(&mut store)?;
     assert_eq!(to_option_u32.call(&mut store, (1, 0))?, (Some(0),));
@@ -1578,7 +1572,7 @@ fn option() -> Result<()> {
 
     let instance = linker.instantiate(&mut store, &component)?;
     let to_option_string = instance
-        .get_typed_func::<(u32, &str), (Option<WasmStr>,), _>(&mut store, "to-option-string")?;
+        .get_typed_func::<(u32, &str), (Option<WasmStr>,)>(&mut store, "to-option-string")?;
     let ret = to_option_string.call(&mut store, (0, ""))?.0;
     assert!(ret.is_none());
     to_option_string.post_return(&mut store)?;
@@ -1678,15 +1672,15 @@ fn expected() -> Result<()> {
     let mut store = Store::new(&engine, ());
     let linker = Linker::new(&engine);
     let instance = linker.instantiate(&mut store, &component)?;
-    let take_expected_unit = instance
-        .get_typed_func::<(Result<(), ()>,), (u32,), _>(&mut store, "take-expected-unit")?;
+    let take_expected_unit =
+        instance.get_typed_func::<(Result<(), ()>,), (u32,)>(&mut store, "take-expected-unit")?;
     assert_eq!(take_expected_unit.call(&mut store, (Ok(()),))?, (0,));
     take_expected_unit.post_return(&mut store)?;
     assert_eq!(take_expected_unit.call(&mut store, (Err(()),))?, (1,));
     take_expected_unit.post_return(&mut store)?;
 
     let take_expected_u8_f32 = instance
-        .get_typed_func::<(Result<u8, f32>,), (u32, u32), _>(&mut store, "take-expected-u8-f32")?;
+        .get_typed_func::<(Result<u8, f32>,), (u32, u32)>(&mut store, "take-expected-u8-f32")?;
     assert_eq!(take_expected_u8_f32.call(&mut store, (Ok(1),))?, (0, 1));
     take_expected_u8_f32.post_return(&mut store)?;
     assert_eq!(
@@ -1695,11 +1689,10 @@ fn expected() -> Result<()> {
     );
     take_expected_u8_f32.post_return(&mut store)?;
 
-    let take_expected_string = instance
-        .get_typed_func::<(Result<&str, &[u8]>,), (u32, WasmStr), _>(
-            &mut store,
-            "take-expected-string",
-        )?;
+    let take_expected_string = instance.get_typed_func::<(Result<&str, &[u8]>,), (u32, WasmStr)>(
+        &mut store,
+        "take-expected-string",
+    )?;
     let (a, b) = take_expected_string.call(&mut store, (Ok("hello"),))?;
     assert_eq!(a, 0);
     assert_eq!(b.to_str(&store)?, "hello");
@@ -1711,7 +1704,7 @@ fn expected() -> Result<()> {
 
     let instance = linker.instantiate(&mut store, &component)?;
     let to_expected_unit =
-        instance.get_typed_func::<(u32,), (Result<(), ()>,), _>(&mut store, "to-expected-unit")?;
+        instance.get_typed_func::<(u32,), (Result<(), ()>,)>(&mut store, "to-expected-unit")?;
     assert_eq!(to_expected_unit.call(&mut store, (0,))?, (Ok(()),));
     to_expected_unit.post_return(&mut store)?;
     assert_eq!(to_expected_unit.call(&mut store, (1,))?, (Err(()),));
@@ -1721,7 +1714,7 @@ fn expected() -> Result<()> {
 
     let instance = linker.instantiate(&mut store, &component)?;
     let to_expected_s16_f32 = instance
-        .get_typed_func::<(u32, u32), (Result<i16, f32>,), _>(&mut store, "to-expected-s16-f32")?;
+        .get_typed_func::<(u32, u32), (Result<i16, f32>,)>(&mut store, "to-expected-s16-f32")?;
     assert_eq!(to_expected_s16_f32.call(&mut store, (0, 0))?, (Ok(0),));
     to_expected_s16_f32.post_return(&mut store)?;
     assert_eq!(to_expected_s16_f32.call(&mut store, (0, 100))?, (Ok(100),));
@@ -1801,7 +1794,7 @@ fn fancy_list() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     let func = instance
-        .get_typed_func::<(&[(Option<u8>, Result<(), &str>)],), (u32, u32, WasmList<u8>), _>(
+        .get_typed_func::<(&[(Option<u8>, Result<(), &str>)],), (u32, u32, WasmList<u8>)>(
             &mut store, "take",
         )?;
 
@@ -1932,7 +1925,7 @@ fn invalid_alignment() -> Result<()> {
             &str,
             &str,
             &str,
-        ), (), _>(&mut store, "many-params")?
+        ), ()>(&mut store, "many-params")?
         .call(&mut store, ("", "", "", "", "", "", "", "", "", "", "", ""))
         .unwrap_err();
     assert!(
@@ -1943,7 +1936,7 @@ fn invalid_alignment() -> Result<()> {
     );
 
     let err = instance(&mut store)?
-        .get_typed_func::<(), (WasmStr,), _>(&mut store, "string-ret")?
+        .get_typed_func::<(), (WasmStr,)>(&mut store, "string-ret")?
         .call(&mut store, ())
         .err()
         .unwrap();
@@ -1954,7 +1947,7 @@ fn invalid_alignment() -> Result<()> {
     );
 
     let err = instance(&mut store)?
-        .get_typed_func::<(), (WasmList<u32>,), _>(&mut store, "list-u32-ret")?
+        .get_typed_func::<(), (WasmList<u32>,)>(&mut store, "list-u32-ret")?
         .call(&mut store, ())
         .err()
         .unwrap();
@@ -2015,7 +2008,7 @@ fn drop_component_still_works() -> Result<()> {
         (store, instance)
     };
 
-    let f = instance.get_typed_func::<(), (), _>(&mut store, "f")?;
+    let f = instance.get_typed_func::<(), ()>(&mut store, "f")?;
     assert_eq!(*store.data(), 0);
     f.call(&mut store, ())?;
     assert_eq!(*store.data(), 2);
@@ -2088,7 +2081,7 @@ fn raw_slice_of_various_types() -> Result<()> {
     };
 
     let list = instance
-        .get_typed_func::<(), (WasmList<u8>,), _>(&mut store, "list-u8")?
+        .get_typed_func::<(), (WasmList<u8>,)>(&mut store, "list-u8")?
         .call_and_post_return(&mut store, ())?
         .0;
     assert_eq!(
@@ -2099,7 +2092,7 @@ fn raw_slice_of_various_types() -> Result<()> {
         ]
     );
     let list = instance
-        .get_typed_func::<(), (WasmList<i8>,), _>(&mut store, "list-i8")?
+        .get_typed_func::<(), (WasmList<i8>,)>(&mut store, "list-i8")?
         .call_and_post_return(&mut store, ())?
         .0;
     assert_eq!(
@@ -2111,7 +2104,7 @@ fn raw_slice_of_various_types() -> Result<()> {
     );
 
     let list = instance
-        .get_typed_func::<(), (WasmList<u16>,), _>(&mut store, "list-u16")?
+        .get_typed_func::<(), (WasmList<u16>,)>(&mut store, "list-u16")?
         .call_and_post_return(&mut store, ())?
         .0;
     assert_eq!(
@@ -2128,7 +2121,7 @@ fn raw_slice_of_various_types() -> Result<()> {
         ]
     );
     let list = instance
-        .get_typed_func::<(), (WasmList<i16>,), _>(&mut store, "list-i16")?
+        .get_typed_func::<(), (WasmList<i16>,)>(&mut store, "list-i16")?
         .call_and_post_return(&mut store, ())?
         .0;
     assert_eq!(
@@ -2145,7 +2138,7 @@ fn raw_slice_of_various_types() -> Result<()> {
         ]
     );
     let list = instance
-        .get_typed_func::<(), (WasmList<u32>,), _>(&mut store, "list-u32")?
+        .get_typed_func::<(), (WasmList<u32>,)>(&mut store, "list-u32")?
         .call_and_post_return(&mut store, ())?
         .0;
     assert_eq!(
@@ -2158,7 +2151,7 @@ fn raw_slice_of_various_types() -> Result<()> {
         ]
     );
     let list = instance
-        .get_typed_func::<(), (WasmList<i32>,), _>(&mut store, "list-i32")?
+        .get_typed_func::<(), (WasmList<i32>,)>(&mut store, "list-i32")?
         .call_and_post_return(&mut store, ())?
         .0;
     assert_eq!(
@@ -2171,7 +2164,7 @@ fn raw_slice_of_various_types() -> Result<()> {
         ]
     );
     let list = instance
-        .get_typed_func::<(), (WasmList<u64>,), _>(&mut store, "list-u64")?
+        .get_typed_func::<(), (WasmList<u64>,)>(&mut store, "list-u64")?
         .call_and_post_return(&mut store, ())?
         .0;
     assert_eq!(
@@ -2182,7 +2175,7 @@ fn raw_slice_of_various_types() -> Result<()> {
         ]
     );
     let list = instance
-        .get_typed_func::<(), (WasmList<i64>,), _>(&mut store, "list-i64")?
+        .get_typed_func::<(), (WasmList<i64>,)>(&mut store, "list-i64")?
         .call_and_post_return(&mut store, ())?
         .0;
     assert_eq!(
@@ -2220,7 +2213,7 @@ fn lower_then_lift() -> Result<()> {
     linker.root().func_wrap("f", |_, _: ()| Ok((2u32,)))?;
     let instance = linker.instantiate(&mut store, &component)?;
 
-    let f = instance.get_typed_func::<(), (i32,), _>(&mut store, "f")?;
+    let f = instance.get_typed_func::<(), (i32,)>(&mut store, "f")?;
     assert_eq!(f.call(&mut store, ())?, (2,));
 
     // First test strings when the import/export ABI happen to line up
@@ -2259,7 +2252,7 @@ fn lower_then_lift() -> Result<()> {
         })?;
     let instance = linker.instantiate(&mut store, &component)?;
 
-    let f = instance.get_typed_func::<(&str,), (), _>(&mut store, "f")?;
+    let f = instance.get_typed_func::<(&str,), ()>(&mut store, "f")?;
     f.call(&mut store, ("hello",))?;
 
     // Next test "type punning" where return values are reinterpreted just
@@ -2299,7 +2292,7 @@ fn lower_then_lift() -> Result<()> {
         })?;
     let instance = linker.instantiate(&mut store, &component)?;
 
-    let f = instance.get_typed_func::<(&str,), (WasmStr,), _>(&mut store, "f")?;
+    let f = instance.get_typed_func::<(&str,), (WasmStr,)>(&mut store, "f")?;
     let err = f.call(&mut store, ("hello",)).err().unwrap();
     assert!(
         err.to_string().contains("return pointer not aligned"),
@@ -2350,19 +2343,19 @@ fn errors_that_poison_instance() -> Result<()> {
     let mut store = Store::new(&engine, ());
     let linker = Linker::new(&engine);
     let instance = linker.instantiate(&mut store, &component)?;
-    let f1 = instance.get_typed_func::<(), (), _>(&mut store, "f1")?;
-    let f2 = instance.get_typed_func::<(), (), _>(&mut store, "f2")?;
+    let f1 = instance.get_typed_func::<(), ()>(&mut store, "f1")?;
+    let f2 = instance.get_typed_func::<(), ()>(&mut store, "f2")?;
     assert_unreachable(f1.call(&mut store, ()));
     assert_poisoned(f1.call(&mut store, ()));
     assert_poisoned(f2.call(&mut store, ()));
 
     let instance = linker.instantiate(&mut store, &component)?;
-    let f3 = instance.get_typed_func::<(&str,), (), _>(&mut store, "f3")?;
+    let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?;
     assert_unreachable(f3.call(&mut store, ("x",)));
     assert_poisoned(f3.call(&mut store, ("x",)));
 
     let instance = linker.instantiate(&mut store, &component)?;
-    let f4 = instance.get_typed_func::<(), (WasmStr,), _>(&mut store, "f4")?;
+    let f4 = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "f4")?;
     assert!(f4.call(&mut store, ()).is_err());
     assert_poisoned(f4.call(&mut store, ()));
 
@@ -2437,7 +2430,7 @@ fn run_export_with_internal_adapter() -> Result<()> {
     let mut store = Store::new(&engine, ());
     let linker = Linker::new(&engine);
     let instance = linker.instantiate(&mut store, &component)?;
-    let run = instance.get_typed_func::<(), (u32,), _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<(), (u32,)>(&mut store, "run")?;
     assert_eq!(run.call(&mut store, ())?, (5,));
     Ok(())
 }
diff --git a/tests/all/component_model/import.rs b/tests/all/component_model/import.rs
index ae771a646..60a598fa7 100644
--- a/tests/all/component_model/import.rs
+++ b/tests/all/component_model/import.rs
@@ -136,7 +136,7 @@ fn simple() -> Result<()> {
     )?;
     let instance = linker.instantiate(&mut store, &component)?;
     instance
-        .get_typed_func::<(), (), _>(&mut store, "call")?
+        .get_typed_func::<(), ()>(&mut store, "call")?
         .call(&mut store, ())?;
     assert_eq!(store.data().as_ref().unwrap(), "hello world");
 
@@ -254,7 +254,7 @@ fn attempt_to_leave_during_malloc() -> Result<()> {
     // happens if we try to leave the instance.
     let trap = linker
         .instantiate(&mut store, &component)?
-        .get_typed_func::<(), (), _>(&mut store, "run")?
+        .get_typed_func::<(), ()>(&mut store, "run")?
         .call(&mut store, ())
         .unwrap_err();
     assert!(
@@ -290,7 +290,7 @@ fn attempt_to_leave_during_malloc() -> Result<()> {
     // trap.
     let trap = linker
         .instantiate(&mut store, &component)?
-        .get_typed_func::<(&str,), (), _>(&mut store, "take-string")?
+        .get_typed_func::<(&str,), ()>(&mut store, "take-string")?
         .call(&mut store, ("x",))
         .unwrap_err();
     assert!(
@@ -347,7 +347,7 @@ fn attempt_to_reenter_during_host() -> Result<()> {
         },
     )?;
     let instance = linker.instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
     store.data_mut().func = Some(func);
     func.call(&mut store, ())?;
 
@@ -576,7 +576,7 @@ fn stack_and_heap_args_and_rets() -> Result<()> {
     )?;
     let instance = linker.instantiate(&mut store, &component)?;
     instance
-        .get_typed_func::<(), (), _>(&mut store, "run")?
+        .get_typed_func::<(), ()>(&mut store, "run")?
         .call(&mut store, ())?;
 
     // Next, test the dynamic API
@@ -723,7 +723,7 @@ fn bad_import_alignment() -> Result<()> {
 
     let trap = linker
         .instantiate(&mut store, &component)?
-        .get_typed_func::<(), (), _>(&mut store, "unaligned-retptr")?
+        .get_typed_func::<(), ()>(&mut store, "unaligned-retptr")?
         .call(&mut store, ())
         .unwrap_err();
     assert!(
@@ -733,7 +733,7 @@ fn bad_import_alignment() -> Result<()> {
     );
     let trap = linker
         .instantiate(&mut store, &component)?
-        .get_typed_func::<(), (), _>(&mut store, "unaligned-argptr")?
+        .get_typed_func::<(), ()>(&mut store, "unaligned-argptr")?
         .call(&mut store, ())
         .unwrap_err();
     assert!(
@@ -787,7 +787,7 @@ fn no_actual_wasm_code() -> Result<()> {
     )?;
 
     let instance = linker.instantiate(&mut store, &component)?;
-    let thunk = instance.get_typed_func::<(), (), _>(&mut store, "thunk")?;
+    let thunk = instance.get_typed_func::<(), ()>(&mut store, "thunk")?;
 
     assert_eq!(*store.data(), 0);
     thunk.call(&mut store, ())?;
diff --git a/tests/all/component_model/macros.rs b/tests/all/component_model/macros.rs
index 4ca5851dd..f6c83e592 100644
--- a/tests/all/component_model/macros.rs
+++ b/tests/all/component_model/macros.rs
@@ -27,7 +27,7 @@ fn record_derive() -> Result<()> {
 
     let input = Foo { a: -42, b: 73 };
     let output = instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")?
         .call_and_post_return(&mut store, (input,))?;
 
     assert_eq!((input,), output);
@@ -41,7 +41,7 @@ fn record_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: field count mismatch (too many)
@@ -56,7 +56,7 @@ fn record_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: field name mismatch
@@ -68,7 +68,7 @@ fn record_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: field type mismatch
@@ -80,7 +80,7 @@ fn record_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Happy path redux, with generics this time
@@ -105,7 +105,7 @@ fn record_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     let output = instance
-        .get_typed_func::<(Generic<i32, u32>,), (Generic<i32, u32>,), _>(&mut store, "echo")?
+        .get_typed_func::<(Generic<i32, u32>,), (Generic<i32, u32>,)>(&mut store, "echo")?
         .call_and_post_return(&mut store, (input,))?;
 
     assert_eq!((input,), output);
@@ -130,7 +130,7 @@ fn union_derive() -> Result<()> {
 
     let component = Component::new(&engine, make_echo_component("(union s32 u32 s32)", 8))?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")?;
 
     for &input in &[Foo::A(-42), Foo::B(73), Foo::C(314159265)] {
         let output = func.call_and_post_return(&mut store, (input,))?;
@@ -144,7 +144,7 @@ fn union_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: case count mismatch (too many)
@@ -156,11 +156,11 @@ fn union_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: case type mismatch
@@ -169,7 +169,7 @@ fn union_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Happy path redux, with generics this time
@@ -184,7 +184,7 @@ fn union_derive() -> Result<()> {
 
     let component = Component::new(&engine, make_echo_component("(union s32 u32 s32)", 8))?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Generic<i32, u32, i32>,), (Generic<i32, u32, i32>,), _>(
+    let func = instance.get_typed_func::<(Generic<i32, u32, i32>,), (Generic<i32, u32, i32>,)>(
         &mut store, "echo",
     )?;
 
@@ -225,7 +225,7 @@ fn variant_derive() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")?;
 
     for &input in &[Foo::A(-42), Foo::B(73), Foo::C] {
         let output = func.call_and_post_return(&mut store, (input,))?;
@@ -242,7 +242,7 @@ fn variant_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: case count mismatch (too many)
@@ -257,7 +257,7 @@ fn variant_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: case name mismatch
@@ -269,7 +269,7 @@ fn variant_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: case type mismatch
@@ -284,7 +284,7 @@ fn variant_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Happy path redux, with generics this time
@@ -307,7 +307,7 @@ fn variant_derive() -> Result<()> {
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
     let func = instance
-        .get_typed_func::<(Generic<i32, u32>,), (Generic<i32, u32>,), _>(&mut store, "echo")?;
+        .get_typed_func::<(Generic<i32, u32>,), (Generic<i32, u32>,)>(&mut store, "echo")?;
 
     for &input in &[Generic::<i32, u32>::A(-42), Generic::B(73), Generic::C] {
         let output = func.call_and_post_return(&mut store, (input,))?;
@@ -339,7 +339,7 @@ fn enum_derive() -> Result<()> {
         make_echo_component(r#"(enum "foo-bar-baz" "B" "C")"#, 4),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")?;
 
     for &input in &[Foo::A, Foo::B, Foo::C] {
         let output = func.call_and_post_return(&mut store, (input,))?;
@@ -356,7 +356,7 @@ fn enum_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: case count mismatch (too many)
@@ -368,7 +368,7 @@ fn enum_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: case name mismatch
@@ -377,7 +377,7 @@ fn enum_derive() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Happy path redux, with large enums (i.e. more than 2^8 cases)
@@ -401,7 +401,7 @@ fn enum_derive() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Many,), (Many,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Many,), (Many,)>(&mut store, "echo")?;
 
     for &input in &[Many::V0, Many::V1, Many::V254, Many::V255, Many::V256] {
         let output = func.call_and_post_return(&mut store, (input,))?;
@@ -434,7 +434,7 @@ fn flags() -> Result<()> {
 
     let component = Component::new(&engine, make_echo_component(r#"(flags)"#, 0))?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Flags0,), (Flags0,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Flags0,), (Flags0,)>(&mut store, "echo")?;
     let output = func.call_and_post_return(&mut store, (Flags0::default(),))?;
     assert_eq!(output, (Flags0::default(),));
 
@@ -462,7 +462,7 @@ fn flags() -> Result<()> {
         make_echo_component(r#"(flags "foo-bar-baz" "B" "C")"#, 4),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")?;
 
     for n in 0..8 {
         let mut input = Foo::default();
@@ -490,7 +490,7 @@ fn flags() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: flag count mismatch (too many)
@@ -502,7 +502,7 @@ fn flags() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Sad path: flag name mismatch
@@ -511,7 +511,7 @@ fn flags() -> Result<()> {
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
 
     assert!(instance
-        .get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
+        .get_typed_func::<(Foo,), (Foo,)>(&mut store, "echo")
         .is_err());
 
     // Happy path redux, with large flag count (exactly 8)
@@ -557,7 +557,7 @@ fn flags() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo8Exact,), (Foo8Exact,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo8Exact,), (Foo8Exact,)>(&mut store, "echo")?;
 
     for &input in &[
         Foo8Exact::F0,
@@ -606,7 +606,7 @@ fn flags() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo16,), (Foo16,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo16,), (Foo16,)>(&mut store, "echo")?;
 
     for &input in &[Foo16::F0, Foo16::F1, Foo16::F6, Foo16::F7, Foo16::F8] {
         let output = func.call_and_post_return(&mut store, (input,))?;
@@ -654,7 +654,7 @@ fn flags() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo16Exact,), (Foo16Exact,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo16Exact,), (Foo16Exact,)>(&mut store, "echo")?;
 
     for &input in &[
         Foo16Exact::F0,
@@ -693,7 +693,7 @@ fn flags() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo32,), (Foo32,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo32,), (Foo32,)>(&mut store, "echo")?;
 
     for &input in &[Foo32::F0, Foo32::F1, Foo32::F14, Foo32::F15, Foo32::F16] {
         let output = func.call_and_post_return(&mut store, (input,))?;
@@ -741,7 +741,7 @@ fn flags() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo32Exact,), (Foo32Exact,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo32Exact,), (Foo32Exact,)>(&mut store, "echo")?;
 
     for &input in &[
         Foo32Exact::F0,
@@ -780,7 +780,7 @@ fn flags() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo64,), (Foo64,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo64,), (Foo64,)>(&mut store, "echo")?;
 
     for &input in &[Foo64::F0, Foo64::F1, Foo64::F30, Foo64::F31, Foo64::F32] {
         let output = func.call_and_post_return(&mut store, (input,))?;
@@ -813,7 +813,7 @@ fn flags() -> Result<()> {
         ),
     )?;
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(Foo96,), (Foo96,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(Foo96,), (Foo96,)>(&mut store, "echo")?;
 
     for &input in &[Foo96::F0, Foo96::F1, Foo96::F62, Foo96::F63, Foo96::F64] {
         let output = func.call_and_post_return(&mut store, (input,))?;
diff --git a/tests/all/component_model/nested.rs b/tests/all/component_model/nested.rs
index 1ca932eca..473c6b751 100644
--- a/tests/all/component_model/nested.rs
+++ b/tests/all/component_model/nested.rs
@@ -165,7 +165,7 @@ fn thread_options_through_inner() -> Result<()> {
         .func_wrap("hostfn", |_, (param,): (u32,)| Ok((param.to_string(),)))?;
     let instance = linker.instantiate(&mut store, &component)?;
     let result = instance
-        .get_typed_func::<(u32,), (WasmStr,), _>(&mut store, "run")?
+        .get_typed_func::<(u32,), (WasmStr,)>(&mut store, "run")?
         .call(&mut store, (43,))?
         .0;
     assert_eq!(result.to_str(&store)?, "42");
diff --git a/tests/all/component_model/post_return.rs b/tests/all/component_model/post_return.rs
index 56bfa5166..d35be4337 100644
--- a/tests/all/component_model/post_return.rs
+++ b/tests/all/component_model/post_return.rs
@@ -24,8 +24,8 @@ fn invalid_api() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let thunk1 = instance.get_typed_func::<(), (), _>(&mut store, "thunk1")?;
-    let thunk2 = instance.get_typed_func::<(), (), _>(&mut store, "thunk2")?;
+    let thunk1 = instance.get_typed_func::<(), ()>(&mut store, "thunk1")?;
+    let thunk2 = instance.get_typed_func::<(), ()>(&mut store, "thunk2")?;
 
     // Ensure that we can't call `post_return` before doing anything
     let msg = "post_return can only be called after a function has previously been called";
@@ -130,7 +130,7 @@ fn invoke_post_return() -> Result<()> {
     )?;
 
     let instance = linker.instantiate(&mut store, &component)?;
-    let thunk = instance.get_typed_func::<(), (), _>(&mut store, "thunk")?;
+    let thunk = instance.get_typed_func::<(), ()>(&mut store, "thunk")?;
 
     assert!(!*store.data());
     thunk.call(&mut store, ())?;
@@ -196,10 +196,10 @@ fn post_return_all_types() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, false);
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let i32 = instance.get_typed_func::<(), (u32,), _>(&mut store, "i32")?;
-    let i64 = instance.get_typed_func::<(), (u64,), _>(&mut store, "i64")?;
-    let f32 = instance.get_typed_func::<(), (f32,), _>(&mut store, "f32")?;
-    let f64 = instance.get_typed_func::<(), (f64,), _>(&mut store, "f64")?;
+    let i32 = instance.get_typed_func::<(), (u32,)>(&mut store, "i32")?;
+    let i64 = instance.get_typed_func::<(), (u64,)>(&mut store, "i64")?;
+    let f32 = instance.get_typed_func::<(), (f32,)>(&mut store, "f32")?;
+    let f64 = instance.get_typed_func::<(), (f64,)>(&mut store, "f64")?;
 
     assert_eq!(i32.call(&mut store, ())?, (1,));
     i32.post_return(&mut store)?;
@@ -251,7 +251,7 @@ fn post_return_string() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, false);
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let get = instance.get_typed_func::<(), (WasmStr,), _>(&mut store, "get")?;
+    let get = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "get")?;
     let s = get.call(&mut store, ())?.0;
     assert_eq!(s.to_str(&store)?, "hello world");
     get.post_return(&mut store)?;
@@ -281,7 +281,7 @@ fn trap_in_post_return_poisons_instance() -> Result<()> {
     let component = Component::new(&engine, component)?;
     let mut store = Store::new(&engine, ());
     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
-    let f = instance.get_typed_func::<(), (), _>(&mut store, "f")?;
+    let f = instance.get_typed_func::<(), ()>(&mut store, "f")?;
     f.call(&mut store, ())?;
     let trap = f.post_return(&mut store).unwrap_err().downcast::<Trap>()?;
     assert_eq!(trap, Trap::UnreachableCodeReached);
diff --git a/tests/all/component_model/strings.rs b/tests/all/component_model/strings.rs
index 21a9ff283..9bd88da32 100644
--- a/tests/all/component_model/strings.rs
+++ b/tests/all/component_model/strings.rs
@@ -179,7 +179,7 @@ fn test_roundtrip(engine: &Engine, src: &str, dst: &str) -> Result<()> {
         },
     )?;
     let instance = linker.instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(String,), (String,), _>(&mut store, "echo")?;
+    let func = instance.get_typed_func::<(String,), (String,)>(&mut store, "echo")?;
 
     for string in STRINGS {
         println!("testing string {string:?}");
@@ -317,7 +317,7 @@ fn test_ptr_overflow(engine: &Engine, src: &str, dst: &str) -> Result<()> {
     let mut test_overflow = |size: u32| -> Result<()> {
         println!("src={src} dst={dst} size={size:#x}");
         let instance = Linker::new(engine).instantiate(&mut store, &component)?;
-        let func = instance.get_typed_func::<(u32,), (), _>(&mut store, "f")?;
+        let func = instance.get_typed_func::<(u32,), ()>(&mut store, "f")?;
         let trap = func
             .call(&mut store, (size,))
             .unwrap_err()
@@ -420,7 +420,7 @@ fn test_realloc_oob(engine: &Engine, src: &str, dst: &str) -> Result<()> {
     let mut store = Store::new(engine, ());
 
     let instance = Linker::new(engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(), (), _>(&mut store, "f")?;
+    let func = instance.get_typed_func::<(), ()>(&mut store, "f")?;
     let trap = func.call(&mut store, ()).unwrap_err().downcast::<Trap>()?;
     assert_eq!(trap, Trap::UnreachableCodeReached);
     Ok(())
@@ -570,7 +570,7 @@ fn test_raw_when_encoded(
     let mut store = Store::new(engine, ());
 
     let instance = Linker::new(engine).instantiate(&mut store, &component)?;
-    let func = instance.get_typed_func::<(&[u8], u32), (), _>(&mut store, "f")?;
+    let func = instance.get_typed_func::<(&[u8], u32), ()>(&mut store, "f")?;
     match func.call(&mut store, (bytes, len)) {
         Ok(_) => Ok(None),
         Err(e) => Ok(Some(e)),
diff --git a/winch/filetests/src/lib.rs b/winch/filetests/src/lib.rs
index 225445a2a..4400bf065 100644
--- a/winch/filetests/src/lib.rs
+++ b/winch/filetests/src/lib.rs
@@ -112,9 +112,9 @@ mod test {
 
         let binding = body_inputs
             .into_iter()
-            .flat_map(|func| compile(&*isa, module, types, func))
+            .map(|func| compile(&*isa, module, types, func).join("\n"))
             .collect::<Vec<String>>()
-            .join("\n");
+            .join("\n\n");
         let actual = binding.as_str();
 
         if std::env::var("WINCH_TEST_BLESS").unwrap_or_default() == "1" {
@@ -151,7 +151,7 @@ mod test {
     ) -> Vec<String> {
         let index = module.func_index(f.0);
         let sig = types
-            .func_type_at(index.as_u32())
+            .function_at(index.as_u32())
             .expect(&format!("function type at index {:?}", index.as_u32()));
         let FunctionBodyData { body, validator } = f.1;
         let validator = validator.into_validator(Default::default());