Repository: bytecodealliance/wasmtime
Pull request #5721 (2023-02-06 20:16:55)

Keep reachable jump tables
Instead of identifying unused branch tables by looking for unused blocks inside of them, track used branch tables while traversing reachable blocks. This introduces an extra allocation of an `EntitySet` to track the used jump tables, but as those are few and this function runs once per `ir::Function`, the allocation seems reasonable.

<!--

Please ensure that the following steps are all taken care of before submitting
the PR.

- [ ] This has been discussed in issue #..., or if not, please tell us why
  here.
- [ ] A short description of what this does, why it is needed; if the
  description becomes long, the matter should probably be discussed in an issue
  first.
- [ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
  If you don't know who could review this, please indicate so. The list of
  suggested reviewers on the right can help you.

Please ensure all communication adheres to the [code of
conduct](https://github.com/bytecodealliance/wasmtime/blob/master/CODE_OF_CONDUCT.md).
-->


jameysharp: Since we kind of jointly authored this during a video call, I don't want to be the reviewer on it. :laughing:

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/cranelift/codegen/src/unreachable_code.rs b/cranelift/codegen/src/unreachable_code.rs
index 569b2f2a6..dfb4be5a4 100644
--- a/cranelift/codegen/src/unreachable_code.rs
+++ b/cranelift/codegen/src/unreachable_code.rs
@@ -1,5 +1,7 @@
 //! Unreachable code elimination.
 
+use cranelift_entity::EntitySet;
+
 use crate::cursor::{Cursor, FuncCursor};
 use crate::dominator_tree::DominatorTree;
 use crate::flowgraph::ControlFlowGraph;
@@ -19,8 +21,13 @@ pub fn eliminate_unreachable_code(
 ) {
     let _tt = timing::unreachable_code();
     let mut pos = FuncCursor::new(func);
+    let mut used_tables = EntitySet::with_capacity(pos.func.jump_tables.len());
     while let Some(block) = pos.next_block() {
         if domtree.is_reachable(block) {
+            let inst = pos.func.layout.last_inst(block).unwrap();
+            if let ir::InstructionData::BranchTable { table, .. } = pos.func.dfg.insts[inst] {
+                used_tables.insert(table);
+            }
             continue;
         }
 
@@ -43,15 +50,8 @@ pub fn eliminate_unreachable_code(
         pos.func.layout.remove_block(block);
     }
 
-    // Remove all jumptable block-list contents that refer to unreachable
-    // blocks; the jumptable itself must have been unused (or used only in an
-    // unreachable block) if so. Note that we are not necessarily removing *all*
-    // unused jumptables, because that would require computing their
-    // reachability as well; we are just removing enough to clean up references
-    // to deleted blocks.
-    for jt_data in func.jump_tables.values_mut() {
-        let invalid_ref = jt_data.iter().any(|block| !domtree.is_reachable(*block));
-        if invalid_ref {
+    for (table, jt_data) in func.jump_tables.iter_mut() {
+        if !used_tables.contains(table) {
             jt_data.clear();
         }
     }
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());