Repository: bytecodealliance/wasmtime
Pull request #5275 (2022-11-15 23:18:15)

Remove explicit `S` type parameters
This commit removes the explicit `S` type parameter on `Func::typed` and `Instance::get_typed_func`. Historical versions of Rust required that this be a type parameter but recent rustcs support a mixture of explicit type parameters and `impl Trait`. This removes, at callsites, a superfluous `, _` argument which otherwise never needs specification.

<!--

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).
-->


github-actions[bot]: #### Subscribe to Label Action

cc @fitzgen, @peterhuene

<details>
This issue or pull request has been labeled: "fuzzing", "wasmtime:api", "wasmtime:docs"

Thus the following users have been cc'd because of the following labels:

* fitzgen: fuzzing
* peterhuene: wasmtime:api

To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.

[Learn more.](https://github.com/bytecodealliance/subscribe-to-label-action)
</details>

Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 235f312b3..605695b9c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -225,3 +225,7 @@ harness = false
 [[bench]]
 name = "call"
 harness = false
+
+[[bench]]
+name = "wasi"
+harness = false
diff --git a/benches/call.rs b/benches/call.rs
index f1e5790b5..9ec51d35d 100644
--- a/benches/call.rs
+++ b/benches/call.rs
@@ -117,7 +117,7 @@ fn bench_host_to_wasm<Params, Results>(
     // below.
     c.bench_function(&format!("host-to-wasm - typed - {}", name), |b| {
         let typed = instance
-            .get_typed_func::<Params, Results, _>(&mut *store, name)
+            .get_typed_func::<Params, Results>(&mut *store, name)
             .unwrap();
         b.iter(|| {
             let results = if is_async.use_async() {
@@ -370,7 +370,7 @@ fn wasm_to_host(c: &mut Criterion) {
     ) {
         group.bench_function(&format!("wasm-to-host - {} - nop", desc), |b| {
             let run = instance
-                .get_typed_func::<u64, (), _>(&mut *store, "run-nop")
+                .get_typed_func::<u64, ()>(&mut *store, "run-nop")
                 .unwrap();
             b.iter_custom(|iters| {
                 let start = Instant::now();
@@ -386,7 +386,7 @@ fn wasm_to_host(c: &mut Criterion) {
             &format!("wasm-to-host - {} - nop-params-and-results", desc),
             |b| {
                 let run = instance
-                    .get_typed_func::<u64, (), _>(&mut *store, "run-nop-params-and-results")
+                    .get_typed_func::<u64, ()>(&mut *store, "run-nop-params-and-results")
                     .unwrap();
                 b.iter_custom(|iters| {
                     let start = Instant::now();
diff --git a/benches/thread_eager_init.rs b/benches/thread_eager_init.rs
index 9f6e4c5b9..8572a335c 100644
--- a/benches/thread_eager_init.rs
+++ b/benches/thread_eager_init.rs
@@ -4,7 +4,7 @@ use std::time::{Duration, Instant};
 use wasmtime::*;
 
 fn measure_execution_time(c: &mut Criterion) {
-    // Baseline performance: a single measurment covers both initializing
+    // Baseline performance: a single measurement covers both initializing
     // thread local resources and executing the first call.
     //
     // The other two bench functions should sum to this duration.
@@ -55,7 +55,7 @@ fn duration_of_call(engine: &Engine, module: &Module) -> Duration {
     let mut store = Store::new(engine, ());
     let inst = Instance::new(&mut store, module, &[]).expect("instantiate");
     let f = inst.get_func(&mut store, "f").expect("get f");
-    let f = f.typed::<(), (), _>(&store).expect("type f");
+    let f = f.typed::<(), ()>(&store).expect("type f");
 
     let call = Instant::now();
     f.call(&mut store, ()).expect("call f");
diff --git a/benches/trap.rs b/benches/trap.rs
index 933c77e16..979f30676 100644
--- a/benches/trap.rs
+++ b/benches/trap.rs
@@ -38,9 +38,8 @@ fn bench_multi_threaded_traps(c: &mut Criterion) {
                                 move || {
                                     let mut store = Store::new(&engine, ());
                                     let instance = Instance::new(&mut store, &module, &[]).unwrap();
-                                    let f = instance
-                                        .get_typed_func::<(), (), _>(&mut store, "")
-                                        .unwrap();
+                                    let f =
+                                        instance.get_typed_func::<(), ()>(&mut store, "").unwrap();
 
                                     // Notify the parent thread that we are
                                     // doing background work now.
@@ -67,9 +66,7 @@ fn bench_multi_threaded_traps(c: &mut Criterion) {
 
                     let mut store = Store::new(&engine, ());
                     let instance = Instance::new(&mut store, &module, &[]).unwrap();
-                    let f = instance
-                        .get_typed_func::<(), (), _>(&mut store, "")
-                        .unwrap();
+                    let f = instance.get_typed_func::<(), ()>(&mut store, "").unwrap();
 
                     // Measure how long it takes to do `iters` worth of traps
                     // while there is a bunch of background work going on.
@@ -111,9 +108,7 @@ fn bench_many_modules_registered_traps(c: &mut Criterion) {
                 b.iter_custom(|iters| {
                     let mut store = Store::new(&engine, ());
                     let instance = Instance::new(&mut store, modules.last().unwrap(), &[]).unwrap();
-                    let f = instance
-                        .get_typed_func::<(), (), _>(&mut store, "")
-                        .unwrap();
+                    let f = instance.get_typed_func::<(), ()>(&mut store, "").unwrap();
 
                     let start = std::time::Instant::now();
                     for _ in 0..iters {
@@ -143,9 +138,7 @@ fn bench_many_stack_frames_traps(c: &mut Criterion) {
                 b.iter_custom(|iters| {
                     let mut store = Store::new(&engine, ());
                     let instance = Instance::new(&mut store, &module, &[]).unwrap();
-                    let f = instance
-                        .get_typed_func::<(), (), _>(&mut store, "")
-                        .unwrap();
+                    let f = instance.get_typed_func::<(), ()>(&mut store, "").unwrap();
 
                     let start = std::time::Instant::now();
                     for _ in 0..iters {
@@ -204,7 +197,7 @@ fn bench_host_wasm_frames_traps(c: &mut Criterion) {
                     );
                     let instance = Instance::new(&mut store, &module, &[host_func.into()]).unwrap();
                     let f = instance
-                        .get_typed_func::<(i32,), (), _>(&mut store, "f")
+                        .get_typed_func::<(i32,), ()>(&mut store, "f")
                         .unwrap();
 
                     let start = std::time::Instant::now();
diff --git a/benches/wasi.rs b/benches/wasi.rs
new file mode 100644
index 000000000..3b8f28863
--- /dev/null
+++ b/benches/wasi.rs
@@ -0,0 +1,71 @@
+//! Measure some common WASI call scenarios.
+
+use criterion::{criterion_group, criterion_main, Criterion};
+use std::time::Instant;
+use wasmtime::{Engine, Linker, Module, Store, TypedFunc};
+use wasmtime_wasi::{sync::WasiCtxBuilder, WasiCtx};
+
+criterion_group!(benches, bench_wasi);
+criterion_main!(benches);
+
+fn bench_wasi(c: &mut Criterion) {
+    // Benchmark each `*.wat` file in the `wasi` directory.
+    for file in std::fs::read_dir("benches/wasi").unwrap() {
+        let path = file.unwrap().path();
+        if path.extension().map(|e| e == "wat").unwrap_or(false) {
+            let wat = std::fs::read(&path).unwrap();
+            let (mut store, run_fn) = instantiate(&wat);
+            let bench_name = format!("wasi/{}", path.file_name().unwrap().to_string_lossy());
+            // To avoid overhead, the module itself must iterate the expected
+            // number of times in a specially-crafted `run` function (see
+            // `instantiate` for details).
+            c.bench_function(&bench_name, move |b| {
+                b.iter_custom(|iters| {
+                    let start = Instant::now();
+                    let result = run_fn.call(&mut store, iters).unwrap();
+                    assert_eq!(iters, result);
+                    start.elapsed()
+                })
+            });
+        }
+    }
+}
+
+/// Compile and instantiate the Wasm module, returning the exported `run`
+/// function. This function expects `run` to:
+/// - have a single `u64` parameter indicating the number of loop iterations to
+///   execute
+/// - execute the body of the function for that number of loop iterations
+/// - return a single `u64` indicating how many loop iterations were executed
+///   (to double-check)
+fn instantiate(wat: &[u8]) -> (Store<WasiCtx>, TypedFunc<u64, u64>) {
+    let engine = Engine::default();
+    let wasi = wasi_context();
+    let mut store = Store::new(&engine, wasi);
+    let module = Module::new(&engine, wat).unwrap();
+    let mut linker = Linker::new(&engine);
+    wasmtime_wasi::add_to_linker(&mut linker, |cx| cx).unwrap();
+    let instance = linker.instantiate(&mut store, &module).unwrap();
+    let run = instance.get_typed_func(&mut store, "run").unwrap();
+    (store, run)
+}
+
+/// Build a WASI context with some actual data to retrieve.
+fn wasi_context() -> WasiCtx {
+    let wasi = WasiCtxBuilder::new();
+    wasi.envs(&[
+        ("a".to_string(), "b".to_string()),
+        ("b".to_string(), "c".to_string()),
+        ("c".to_string(), "d".to_string()),
+    ])
+    .unwrap()
+    .args(&[
+        "exe".to_string(),
+        "--flag1".to_string(),
+        "--flag2".to_string(),
+        "--flag3".to_string(),
+        "--flag4".to_string(),
+    ])
+    .unwrap()
+    .build()
+}
diff --git a/benches/wasi/get-current-time.wat b/benches/wasi/get-current-time.wat
new file mode 100644
index 000000000..8ac6ceb07
--- /dev/null
+++ b/benches/wasi/get-current-time.wat
@@ -0,0 +1,22 @@
+(module
+    (import "wasi_snapshot_preview1" "clock_time_get"
+        (func $__wasi_clock_time_get (param i32 i64 i32) (result i32)))
+    (func (export "run") (param $iters i64) (result i64)
+        (local $i i64)
+        (local.set $i (i64.const 0))
+        (loop $cont
+            ;; Retrieve the current time with the following parameters:
+            ;; - $clockid: here we use the enum value for $realtime
+            ;; - $precision: the maximum lag, which we set to 0 here
+            ;; - the address at which to write the u64 $timestamp
+            ;; Returns an error code.
+            (call $__wasi_clock_time_get (i32.const 1) (i64.const 0) (i32.const 0))
+            (drop)
+            ;; Continue looping until $i reaches $iters.
+            (local.set $i (i64.add (local.get $i) (i64.const 1)))
+            (br_if $cont (i64.lt_u (local.get $i) (local.get $iters)))
+        )
+        (local.get $i)
+    )
+    (memory (export "memory") 1)
+)
diff --git a/benches/wasi/read-arguments.wat b/benches/wasi/read-arguments.wat
new file mode 100644
index 000000000..c6f1d4a33
--- /dev/null
+++ b/benches/wasi/read-arguments.wat
@@ -0,0 +1,42 @@
+(module
+    (import "wasi_snapshot_preview1" "args_get"
+        (func $__wasi_args_get (param i32 i32) (result i32)))
+    (import "wasi_snapshot_preview1" "args_sizes_get"
+        (func $__wasi_args_sizes_get (param i32 i32) (result i32)))
+    (func (export "run") (param $iters i64) (result i64)
+        (local $i i64)
+        (local.set $i (i64.const 0))
+        (loop $cont
+            ;; Read the current argument list by:
+            ;;  1) retrieving the argument sizes and then
+            ;;  2) retrieving the argument data itself.
+
+            ;; Retrieve the sizes of the arguments with parameters:
+            ;; - the address at which to write the number of arguments
+            ;; - the address at which to write the size of the argument buffer
+            ;; Returns an error code.
+            (call $__wasi_args_sizes_get (i32.const 0) (i32.const 4))
+            (drop)
+
+            ;; Read the arguments with parameters:
+            ;; - the address at which to write the array of argument pointers
+            ;;   (i.e., one pointer per argument); here we overwrite the size
+            ;;   written at address 0
+            ;; - the address at which to write the buffer of argument strings
+            ;;   (pointed to by the items written to the first address); we
+            ;;   calculate where to start the buffer based on the size of the
+            ;;   pointer list (i.e., number of arguments * 4 bytes per pointer)
+            ;; Returns an error code.
+            (call $__wasi_args_get
+                (i32.const 0)
+                (i32.mul (i32.load (i32.const 0)) (i32.const 4)))
+            (drop)
+
+            ;; Continue looping until $i reaches $iters.
+            (local.set $i (i64.add (local.get $i) (i64.const 1)))
+            (br_if $cont (i64.lt_u (local.get $i) (local.get $iters)))
+        )
+        (local.get $i)
+    )
+    (memory (export "memory") 1)
+)
diff --git a/benches/wasi/read-environment.wat b/benches/wasi/read-environment.wat
new file mode 100644
index 000000000..50f50b227
--- /dev/null
+++ b/benches/wasi/read-environment.wat
@@ -0,0 +1,45 @@
+(module
+    (import "wasi_snapshot_preview1" "environ_get"
+        (func $__wasi_environ_get (param i32 i32) (result i32)))
+    (import "wasi_snapshot_preview1" "environ_sizes_get"
+        (func $__wasi_environ_sizes_get (param i32 i32) (result i32)))
+    (func (export "run") (param $iters i64) (result i64)
+        (local $i i64)
+        (local.set $i (i64.const 0))
+        (loop $cont
+            ;; Read the current environment key-value pairs by:
+            ;;  1) retrieving the environment sizes and then
+            ;;  2) retrieving the environment data itself.
+
+            ;; Retrieve the sizes of the environment with parameters:
+            ;; - the address at which to write the number of environment
+            ;;   variables
+            ;; - the address at which to write the size of the environment
+            ;;   buffer
+            ;; Returns an error code.
+            (call $__wasi_environ_sizes_get (i32.const 0) (i32.const 4))
+            (drop)
+
+            ;; Read the environment with parameters:
+            ;; - the address at which to write the array of environment pointers
+            ;;   (i.e., one pointer per key-value pair); here we overwrite
+            ;;   the size written at address 0
+            ;; - the address at which to write the buffer of key-value pairs
+            ;;   (pointed to by the items written to the first address); we
+            ;;   calculate where to start the buffer based on the size of the
+            ;;   pointer list (i.e., number of key-value pairs * 4 bytes per
+            ;;   pointer)
+            ;; Returns an error code.
+            (call $__wasi_environ_get
+                (i32.const 0)
+                (i32.mul (i32.load (i32.const 0)) (i32.const 4)))
+            (drop)
+
+            ;; Continue looping until $i reaches $iters.
+            (local.set $i (i64.add (local.get $i) (i64.const 1)))
+            (br_if $cont (i64.lt_u (local.get $i) (local.get $iters)))
+        )
+        (local.get $i)
+    )
+    (memory (export "memory") 1)
+)
diff --git a/crates/fuzzing/src/oracles/stacks.rs b/crates/fuzzing/src/oracles/stacks.rs
index 3216ed10c..8705b5887 100644
--- a/crates/fuzzing/src/oracles/stacks.rs
+++ b/crates/fuzzing/src/oracles/stacks.rs
@@ -53,7 +53,7 @@ pub fn check_stacks(stacks: Stacks) -> usize {
         .expect("should instantiate okay");
 
     let run = instance
-        .get_typed_func::<(u32,), (), _>(&mut store, "run")
+        .get_typed_func::<(u32,), ()>(&mut store, "run")
         .expect("should export `run` function");
 
     let mut max_stack_depth = 0;
@@ -62,7 +62,7 @@ pub fn check_stacks(stacks: Stacks) -> usize {
         if let Err(trap) = run.call(&mut store, (input.into(),)) {
             log::debug!("trap: {:?}", trap);
             let get_stack = instance
-                .get_typed_func::<(), (u32, u32), _>(&mut store, "get_stack")
+                .get_typed_func::<(), (u32, u32)>(&mut store, "get_stack")
                 .expect("should export `get_stack` function as expected");
 
             let (ptr, len) = get_stack
diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs
index 587fd8e56..ecc3f22b4 100644
--- a/crates/wasmtime/src/func.rs
+++ b/crates/wasmtime/src/func.rs
@@ -95,7 +95,7 @@ use wasmtime_runtime::{
 /// // ... or we can make a static assertion about its signature and call it.
 /// // Our first call here can fail if the signatures don't match, and then the
 /// // second call can fail if the function traps (like the `match` above).
-/// let foo = foo.typed::<(), (), _>(&store)?;
+/// let foo = foo.typed::<(), ()>(&store)?;
 /// foo.call(&mut store, ())?;
 /// # Ok(())
 /// # }
@@ -130,7 +130,7 @@ use wasmtime_runtime::{
 ///     "#,
 /// )?;
 /// let instance = Instance::new(&mut store, &module, &[add.into()])?;
-/// let call_add_twice = instance.get_typed_func::<(), i32, _>(&mut store, "call_add_twice")?;
+/// let call_add_twice = instance.get_typed_func::<(), i32>(&mut store, "call_add_twice")?;
 ///
 /// assert_eq!(call_add_twice.call(&mut store, ())?, 10);
 /// # Ok(())
@@ -603,7 +603,7 @@ impl Func {
     ///     "#,
     /// )?;
     /// let instance = Instance::new(&mut store, &module, &[add.into()])?;
-    /// let foo = instance.get_typed_func::<(i32, i32), i32, _>(&mut store, "foo")?;
+    /// let foo = instance.get_typed_func::<(i32, i32), i32>(&mut store, "foo")?;
     /// assert_eq!(foo.call(&mut store, (1, 2))?, 3);
     /// # Ok(())
     /// # }
@@ -634,7 +634,7 @@ impl Func {
     ///     "#,
     /// )?;
     /// let instance = Instance::new(&mut store, &module, &[add.into()])?;
-    /// let foo = instance.get_typed_func::<(i32, i32), i32, _>(&mut store, "foo")?;
+    /// let foo = instance.get_typed_func::<(i32, i32), i32>(&mut store, "foo")?;
     /// assert_eq!(foo.call(&mut store, (1, 2))?, 3);
     /// assert!(foo.call(&mut store, (i32::max_value(), 1)).is_err());
     /// # Ok(())
@@ -672,7 +672,7 @@ impl Func {
     ///     "#,
     /// )?;
     /// let instance = Instance::new(&mut store, &module, &[debug.into()])?;
-    /// let foo = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
+    /// let foo = instance.get_typed_func::<(), ()>(&mut store, "foo")?;
     /// foo.call(&mut store, ())?;
     /// # Ok(())
     /// # }
@@ -720,7 +720,7 @@ impl Func {
     ///     "#,
     /// )?;
     /// let instance = Instance::new(&mut store, &module, &[log_str.into()])?;
-    /// let foo = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
+    /// let foo = instance.get_typed_func::<(), ()>(&mut store, "foo")?;
     /// foo.call(&mut store, ())?;
     /// # Ok(())
     /// # }
@@ -1178,10 +1178,6 @@ impl Func {
     /// function. This behaves the same way as `Params`, but just for the
     /// results of the function.
     ///
-    /// The `S` type parameter represents the method of passing in the store
-    /// context, and can typically be specified as simply `_` when calling this
-    /// function.
-    ///
     /// Translation between Rust types and WebAssembly types looks like:
     ///
     /// | WebAssembly | Rust                |
@@ -1232,7 +1228,7 @@ impl Func {
     /// // Note that this call can fail due to the typecheck not passing, but
     /// // in our case we statically know the module so we know this should
     /// // pass.
-    /// let typed = foo.typed::<(), (), _>(&store)?;
+    /// let typed = foo.typed::<(), ()>(&store)?;
     ///
     /// // Note that this can fail if the wasm traps at runtime.
     /// typed.call(&mut store, ())?;
@@ -1245,7 +1241,7 @@ impl Func {
     /// ```
     /// # use wasmtime::*;
     /// # fn foo(add: &Func, mut store: Store<()>) -> anyhow::Result<()> {
-    /// let typed = add.typed::<(i32, i64), f32, _>(&store)?;
+    /// let typed = add.typed::<(i32, i64), f32>(&store)?;
     /// assert_eq!(typed.call(&mut store, (1, 2))?, 3.0);
     /// # Ok(())
     /// # }
@@ -1256,18 +1252,20 @@ impl Func {
     /// ```
     /// # use wasmtime::*;
     /// # fn foo(add_with_overflow: &Func, mut store: Store<()>) -> anyhow::Result<()> {
-    /// let typed = add_with_overflow.typed::<(u32, u32), (u32, i32), _>(&store)?;
+    /// let typed = add_with_overflow.typed::<(u32, u32), (u32, i32)>(&store)?;
     /// let (result, overflow) = typed.call(&mut store, (u32::max_value(), 2))?;
     /// assert_eq!(result, 1);
     /// assert_eq!(overflow, 1);
     /// # Ok(())
     /// # }
     /// ```
-    pub fn typed<Params, Results, S>(&self, store: S) -> Result<TypedFunc<Params, Results>>
+    pub fn typed<Params, Results>(
+        &self,
+        store: impl AsContext,
+    ) -> Result<TypedFunc<Params, Results>>
     where
         Params: WasmParams,
         Results: WasmResults,
-        S: AsContext,
     {
         // Type-check that the params/results are all valid
         let ty = self.ty(store);
diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs
index cb7897ad3..970fb030a 100644
--- a/crates/wasmtime/src/instance.rs
+++ b/crates/wasmtime/src/instance.rs
@@ -457,21 +457,20 @@ 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: crate::WasmParams,
         Results: crate::WasmResults,
-        S: AsContextMut,
     {
         let f = self
             .get_export(store.as_context_mut(), name)
             .and_then(|f| f.into_func())
             .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/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs
index 1f0d0a9e0..a11bdd940 100644
--- a/crates/wasmtime/src/lib.rs
+++ b/crates/wasmtime/src/lib.rs
@@ -57,7 +57,7 @@
 //!     // afterwards we can fetch exports by name, as well as asserting the
 //!     // type signature of the function with `get_typed_func`.
 //!     let instance = Instance::new(&mut store, &module, &[host_hello.into()])?;
-//!     let hello = instance.get_typed_func::<(), (), _>(&mut store, "hello")?;
+//!     let hello = instance.get_typed_func::<(), ()>(&mut store, "hello")?;
 //!
 //!     // And finally we can call the wasm!
 //!     hello.call(&mut store, ())?;
@@ -168,7 +168,7 @@
 //!     // resolve the imports of the module using name-based resolution.
 //!     let mut store = Store::new(&engine, 0);
 //!     let instance = linker.instantiate(&mut store, &module)?;
-//!     let hello = instance.get_typed_func::<(), (), _>(&mut store, "hello")?;
+//!     let hello = instance.get_typed_func::<(), ()>(&mut store, "hello")?;
 //!     hello.call(&mut store, ())?;
 //!
 //!     Ok(())
@@ -373,7 +373,7 @@
 //!     "#,
 //! )?;
 //! let instance = Instance::new(&mut store, &module, &[log_str.into()])?;
-//! let foo = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
+//! let foo = instance.get_typed_func::<(), ()>(&mut store, "foo")?;
 //! foo.call(&mut store, ())?;
 //! # Ok(())
 //! # }
diff --git a/crates/wasmtime/src/linker.rs b/crates/wasmtime/src/linker.rs
index ba7890898..c1891ff80 100644
--- a/crates/wasmtime/src/linker.rs
+++ b/crates/wasmtime/src/linker.rs
@@ -643,7 +643,7 @@ impl<T> Linker<T> {
     /// let module = Module::new(&engine, wat)?;
     /// linker.module(&mut store, "commander", &module)?;
     /// let run = linker.get_default(&mut store, "")?
-    ///     .typed::<(), (), _>(&store)?
+    ///     .typed::<(), ()>(&store)?
     ///     .clone();
     /// run.call(&mut store, ())?;
     /// run.call(&mut store, ())?;
@@ -664,7 +664,7 @@ impl<T> Linker<T> {
     /// let module = Module::new(&engine, wat)?;
     /// linker.module(&mut store, "", &module)?;
     /// let run = linker.get(&mut store, "", "run").unwrap().into_func().unwrap();
-    /// let count = run.typed::<(), i32, _>(&store)?.call(&mut store, ())?;
+    /// let count = run.typed::<(), i32>(&store)?.call(&mut store, ())?;
     /// assert_eq!(count, 0, "a Command should get a fresh instance on each invocation");
     ///
     /// # Ok(())
@@ -727,7 +727,7 @@ impl<T> Linker<T> {
 
                 if let Some(export) = instance.get_export(&mut store, "_initialize") {
                     if let Extern::Func(func) = export {
-                        func.typed::<(), (), _>(&store)
+                        func.typed::<(), ()>(&store)
                             .and_then(|f| f.call(&mut store, ()).map_err(Into::into))
                             .context("calling the Reactor initialization function")?;
                     }
@@ -793,7 +793,7 @@ impl<T> Linker<T> {
                 if let Some(export) = instance.get_export(&mut store, "_initialize") {
                     if let Extern::Func(func) = export {
                         let func = func
-                            .typed::<(), (), _>(&store)
+                            .typed::<(), ()>(&store)
                             .context("loading the Reactor initialization function")?;
                         func.call_async(&mut store, ())
                             .await
diff --git a/crates/wasmtime/src/trap.rs b/crates/wasmtime/src/trap.rs
index 710b3fdd3..7b2631e9b 100644
--- a/crates/wasmtime/src/trap.rs
+++ b/crates/wasmtime/src/trap.rs
@@ -54,12 +54,12 @@ use wasmtime_jit::{demangle_function_name, demangle_function_name_or_index};
 /// let mut store = Store::new(&engine, ());
 /// let instance = Instance::new(&mut store, &module, &[])?;
 ///
-/// let trap = instance.get_typed_func::<(), (), _>(&mut store, "trap")?;
+/// let trap = instance.get_typed_func::<(), ()>(&mut store, "trap")?;
 /// let error = trap.call(&mut store, ()).unwrap_err();
 /// assert_eq!(*error.downcast_ref::<Trap>().unwrap(), Trap::UnreachableCodeReached);
 /// assert!(error.root_cause().is::<Trap>());
 ///
-/// let overflow = instance.get_typed_func::<(), (), _>(&mut store, "overflow")?;
+/// let overflow = instance.get_typed_func::<(), ()>(&mut store, "overflow")?;
 /// let error = overflow.call(&mut store, ()).unwrap_err();
 /// assert_eq!(*error.downcast_ref::<Trap>().unwrap(), Trap::StackOverflow);
 /// # Ok(())
@@ -266,7 +266,7 @@ impl std::error::Error for Trap {}
 /// )?;
 /// let mut store = Store::new(&engine, ());
 /// let instance = Instance::new(&mut store, &module, &[])?;
-/// let func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+/// let func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 /// let error = func.call(&mut store, ()).unwrap_err();
 /// let bt = error.downcast_ref::<WasmBacktrace>().unwrap();
 /// let frames = bt.frames();
diff --git a/docs/lang-rust.md b/docs/lang-rust.md
index 5a4a3747e..cc5d57248 100644
--- a/docs/lang-rust.md
+++ b/docs/lang-rust.md
@@ -86,7 +86,7 @@ fn main() -> Result<(), Box<dyn Error>> {
     // There's a few ways we can call the `answer` `Func` value. The easiest
     // is to statically assert its signature with `typed` (in this case
     // asserting it takes no arguments and returns one i32) and then call it.
-    let answer = answer.typed::<(), i32, _>(&store)?;
+    let answer = answer.typed::<(), i32>(&store)?;
 
     // And finally we can call our function! Note that the error propagation
     // with `?` is done to handle the case where the wasm function traps.
@@ -184,7 +184,7 @@ fn main() -> Result<(), Box<dyn Error>> {
     let instance = linker.instantiate(&mut store, &module)?;
 
     // Like before, we can get the run function and execute it.
-    let run = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
     run.call(&mut store, ())?;
 
     // We can also inspect what integers were logged:
diff --git a/docs/wasm-wat.md b/docs/wasm-wat.md
index c08fc49e7..634d35730 100644
--- a/docs/wasm-wat.md
+++ b/docs/wasm-wat.md
@@ -47,7 +47,7 @@ let wat = r#"
 "#;
 let module = Module::new(store.engine(), wat)?;
 let instance = Instance::new(&mut store, &module, &[])?;
-let add = instance.get_typed_func::<(i32, i32), i32, _>(&mut store, "add")?;
+let add = instance.get_typed_func::<(i32, i32), i32>(&mut store, "add")?;
 println!("1 + 2 = {}", add.call(&mut store, (1, 2))?);
 # Ok(())
 # }
diff --git a/examples/epochs.rs b/examples/epochs.rs
index fd19fd28d..47d72d7b3 100644
--- a/examples/epochs.rs
+++ b/examples/epochs.rs
@@ -36,7 +36,7 @@ fn main() -> Result<(), Error> {
 
     // Invoke `fibonacci` with a large argument such that a normal
     // invocation would take many seconds to complete.
-    let fibonacci = instance.get_typed_func::<i32, i32, _>(&mut store, "fibonacci")?;
+    let fibonacci = instance.get_typed_func::<i32, i32>(&mut store, "fibonacci")?;
     match fibonacci.call(&mut store, 100) {
         Ok(_) => panic!("Somehow we computed recursive fib(100) in less than a second!"),
         Err(_) => {
diff --git a/examples/externref.rs b/examples/externref.rs
index 794e5fbb7..67c91d8af 100644
--- a/examples/externref.rs
+++ b/examples/externref.rs
@@ -44,7 +44,7 @@ fn main() -> Result<()> {
 
     println!("Calling `externref` func...");
     let func =
-        instance.get_typed_func::<Option<ExternRef>, Option<ExternRef>, _>(&mut store, "func")?;
+        instance.get_typed_func::<Option<ExternRef>, Option<ExternRef>>(&mut store, "func")?;
     let ret = func.call(&mut store, Some(externref.clone()))?;
     assert!(ret.is_some());
     assert!(ret.unwrap().ptr_eq(&externref));
diff --git a/examples/fib-debug/main.rs b/examples/fib-debug/main.rs
index 66216081a..b9e51f229 100644
--- a/examples/fib-debug/main.rs
+++ b/examples/fib-debug/main.rs
@@ -21,7 +21,7 @@ fn main() -> Result<()> {
     let instance = Instance::new(&mut store, &module, &[])?;
 
     // Invoke `fib` export
-    let fib = instance.get_typed_func::<i32, i32, _>(&mut store, "fib")?;
+    let fib = instance.get_typed_func::<i32, i32>(&mut store, "fib")?;
     println!("fib(6) = {}", fib.call(&mut store, 6)?);
     Ok(())
 }
diff --git a/examples/fuel.rs b/examples/fuel.rs
index acca9f2d9..e6f4c74ec 100644
--- a/examples/fuel.rs
+++ b/examples/fuel.rs
@@ -15,7 +15,7 @@ fn main() -> Result<()> {
     let instance = Instance::new(&mut store, &module, &[])?;
 
     // Invoke `fibonacci` export with higher and higher numbers until we exhaust our fuel.
-    let fibonacci = instance.get_typed_func::<i32, i32, _>(&mut store, "fibonacci")?;
+    let fibonacci = instance.get_typed_func::<i32, i32>(&mut store, "fibonacci")?;
     for n in 1.. {
         let fuel_before = store.fuel_consumed().unwrap();
         let output = match fibonacci.call(&mut store, n) {
diff --git a/examples/gcd.rs b/examples/gcd.rs
index a748c6d82..176ee656e 100644
--- a/examples/gcd.rs
+++ b/examples/gcd.rs
@@ -15,7 +15,7 @@ fn main() -> Result<()> {
     let instance = Instance::new(&mut store, &module, &[])?;
 
     // Invoke `gcd` export
-    let gcd = instance.get_typed_func::<(i32, i32), i32, _>(&mut store, "gcd")?;
+    let gcd = instance.get_typed_func::<(i32, i32), i32>(&mut store, "gcd")?;
 
     println!("gcd(6, 27) = {}", gcd.call(&mut store, (6, 27))?);
     Ok(())
diff --git a/examples/hello.rs b/examples/hello.rs
index 62ae9fa35..67df450ec 100644
--- a/examples/hello.rs
+++ b/examples/hello.rs
@@ -53,7 +53,7 @@ fn main() -> Result<()> {
 
     // Next we poke around a bit to extract the `run` function from the module.
     println!("Extracting export...");
-    let run = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     // And last but not least we can call it!
     println!("Calling export...");
diff --git a/examples/interrupt.rs b/examples/interrupt.rs
index 749a63304..87d6d4dd0 100644
--- a/examples/interrupt.rs
+++ b/examples/interrupt.rs
@@ -16,7 +16,7 @@ fn main() -> Result<()> {
     // Compile and instantiate a small example with an infinite loop.
     let module = Module::from_file(&engine, "examples/interrupt.wat")?;
     let instance = Instance::new(&mut store, &module, &[])?;
-    let run = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     // Spin up a thread to send us an interrupt in a second
     std::thread::spawn(move || {
diff --git a/examples/linking.rs b/examples/linking.rs
index fbcd11dfd..a2d756057 100644
--- a/examples/linking.rs
+++ b/examples/linking.rs
@@ -32,7 +32,7 @@ fn main() -> Result<()> {
 
     // And with that we can perform the final link and the execute the module.
     let linking1 = linker.instantiate(&mut store, &linking1)?;
-    let run = linking1.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run = linking1.get_typed_func::<(), ()>(&mut store, "run")?;
     run.call(&mut store, ())?;
     Ok(())
 }
diff --git a/examples/memory.rs b/examples/memory.rs
index ab971b2d0..93c712cf1 100644
--- a/examples/memory.rs
+++ b/examples/memory.rs
@@ -20,9 +20,9 @@ fn main() -> Result<()> {
     let memory = instance
         .get_memory(&mut store, "memory")
         .ok_or(anyhow::format_err!("failed to find `memory` export"))?;
-    let size = instance.get_typed_func::<(), i32, _>(&mut store, "size")?;
-    let load_fn = instance.get_typed_func::<i32, i32, _>(&mut store, "load")?;
-    let store_fn = instance.get_typed_func::<(i32, i32), (), _>(&mut store, "store")?;
+    let size = instance.get_typed_func::<(), i32>(&mut store, "size")?;
+    let load_fn = instance.get_typed_func::<i32, i32>(&mut store, "load")?;
+    let store_fn = instance.get_typed_func::<(i32, i32), ()>(&mut store, "store")?;
 
     println!("Checking memory...");
     assert_eq!(memory.size(&store), 2);
diff --git a/examples/multi.rs b/examples/multi.rs
index b243d83cd..8f495847b 100644
--- a/examples/multi.rs
+++ b/examples/multi.rs
@@ -33,7 +33,7 @@ fn main() -> Result<()> {
 
     // Extract exports.
     println!("Extracting export...");
-    let g = instance.get_typed_func::<(i32, i64), (i64, i32), _>(&mut store, "g")?;
+    let g = instance.get_typed_func::<(i32, i64), (i64, i32)>(&mut store, "g")?;
 
     // Call `$g`.
     println!("Calling export \"g\"...");
@@ -51,7 +51,6 @@ fn main() -> Result<()> {
         .get_typed_func::<
         (i64, i64, i64, i64, i64, i64, i64, i64, i64, i64),
         (i64, i64, i64, i64, i64, i64, i64, i64, i64, i64),
-        _,
         >
         (&mut store, "round_trip_many")?;
     let results = round_trip_many.call(&mut store, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9))?;
diff --git a/examples/multimemory.rs b/examples/multimemory.rs
index 9a1dd8e16..023817f6a 100644
--- a/examples/multimemory.rs
+++ b/examples/multimemory.rs
@@ -25,16 +25,16 @@ fn main() -> Result<()> {
     let memory0 = instance
         .get_memory(&mut store, "memory0")
         .ok_or(anyhow::format_err!("failed to find `memory0` export"))?;
-    let size0 = instance.get_typed_func::<(), i32, _>(&mut store, "size0")?;
-    let load0 = instance.get_typed_func::<i32, i32, _>(&mut store, "load0")?;
-    let store0 = instance.get_typed_func::<(i32, i32), (), _>(&mut store, "store0")?;
+    let size0 = instance.get_typed_func::<(), i32>(&mut store, "size0")?;
+    let load0 = instance.get_typed_func::<i32, i32>(&mut store, "load0")?;
+    let store0 = instance.get_typed_func::<(i32, i32), ()>(&mut store, "store0")?;
 
     let memory1 = instance
         .get_memory(&mut store, "memory1")
         .ok_or(anyhow::format_err!("failed to find `memory1` export"))?;
-    let size1 = instance.get_typed_func::<(), i32, _>(&mut store, "size1")?;
-    let load1 = instance.get_typed_func::<i32, i32, _>(&mut store, "load1")?;
-    let store1 = instance.get_typed_func::<(i32, i32), (), _>(&mut store, "store1")?;
+    let size1 = instance.get_typed_func::<(), i32>(&mut store, "size1")?;
+    let load1 = instance.get_typed_func::<i32, i32>(&mut store, "load1")?;
+    let store1 = instance.get_typed_func::<(i32, i32), ()>(&mut store, "store1")?;
 
     println!("Checking memory...");
     assert_eq!(memory0.size(&store), 2);
diff --git a/examples/serialize.rs b/examples/serialize.rs
index 22a281698..0d38fd5f5 100644
--- a/examples/serialize.rs
+++ b/examples/serialize.rs
@@ -53,7 +53,7 @@ fn deserialize(buffer: &[u8]) -> Result<()> {
 
     // Next we poke around a bit to extract the `run` function from the module.
     println!("Extracting export...");
-    let run = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     // And last but not least we can call it!
     println!("Calling export...");
diff --git a/examples/threads.rs b/examples/threads.rs
index 9586022a5..3c3564833 100644
--- a/examples/threads.rs
+++ b/examples/threads.rs
@@ -52,7 +52,7 @@ fn run(engine: &Engine, module: &Module, linker: &Linker<()>) -> Result<()> {
     println!("Instantiating module...");
     let mut store = Store::new(&engine, ());
     let instance = linker.instantiate(&mut store, module)?;
-    let run = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     println!("Executing...");
     for _ in 0..N_REPS {
diff --git a/examples/tokio/main.rs b/examples/tokio/main.rs
index f26e7beae..e90f6de97 100644
--- a/examples/tokio/main.rs
+++ b/examples/tokio/main.rs
@@ -106,7 +106,7 @@ async fn run_wasm(inputs: Inputs) -> Result<(), Error> {
         .instantiate_async(&mut store, &inputs.env.module)
         .await?;
     instance
-        .get_typed_func::<(), (), _>(&mut store, "_start")?
+        .get_typed_func::<(), ()>(&mut store, "_start")?
         .call_async(&mut store, ())
         .await?;
 
diff --git a/examples/wasi/main.rs b/examples/wasi/main.rs
index 8ffd98d78..30d8e1f2a 100644
--- a/examples/wasi/main.rs
+++ b/examples/wasi/main.rs
@@ -30,7 +30,7 @@ fn main() -> Result<()> {
     linker.module(&mut store, "", &module)?;
     linker
         .get_default(&mut store, "")?
-        .typed::<(), (), _>(&store)?
+        .typed::<(), ()>(&store)?
         .call(&mut store, ())?;
 
     Ok(())
diff --git a/src/commands/compile.rs b/src/commands/compile.rs
index 0988e5749..e7562447a 100644
--- a/src/commands/compile.rs
+++ b/src/commands/compile.rs
@@ -133,7 +133,7 @@ mod test {
         let module = unsafe { Module::deserialize(&engine, contents)? };
         let mut store = Store::new(&engine, ());
         let instance = Instance::new(&mut store, &module, &[])?;
-        let f = instance.get_typed_func::<i32, i32, _>(&mut store, "f")?;
+        let f = instance.get_typed_func::<i32, i32>(&mut store, "f")?;
         assert_eq!(f.call(&mut store, 1234).unwrap(), 1234);
 
         Ok(())


Test patch:
diff --git a/crates/test-programs/tests/wasm_tests/runtime/cap_std_sync.rs b/crates/test-programs/tests/wasm_tests/runtime/cap_std_sync.rs
index 80569ee7a..939b0bdb9 100644
--- a/crates/test-programs/tests/wasm_tests/runtime/cap_std_sync.rs
+++ b/crates/test-programs/tests/wasm_tests/runtime/cap_std_sync.rs
@@ -59,7 +59,7 @@ fn run(
 
         let mut store = Store::new(&engine, builder.build());
         let instance = linker.instantiate(&mut store, &module)?;
-        let start = instance.get_typed_func::<(), (), _>(&mut store, "_start")?;
+        let start = instance.get_typed_func::<(), ()>(&mut store, "_start")?;
         start.call(&mut store, ()).map_err(anyhow::Error::from)
     };
 
diff --git a/crates/test-programs/tests/wasm_tests/runtime/tokio.rs b/crates/test-programs/tests/wasm_tests/runtime/tokio.rs
index 3eb23e8a3..565dc088d 100644
--- a/crates/test-programs/tests/wasm_tests/runtime/tokio.rs
+++ b/crates/test-programs/tests/wasm_tests/runtime/tokio.rs
@@ -67,7 +67,7 @@ fn run(
             let mut store = Store::new(&engine, builder.build());
 
             let instance = linker.instantiate_async(&mut store, &module).await?;
-            let start = instance.get_typed_func::<(), (), _>(&mut store, "_start")?;
+            let start = instance.get_typed_func::<(), ()>(&mut store, "_start")?;
             start
                 .call_async(&mut store, ())
                 .await
diff --git a/tests/all/async_functions.rs b/tests/all/async_functions.rs
index d2b0d03cb..7d8a389b3 100644
--- a/tests/all/async_functions.rs
+++ b/tests/all/async_functions.rs
@@ -14,7 +14,7 @@ async fn run_smoke_test(store: &mut Store<()>, func: Func) {
 }
 
 async fn run_smoke_typed_test(store: &mut Store<()>, func: Func) {
-    let func = func.typed::<(), (), _>(&store).unwrap();
+    let func = func.typed::<(), ()>(&store).unwrap();
     func.call_async(&mut *store, ()).await.unwrap();
     func.call_async(&mut *store, ()).await.unwrap();
 }
@@ -545,8 +545,8 @@ async fn recursive_async() -> Result<()> {
         )",
     )?;
     let i = Instance::new_async(&mut store, &m, &[]).await?;
-    let overflow = i.get_typed_func::<(), (), _>(&mut store, "overflow")?;
-    let normal = i.get_typed_func::<(), (), _>(&mut store, "normal")?;
+    let overflow = i.get_typed_func::<(), ()>(&mut store, "overflow")?;
+    let normal = i.get_typed_func::<(), ()>(&mut store, "normal")?;
     let f2 = Func::wrap0_async(&mut store, move |mut caller| {
         Box::new(async move {
             // recursive async calls shouldn't immediately stack overflow...
@@ -600,7 +600,7 @@ async fn linker_module_command() -> Result<()> {
 
     linker.module_async(&mut store, "", &module1).await?;
     let instance = linker.instantiate_async(&mut store, &module2).await?;
-    let f = instance.get_typed_func::<(), i32, _>(&mut store, "get")?;
+    let f = instance.get_typed_func::<(), i32>(&mut store, "get")?;
     assert_eq!(f.call_async(&mut store, ()).await?, 0);
     assert_eq!(f.call_async(&mut store, ()).await?, 0);
 
@@ -638,7 +638,7 @@ async fn linker_module_reactor() -> Result<()> {
 
     linker.module_async(&mut store, "", &module1).await?;
     let instance = linker.instantiate_async(&mut store, &module2).await?;
-    let f = instance.get_typed_func::<(), i32, _>(&mut store, "get")?;
+    let f = instance.get_typed_func::<(), i32>(&mut store, "get")?;
     assert_eq!(f.call_async(&mut store, ()).await?, 0);
     assert_eq!(f.call_async(&mut store, ()).await?, 1);
 
diff --git a/tests/all/call_hook.rs b/tests/all/call_hook.rs
index f28771a2d..7184f06db 100644
--- a/tests/all/call_hook.rs
+++ b/tests/all/call_hook.rs
@@ -76,7 +76,7 @@ fn call_wrapped_func() -> Result<(), Error> {
         assert_eq!(store.data().calls_into_wasm, n);
         assert_eq!(store.data().returns_from_wasm, n);
 
-        f.typed::<(i32, i64, f32, f64), (), _>(&store)?
+        f.typed::<(i32, i64, f32, f64), ()>(&store)?
             .call(&mut store, (1, 2, 3.0, 4.0))?;
         n += 1;
 
@@ -150,7 +150,7 @@ async fn call_wrapped_async_func() -> Result<(), Error> {
     assert_eq!(store.data().calls_into_wasm, 1);
     assert_eq!(store.data().returns_from_wasm, 1);
 
-    f.typed::<(i32, i64, f32, f64), (), _>(&store)?
+    f.typed::<(i32, i64, f32, f64), ()>(&store)?
         .call_async(&mut store, (1, 2, 3.0, 4.0))
         .await?;
 
@@ -218,7 +218,7 @@ fn call_linked_func() -> Result<(), Error> {
     assert_eq!(store.data().calls_into_wasm, 1);
     assert_eq!(store.data().returns_from_wasm, 1);
 
-    export.typed::<(), (), _>(&store)?.call(&mut store, ())?;
+    export.typed::<(), ()>(&store)?.call(&mut store, ())?;
 
     assert_eq!(store.data().calls_into_host, 2);
     assert_eq!(store.data().returns_from_host, 2);
@@ -290,7 +290,7 @@ async fn call_linked_func_async() -> Result<(), Error> {
     assert_eq!(store.data().returns_from_wasm, 1);
 
     export
-        .typed::<(), (), _>(&store)?
+        .typed::<(), ()>(&store)?
         .call_async(&mut store, ())
         .await?;
 
@@ -362,7 +362,7 @@ fn recursion() -> Result<(), Error> {
                 .expect("caller exports \"export\"")
                 .into_func()
                 .expect("export is a func")
-                .typed::<i32, (), _>(&caller)
+                .typed::<i32, ()>(&caller)
                 .expect("export typing")
                 .call(&mut caller, n - 1)
                 .unwrap()
@@ -398,7 +398,7 @@ fn recursion() -> Result<(), Error> {
     assert_eq!(store.data().returns_from_wasm, n + 1);
 
     export
-        .typed::<i32, (), _>(&store)?
+        .typed::<i32, ()>(&store)?
         .call(&mut store, n as i32)?;
 
     assert_eq!(store.data().calls_into_host, 2 * (n + 1));
@@ -445,7 +445,7 @@ fn trapping() -> Result<(), Error> {
                     .expect("caller exports \"export\"")
                     .into_func()
                     .expect("export is a func")
-                    .typed::<(i32, i32), (), _>(&caller)
+                    .typed::<(i32, i32), ()>(&caller)
                     .expect("export typing")
                     .call(&mut caller, (action, 0))?;
             }
@@ -676,7 +676,7 @@ async fn timeout_async_hook() -> Result<(), Error> {
 
     let inst = linker.instantiate_async(&mut store, &module).await?;
     let export = inst
-        .get_typed_func::<(), (), _>(&mut store, "export")
+        .get_typed_func::<(), ()>(&mut store, "export")
         .expect("export is func");
 
     store.set_epoch_deadline(1);
@@ -743,7 +743,7 @@ async fn drop_suspended_async_hook() -> Result<(), Error> {
     let inst = linker.instantiate_async(&mut store, &module).await?;
     assert_eq!(*store.data(), 0);
     let export = inst
-        .get_typed_func::<(), (), _>(&mut store, "")
+        .get_typed_func::<(), ()>(&mut store, "")
         .expect("export is func");
 
     // First test that if we drop in the middle of an async hook that everything
diff --git a/tests/all/custom_signal_handler.rs b/tests/all/custom_signal_handler.rs
index 22cf65416..498014093 100644
--- a/tests/all/custom_signal_handler.rs
+++ b/tests/all/custom_signal_handler.rs
@@ -47,7 +47,7 @@ mod tests {
 
     fn invoke_export(store: &mut Store<()>, instance: Instance, func_name: &str) -> Result<i32> {
         let ret = instance
-            .get_typed_func::<(), i32, _>(&mut *store, func_name)?
+            .get_typed_func::<(), i32>(&mut *store, func_name)?
             .call(store, ())?;
         Ok(ret)
     }
@@ -175,7 +175,7 @@ mod tests {
 
         // these invoke wasmtime_call_trampoline from callable.rs
         {
-            let read_func = instance.get_typed_func::<(), i32, _>(&mut store, "read")?;
+            let read_func = instance.get_typed_func::<(), i32>(&mut store, "read")?;
             println!("calling read...");
             let result = read_func
                 .call(&mut store, ())
@@ -185,7 +185,7 @@ mod tests {
 
         {
             let read_out_of_bounds_func =
-                instance.get_typed_func::<(), i32, _>(&mut store, "read_out_of_bounds")?;
+                instance.get_typed_func::<(), i32>(&mut store, "read_out_of_bounds")?;
             println!("calling read_out_of_bounds...");
             let trap = read_out_of_bounds_func
                 .call(&mut store, ())
diff --git a/tests/all/externals.rs b/tests/all/externals.rs
index 04742fa50..baf15c9d1 100644
--- a/tests/all/externals.rs
+++ b/tests/all/externals.rs
@@ -133,8 +133,8 @@ fn cross_store() -> anyhow::Result<()> {
         .call(&mut store2, &[Some(s2_f.clone()).into()], &mut [])
         .is_ok());
 
-    let s1_f_t = s1_f.typed::<Option<Func>, (), _>(&store1)?;
-    let s2_f_t = s2_f.typed::<Option<Func>, (), _>(&store2)?;
+    let s1_f_t = s1_f.typed::<Option<Func>, ()>(&store1)?;
+    let s2_f_t = s2_f.typed::<Option<Func>, ()>(&store2)?;
 
     assert!(s1_f_t.call(&mut store1, None).is_ok());
     assert!(s2_f_t.call(&mut store2, None).is_ok());
diff --git a/tests/all/fuel.rs b/tests/all/fuel.rs
index a42c3084d..eec8f9dff 100644
--- a/tests/all/fuel.rs
+++ b/tests/all/fuel.rs
@@ -170,9 +170,7 @@ fn host_function_consumes_all() {
     });
 
     let instance = Instance::new(&mut store, &module, &[func.into()]).unwrap();
-    let export = instance
-        .get_typed_func::<(), (), _>(&mut store, "")
-        .unwrap();
+    let export = instance.get_typed_func::<(), ()>(&mut store, "").unwrap();
     let trap = export.call(&mut store, ()).unwrap_err();
     assert!(
         format!("{trap:?}").contains("all fuel consumed"),
diff --git a/tests/all/func.rs b/tests/all/func.rs
index d56d44e50..30bc0c95b 100644
--- a/tests/all/func.rs
+++ b/tests/all/func.rs
@@ -246,40 +246,40 @@ fn trap_import() -> Result<()> {
 fn get_from_wrapper() {
     let mut store = Store::<()>::default();
     let f = Func::wrap(&mut store, || {});
-    assert!(f.typed::<(), (), _>(&store).is_ok());
-    assert!(f.typed::<(), i32, _>(&store).is_err());
-    assert!(f.typed::<(), (), _>(&store).is_ok());
-    assert!(f.typed::<i32, (), _>(&store).is_err());
-    assert!(f.typed::<i32, i32, _>(&store).is_err());
-    assert!(f.typed::<(i32, i32), (), _>(&store).is_err());
-    assert!(f.typed::<(i32, i32), i32, _>(&store).is_err());
+    assert!(f.typed::<(), ()>(&store).is_ok());
+    assert!(f.typed::<(), i32>(&store).is_err());
+    assert!(f.typed::<(), ()>(&store).is_ok());
+    assert!(f.typed::<i32, ()>(&store).is_err());
+    assert!(f.typed::<i32, i32>(&store).is_err());
+    assert!(f.typed::<(i32, i32), ()>(&store).is_err());
+    assert!(f.typed::<(i32, i32), i32>(&store).is_err());
 
     let f = Func::wrap(&mut store, || -> i32 { loop {} });
-    assert!(f.typed::<(), i32, _>(&store).is_ok());
+    assert!(f.typed::<(), i32>(&store).is_ok());
     let f = Func::wrap(&mut store, || -> f32 { loop {} });
-    assert!(f.typed::<(), f32, _>(&store).is_ok());
+    assert!(f.typed::<(), f32>(&store).is_ok());
     let f = Func::wrap(&mut store, || -> f64 { loop {} });
-    assert!(f.typed::<(), f64, _>(&store).is_ok());
+    assert!(f.typed::<(), f64>(&store).is_ok());
     let f = Func::wrap(&mut store, || -> Option<ExternRef> { loop {} });
-    assert!(f.typed::<(), Option<ExternRef>, _>(&store).is_ok());
+    assert!(f.typed::<(), Option<ExternRef>>(&store).is_ok());
     let f = Func::wrap(&mut store, || -> Option<Func> { loop {} });
-    assert!(f.typed::<(), Option<Func>, _>(&store).is_ok());
+    assert!(f.typed::<(), Option<Func>>(&store).is_ok());
 
     let f = Func::wrap(&mut store, |_: i32| {});
-    assert!(f.typed::<i32, (), _>(&store).is_ok());
-    assert!(f.typed::<i64, (), _>(&store).is_err());
-    assert!(f.typed::<f32, (), _>(&store).is_err());
-    assert!(f.typed::<f64, (), _>(&store).is_err());
+    assert!(f.typed::<i32, ()>(&store).is_ok());
+    assert!(f.typed::<i64, ()>(&store).is_err());
+    assert!(f.typed::<f32, ()>(&store).is_err());
+    assert!(f.typed::<f64, ()>(&store).is_err());
     let f = Func::wrap(&mut store, |_: i64| {});
-    assert!(f.typed::<i64, (), _>(&store).is_ok());
+    assert!(f.typed::<i64, ()>(&store).is_ok());
     let f = Func::wrap(&mut store, |_: f32| {});
-    assert!(f.typed::<f32, (), _>(&store).is_ok());
+    assert!(f.typed::<f32, ()>(&store).is_ok());
     let f = Func::wrap(&mut store, |_: f64| {});
-    assert!(f.typed::<f64, (), _>(&store).is_ok());
+    assert!(f.typed::<f64, ()>(&store).is_ok());
     let f = Func::wrap(&mut store, |_: Option<ExternRef>| {});
-    assert!(f.typed::<Option<ExternRef>, (), _>(&store).is_ok());
+    assert!(f.typed::<Option<ExternRef>, ()>(&store).is_ok());
     let f = Func::wrap(&mut store, |_: Option<Func>| {});
-    assert!(f.typed::<Option<Func>, (), _>(&store).is_ok());
+    assert!(f.typed::<Option<Func>, ()>(&store).is_ok());
 }
 
 #[test]
@@ -287,16 +287,16 @@ fn get_from_signature() {
     let mut store = Store::<()>::default();
     let ty = FuncType::new(None, None);
     let f = Func::new(&mut store, ty, |_, _, _| panic!());
-    assert!(f.typed::<(), (), _>(&store).is_ok());
-    assert!(f.typed::<(), i32, _>(&store).is_err());
-    assert!(f.typed::<i32, (), _>(&store).is_err());
+    assert!(f.typed::<(), ()>(&store).is_ok());
+    assert!(f.typed::<(), i32>(&store).is_err());
+    assert!(f.typed::<i32, ()>(&store).is_err());
 
     let ty = FuncType::new(Some(ValType::I32), Some(ValType::F64));
     let f = Func::new(&mut store, ty, |_, _, _| panic!());
-    assert!(f.typed::<(), (), _>(&store).is_err());
-    assert!(f.typed::<(), i32, _>(&store).is_err());
-    assert!(f.typed::<i32, (), _>(&store).is_err());
-    assert!(f.typed::<i32, f64, _>(&store).is_ok());
+    assert!(f.typed::<(), ()>(&store).is_err());
+    assert!(f.typed::<(), i32>(&store).is_err());
+    assert!(f.typed::<i32, ()>(&store).is_err());
+    assert!(f.typed::<i32, f64>(&store).is_ok());
 }
 
 #[test]
@@ -316,17 +316,17 @@ fn get_from_module() -> anyhow::Result<()> {
     )?;
     let instance = Instance::new(&mut store, &module, &[])?;
     let f0 = instance.get_func(&mut store, "f0").unwrap();
-    assert!(f0.typed::<(), (), _>(&store).is_ok());
-    assert!(f0.typed::<(), i32, _>(&store).is_err());
+    assert!(f0.typed::<(), ()>(&store).is_ok());
+    assert!(f0.typed::<(), i32>(&store).is_err());
     let f1 = instance.get_func(&mut store, "f1").unwrap();
-    assert!(f1.typed::<(), (), _>(&store).is_err());
-    assert!(f1.typed::<i32, (), _>(&store).is_ok());
-    assert!(f1.typed::<i32, f32, _>(&store).is_err());
+    assert!(f1.typed::<(), ()>(&store).is_err());
+    assert!(f1.typed::<i32, ()>(&store).is_ok());
+    assert!(f1.typed::<i32, f32>(&store).is_err());
     let f2 = instance.get_func(&mut store, "f2").unwrap();
-    assert!(f2.typed::<(), (), _>(&store).is_err());
-    assert!(f2.typed::<(), i32, _>(&store).is_ok());
-    assert!(f2.typed::<i32, (), _>(&store).is_err());
-    assert!(f2.typed::<i32, f32, _>(&store).is_err());
+    assert!(f2.typed::<(), ()>(&store).is_err());
+    assert!(f2.typed::<(), i32>(&store).is_ok());
+    assert!(f2.typed::<i32, ()>(&store).is_err());
+    assert!(f2.typed::<i32, f32>(&store).is_err());
     Ok(())
 }
 
@@ -344,29 +344,29 @@ fn call_wrapped_func() -> Result<()> {
         &[Val::I32(1), Val::I64(2), 3.0f32.into(), 4.0f64.into()],
         &mut [],
     )?;
-    f.typed::<(i32, i64, f32, f64), (), _>(&store)?
+    f.typed::<(i32, i64, f32, f64), ()>(&store)?
         .call(&mut store, (1, 2, 3.0, 4.0))?;
 
     let mut results = [Val::I32(0)];
     let f = Func::wrap(&mut store, || 1i32);
     f.call(&mut store, &[], &mut results)?;
     assert_eq!(results[0].unwrap_i32(), 1);
-    assert_eq!(f.typed::<(), i32, _>(&store)?.call(&mut store, ())?, 1);
+    assert_eq!(f.typed::<(), i32>(&store)?.call(&mut store, ())?, 1);
 
     let f = Func::wrap(&mut store, || 2i64);
     f.call(&mut store, &[], &mut results)?;
     assert_eq!(results[0].unwrap_i64(), 2);
-    assert_eq!(f.typed::<(), i64, _>(&store)?.call(&mut store, ())?, 2);
+    assert_eq!(f.typed::<(), i64>(&store)?.call(&mut store, ())?, 2);
 
     let f = Func::wrap(&mut store, || 3.0f32);
     f.call(&mut store, &[], &mut results)?;
     assert_eq!(results[0].unwrap_f32(), 3.0);
-    assert_eq!(f.typed::<(), f32, _>(&store)?.call(&mut store, ())?, 3.0);
+    assert_eq!(f.typed::<(), f32>(&store)?.call(&mut store, ())?, 3.0);
 
     let f = Func::wrap(&mut store, || 4.0f64);
     f.call(&mut store, &[], &mut results)?;
     assert_eq!(results[0].unwrap_f64(), 4.0);
-    assert_eq!(f.typed::<(), f64, _>(&store)?.call(&mut store, ())?, 4.0);
+    assert_eq!(f.typed::<(), f64>(&store)?.call(&mut store, ())?, 4.0);
     Ok(())
 }
 
@@ -502,7 +502,7 @@ fn pass_cross_store_arg() -> anyhow::Result<()> {
 
     // And using `.get` followed by a function call also fails with cross-Store
     // arguments.
-    let f = store1_func.typed::<Option<Func>, (), _>(&store1)?;
+    let f = store1_func.typed::<Option<Func>, ()>(&store1)?;
     let result = f.call(&mut store1, Some(store2_func));
     assert!(result.is_err());
     assert!(result.unwrap_err().to_string().contains("cross-`Store`"));
@@ -572,18 +572,17 @@ fn typed_multiple_results() -> anyhow::Result<()> {
     )?;
     let instance = Instance::new(&mut store, &module, &[])?;
     let f0 = instance.get_func(&mut store, "f0").unwrap();
-    assert!(f0.typed::<(), (), _>(&store).is_err());
-    assert!(f0.typed::<(), (i32, f32), _>(&store).is_err());
-    assert!(f0.typed::<(), i32, _>(&store).is_err());
+    assert!(f0.typed::<(), ()>(&store).is_err());
+    assert!(f0.typed::<(), (i32, f32)>(&store).is_err());
+    assert!(f0.typed::<(), i32>(&store).is_err());
     assert_eq!(
-        f0.typed::<(), (i32, i64), _>(&store)?
-            .call(&mut store, ())?,
+        f0.typed::<(), (i32, i64)>(&store)?.call(&mut store, ())?,
         (0, 1)
     );
 
     let f1 = instance.get_func(&mut store, "f1").unwrap();
     assert_eq!(
-        f1.typed::<(i32, i32, i32), (f32, f64), _>(&store)?
+        f1.typed::<(i32, i32, i32), (f32, f64)>(&store)?
             .call(&mut store, (1, 2, 3))?,
         (2., 3.)
     );
@@ -610,7 +609,7 @@ fn trap_doesnt_leak() -> anyhow::Result<()> {
         drop(&canary1);
         bail!("")
     });
-    assert!(f1.typed::<(), (), _>(&store)?.call(&mut store, ()).is_err());
+    assert!(f1.typed::<(), ()>(&store)?.call(&mut store, ()).is_err());
     assert!(f1.call(&mut store, &[], &mut []).is_err());
 
     // test that `Func::new` is correct
@@ -620,7 +619,7 @@ fn trap_doesnt_leak() -> anyhow::Result<()> {
         drop(&canary2);
         bail!("")
     });
-    assert!(f2.typed::<(), (), _>(&store)?.call(&mut store, ()).is_err());
+    assert!(f2.typed::<(), ()>(&store)?.call(&mut store, ()).is_err());
     assert!(f2.call(&mut store, &[], &mut []).is_err());
 
     // drop everything and ensure dtors are run
@@ -646,7 +645,7 @@ fn wrap_multiple_results() -> anyhow::Result<()> {
     {
         let f = Func::wrap(&mut *store, move || t);
         let mut results = vec![Val::I32(0); f.ty(&store).results().len()];
-        assert_eq!(f.typed::<(), T, _>(&store)?.call(&mut *store, ())?, t);
+        assert_eq!(f.typed::<(), T>(&store)?.call(&mut *store, ())?, t);
         f.call(&mut *store, &[], &mut results)?;
         assert!(t.eq_values(&results));
 
@@ -654,7 +653,7 @@ fn wrap_multiple_results() -> anyhow::Result<()> {
         let instance = Instance::new(&mut *store, &module, &[f.into()])?;
         let f = instance.get_func(&mut *store, "foo").unwrap();
 
-        assert_eq!(f.typed::<(), T, _>(&store)?.call(&mut *store, ())?, t);
+        assert_eq!(f.typed::<(), T>(&store)?.call(&mut *store, ())?, t);
         f.call(&mut *store, &[], &mut results)?;
         assert!(t.eq_values(&results));
         Ok(())
@@ -814,7 +813,7 @@ fn trampoline_for_declared_elem() -> anyhow::Result<()> {
     let mut store = Store::new(&engine, ());
     let instance = Instance::new(&mut store, &module, &[])?;
 
-    let g = instance.get_typed_func::<(), Option<Func>, _>(&mut store, "g")?;
+    let g = instance.get_typed_func::<(), Option<Func>>(&mut store, "g")?;
 
     let func = g.call(&mut store, ())?;
     func.unwrap().call(&mut store, &[], &mut [])?;
@@ -871,8 +870,7 @@ fn wasm_ty_roundtrip() -> Result<(), anyhow::Error> {
          "#,
     )?;
     let instance = Instance::new(&mut store, &module, &[debug.into()])?;
-    let foo =
-        instance.get_typed_func::<(i32, u32, f32, i64, u64, f64), (), _>(&mut store, "foo")?;
+    let foo = instance.get_typed_func::<(i32, u32, f32, i64, u64, f64), ()>(&mut store, "foo")?;
     foo.call(&mut store, (-1, 1, 2.0, -3, 3, 4.0))?;
     Ok(())
 }
@@ -892,14 +890,14 @@ fn typed_funcs_count_params_correctly_in_error_messages() -> anyhow::Result<()>
     let instance = Instance::new(&mut store, &module, &[])?;
 
     // Too few parameters.
-    match instance.get_typed_func::<(), (), _>(&mut store, "f") {
+    match instance.get_typed_func::<(), ()>(&mut store, "f") {
         Ok(_) => panic!("should be wrong signature"),
         Err(e) => {
             let msg = format!("{:?}", e);
             assert!(dbg!(msg).contains("expected 0 types, found 2"))
         }
     }
-    match instance.get_typed_func::<(i32,), (), _>(&mut store, "f") {
+    match instance.get_typed_func::<(i32,), ()>(&mut store, "f") {
         Ok(_) => panic!("should be wrong signature"),
         Err(e) => {
             let msg = format!("{:?}", e);
@@ -908,7 +906,7 @@ fn typed_funcs_count_params_correctly_in_error_messages() -> anyhow::Result<()>
     }
 
     // Too many parameters.
-    match instance.get_typed_func::<(i32, i32, i32), (), _>(&mut store, "f") {
+    match instance.get_typed_func::<(i32, i32, i32), ()>(&mut store, "f") {
         Ok(_) => panic!("should be wrong signature"),
         Err(e) => {
             let msg = format!("{:?}", e);
diff --git a/tests/all/gc.rs b/tests/all/gc.rs
index 4730f7941..e9b1e0abd 100644
--- a/tests/all/gc.rs
+++ b/tests/all/gc.rs
@@ -285,7 +285,7 @@ fn global_drops_externref() -> anyhow::Result<()> {
             "#,
         )?;
         let instance = Instance::new(&mut store, &module, &[])?;
-        let run = instance.get_typed_func::<Option<ExternRef>, (), _>(&mut store, "run")?;
+        let run = instance.get_typed_func::<Option<ExternRef>, ()>(&mut store, "run")?;
         let flag = Arc::new(AtomicBool::new(false));
         let externref = ExternRef::new(SetFlagOnDrop(flag.clone()));
         run.call(&mut store, Some(externref))?;
@@ -335,7 +335,7 @@ fn table_drops_externref() -> anyhow::Result<()> {
         "#,
         )?;
         let instance = Instance::new(&mut store, &module, &[])?;
-        let run = instance.get_typed_func::<Option<ExternRef>, (), _>(&mut store, "run")?;
+        let run = instance.get_typed_func::<Option<ExternRef>, ()>(&mut store, "run")?;
         let flag = Arc::new(AtomicBool::new(false));
         let externref = ExternRef::new(SetFlagOnDrop(flag.clone()));
         run.call(&mut store, Some(externref))?;
@@ -387,7 +387,7 @@ fn gee_i_sure_hope_refcounting_is_atomic() -> anyhow::Result<()> {
     )?;
 
     let instance = Instance::new(&mut store, &module, &[])?;
-    let run = instance.get_typed_func::<Option<ExternRef>, (), _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<Option<ExternRef>, ()>(&mut store, "run")?;
 
     let flag = Arc::new(AtomicBool::new(false));
     let externref = ExternRef::new(SetFlagOnDrop(flag.clone()));
@@ -482,7 +482,7 @@ fn no_gc_middle_of_args() -> anyhow::Result<()> {
     )?;
 
     let instance = linker.instantiate(&mut store, &module)?;
-    let func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
     func.call(&mut store, ())?;
 
     Ok(())
diff --git a/tests/all/host_funcs.rs b/tests/all/host_funcs.rs
index 9b96b69ee..795305efb 100644
--- a/tests/all/host_funcs.rs
+++ b/tests/all/host_funcs.rs
@@ -430,7 +430,7 @@ fn call_wasm_many_args() -> Result<()> {
     )?;
 
     let typed_run = instance
-        .get_typed_func::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), (), _>(
+        .get_typed_func::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), ()>(
             &mut store, "run",
         )?;
     typed_run.call(&mut store, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))?;
@@ -499,19 +499,19 @@ fn new_from_signature() -> Result<()> {
         .unwrap()
         .into_func()
         .unwrap();
-    assert!(f.typed::<(), (), _>(&store).is_ok());
-    assert!(f.typed::<(), i32, _>(&store).is_err());
-    assert!(f.typed::<i32, (), _>(&store).is_err());
+    assert!(f.typed::<(), ()>(&store).is_ok());
+    assert!(f.typed::<(), i32>(&store).is_err());
+    assert!(f.typed::<i32, ()>(&store).is_err());
 
     let f = linker
         .get(&mut store, "", "f2")
         .unwrap()
         .into_func()
         .unwrap();
-    assert!(f.typed::<(), (), _>(&store).is_err());
-    assert!(f.typed::<(), i32, _>(&store).is_err());
-    assert!(f.typed::<i32, (), _>(&store).is_err());
-    assert!(f.typed::<i32, f64, _>(&store).is_ok());
+    assert!(f.typed::<(), ()>(&store).is_err());
+    assert!(f.typed::<(), i32>(&store).is_err());
+    assert!(f.typed::<i32, ()>(&store).is_err());
+    assert!(f.typed::<i32, f64>(&store).is_ok());
 
     Ok(())
 }
@@ -549,7 +549,7 @@ fn call_wrapped_func() -> Result<()> {
         &[Val::I32(1), Val::I64(2), 3.0f32.into(), 4.0f64.into()],
         &mut [],
     )?;
-    f.typed::<(i32, i64, f32, f64), (), _>(&store)?
+    f.typed::<(i32, i64, f32, f64), ()>(&store)?
         .call(&mut store, (1, 2, 3.0, 4.0))?;
 
     let f = linker
@@ -559,7 +559,7 @@ fn call_wrapped_func() -> Result<()> {
         .unwrap();
     f.call(&mut store, &[], &mut results)?;
     assert_eq!(results[0].unwrap_i32(), 1);
-    assert_eq!(f.typed::<(), i32, _>(&store)?.call(&mut store, ())?, 1);
+    assert_eq!(f.typed::<(), i32>(&store)?.call(&mut store, ())?, 1);
 
     let f = linker
         .get(&mut store, "", "f3")
@@ -568,7 +568,7 @@ fn call_wrapped_func() -> Result<()> {
         .unwrap();
     f.call(&mut store, &[], &mut results)?;
     assert_eq!(results[0].unwrap_i64(), 2);
-    assert_eq!(f.typed::<(), i64, _>(&store)?.call(&mut store, ())?, 2);
+    assert_eq!(f.typed::<(), i64>(&store)?.call(&mut store, ())?, 2);
 
     let f = linker
         .get(&mut store, "", "f4")
@@ -577,7 +577,7 @@ fn call_wrapped_func() -> Result<()> {
         .unwrap();
     f.call(&mut store, &[], &mut results)?;
     assert_eq!(results[0].unwrap_f32(), 3.0);
-    assert_eq!(f.typed::<(), f32, _>(&store)?.call(&mut store, ())?, 3.0);
+    assert_eq!(f.typed::<(), f32>(&store)?.call(&mut store, ())?, 3.0);
 
     let f = linker
         .get(&mut store, "", "f5")
@@ -586,7 +586,7 @@ fn call_wrapped_func() -> Result<()> {
         .unwrap();
     f.call(&mut store, &[], &mut results)?;
     assert_eq!(results[0].unwrap_f64(), 4.0);
-    assert_eq!(f.typed::<(), f64, _>(&store)?.call(&mut store, ())?, 4.0);
+    assert_eq!(f.typed::<(), f64>(&store)?.call(&mut store, ())?, 4.0);
 
     Ok(())
 }
@@ -714,7 +714,7 @@ fn wasi_imports() -> Result<()> {
     let mut store = Store::new(&engine, WasiCtxBuilder::new().build());
     let instance = linker.instantiate(&mut store, &module)?;
 
-    let start = instance.get_typed_func::<(), (), _>(&mut store, "_start")?;
+    let start = instance.get_typed_func::<(), ()>(&mut store, "_start")?;
     let exit = start
         .call(&mut store, ())
         .unwrap_err()
diff --git a/tests/all/iloop.rs b/tests/all/iloop.rs
index 68614ddd7..fedef6f6d 100644
--- a/tests/all/iloop.rs
+++ b/tests/all/iloop.rs
@@ -29,7 +29,7 @@ fn loops_interruptable() -> anyhow::Result<()> {
     let mut store = interruptable_store();
     let module = Module::new(store.engine(), r#"(func (export "loop") (loop br 0))"#)?;
     let instance = Instance::new(&mut store, &module, &[])?;
-    let iloop = instance.get_typed_func::<(), (), _>(&mut store, "loop")?;
+    let iloop = instance.get_typed_func::<(), ()>(&mut store, "loop")?;
     store.engine().increment_epoch();
     let trap = iloop.call(&mut store, ()).unwrap_err().downcast::<Trap>()?;
     assert_eq!(trap, Trap::Interrupt);
@@ -42,7 +42,7 @@ fn functions_interruptable() -> anyhow::Result<()> {
     let module = hugely_recursive_module(store.engine())?;
     let func = Func::wrap(&mut store, || {});
     let instance = Instance::new(&mut store, &module, &[func.into()])?;
-    let iloop = instance.get_typed_func::<(), (), _>(&mut store, "loop")?;
+    let iloop = instance.get_typed_func::<(), ()>(&mut store, "loop")?;
     store.engine().increment_epoch();
     let trap = iloop.call(&mut store, ()).unwrap_err().downcast::<Trap>()?;
     assert_eq!(trap, Trap::Interrupt);
@@ -89,7 +89,7 @@ fn loop_interrupt_from_afar() -> anyhow::Result<()> {
 
     // Enter the infinitely looping function and assert that our interrupt
     // handle does indeed actually interrupt the function.
-    let iloop = instance.get_typed_func::<(), (), _>(&mut store, "loop")?;
+    let iloop = instance.get_typed_func::<(), ()>(&mut store, "loop")?;
     let trap = iloop.call(&mut store, ()).unwrap_err().downcast::<Trap>()?;
     STOP.store(true, SeqCst);
     thread.join().unwrap();
@@ -125,7 +125,7 @@ fn function_interrupt_from_afar() -> anyhow::Result<()> {
 
     // Enter the infinitely looping function and assert that our interrupt
     // handle does indeed actually interrupt the function.
-    let iloop = instance.get_typed_func::<(), (), _>(&mut store, "loop")?;
+    let iloop = instance.get_typed_func::<(), ()>(&mut store, "loop")?;
     let trap = iloop.call(&mut store, ()).unwrap_err().downcast::<Trap>()?;
     STOP.store(true, SeqCst);
     thread.join().unwrap();
diff --git a/tests/all/import_indexes.rs b/tests/all/import_indexes.rs
index 94c58639b..d6718f166 100644
--- a/tests/all/import_indexes.rs
+++ b/tests/all/import_indexes.rs
@@ -43,7 +43,7 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> {
     ];
     let instance = Instance::new(&mut store, &module, &imports)?;
 
-    let func = instance.get_typed_func::<(), i32, _>(&mut store, "foo")?;
+    let func = instance.get_typed_func::<(), i32>(&mut store, "foo")?;
     let result = func.call(&mut store, ())?;
     assert_eq!(result, 3);
     Ok(())
diff --git a/tests/all/instance.rs b/tests/all/instance.rs
index e37dd95a9..95ed175df 100644
--- a/tests/all/instance.rs
+++ b/tests/all/instance.rs
@@ -63,8 +63,8 @@ fn linear_memory_limits() -> Result<()> {
 
         let mut store = Store::new(engine, ());
         let instance = Instance::new(&mut store, &module, &[])?;
-        let size = instance.get_typed_func::<(), i32, _>(&mut store, "size")?;
-        let grow = instance.get_typed_func::<(), i32, _>(&mut store, "grow")?;
+        let size = instance.get_typed_func::<(), i32>(&mut store, "size")?;
+        let grow = instance.get_typed_func::<(), i32>(&mut store, "grow")?;
 
         assert_eq!(size.call(&mut store, ())?, 65534);
         assert_eq!(grow.call(&mut store, ())?, 65534);
diff --git a/tests/all/limits.rs b/tests/all/limits.rs
index d1b013cb1..333583f65 100644
--- a/tests/all/limits.rs
+++ b/tests/all/limits.rs
@@ -78,7 +78,7 @@ fn test_limits() -> Result<()> {
     store.limiter(|s| s as &mut dyn ResourceLimiter);
     let instance = Instance::new(&mut store, &module, &[])?;
     let grow = instance.get_func(&mut store, "grow").unwrap();
-    let grow = grow.typed::<i32, i32, _>(&store).unwrap();
+    let grow = grow.typed::<i32, i32>(&store).unwrap();
 
     grow.call(&mut store, 3).unwrap();
     grow.call(&mut store, 5).unwrap();
@@ -464,7 +464,7 @@ fn test_custom_memory_limiter() -> Result<()> {
     assert!(!store.data().limit_exceeded);
 
     // Grow the host "memory" by 384 KiB
-    let f = instance.get_typed_func::<u32, u32, _>(&mut store, "f")?;
+    let f = instance.get_typed_func::<u32, u32>(&mut store, "f")?;
 
     assert_eq!(f.call(&mut store, 1 * 0x10000)?, 1);
     assert_eq!(f.call(&mut store, 3 * 0x10000)?, 1);
@@ -576,7 +576,7 @@ async fn test_custom_memory_limiter_async() -> Result<()> {
     assert!(!store.data().limit_exceeded);
 
     // Grow the host "memory" by 384 KiB
-    let f = instance.get_typed_func::<u32, u32, _>(&mut store, "f")?;
+    let f = instance.get_typed_func::<u32, u32>(&mut store, "f")?;
 
     assert_eq!(f.call_async(&mut store, 1 * 0x10000).await?, 1);
     assert_eq!(f.call_async(&mut store, 3 * 0x10000).await?, 1);
@@ -965,7 +965,7 @@ fn panic_in_memory_limiter_wasm_stack() {
     store.limiter(|s| s as &mut dyn ResourceLimiter);
     let instance = linker.instantiate(&mut store, &module).unwrap();
     let grow = instance.get_func(&mut store, "grow").unwrap();
-    let grow = grow.typed::<i32, i32, _>(&store).unwrap();
+    let grow = grow.typed::<i32, i32>(&store).unwrap();
 
     // Grow the memory, which should panic
     grow.call(&mut store, 3).unwrap();
@@ -1032,7 +1032,7 @@ async fn panic_in_async_memory_limiter_wasm_stack() {
     store.limiter_async(|s| s as &mut dyn ResourceLimiterAsync);
     let instance = linker.instantiate_async(&mut store, &module).await.unwrap();
     let grow = instance.get_func(&mut store, "grow").unwrap();
-    let grow = grow.typed::<i32, i32, _>(&store).unwrap();
+    let grow = grow.typed::<i32, i32>(&store).unwrap();
 
     // Grow the memory, which should panic
     grow.call_async(&mut store, 3).await.unwrap();
diff --git a/tests/all/linker.rs b/tests/all/linker.rs
index 9728d757f..1f65f017b 100644
--- a/tests/all/linker.rs
+++ b/tests/all/linker.rs
@@ -101,7 +101,7 @@ fn function_interposition() -> Result<()> {
         .unwrap()
         .into_func()
         .unwrap();
-    let func = func.typed::<(), i32, _>(&store)?;
+    let func = func.typed::<(), i32>(&store)?;
     assert_eq!(func.call(&mut store, ())?, 112);
     Ok(())
 }
@@ -134,7 +134,7 @@ fn function_interposition_renamed() -> Result<()> {
     }
     let instance = linker.instantiate(&mut store, &module)?;
     let func = instance.get_func(&mut store, "export").unwrap();
-    let func = func.typed::<(), i32, _>(&store)?;
+    let func = func.typed::<(), i32>(&store)?;
     assert_eq!(func.call(&mut store, ())?, 112);
     Ok(())
 }
@@ -167,7 +167,7 @@ fn module_interposition() -> Result<()> {
         .unwrap()
         .into_func()
         .unwrap();
-    let func = func.typed::<(), i32, _>(&store)?;
+    let func = func.typed::<(), i32>(&store)?;
     assert_eq!(func.call(&mut store, ())?, 112);
     Ok(())
 }
diff --git a/tests/all/memory.rs b/tests/all/memory.rs
index 2005479f0..281a2e7ab 100644
--- a/tests/all/memory.rs
+++ b/tests/all/memory.rs
@@ -346,7 +346,7 @@ fn tiny_static_heap() -> Result<()> {
     )?;
 
     let i = Instance::new(&mut store, &module, &[])?;
-    let f = i.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let f = i.get_typed_func::<(), ()>(&mut store, "run")?;
     f.call(&mut store, ())?;
     Ok(())
 }
diff --git a/tests/all/module.rs b/tests/all/module.rs
index dd5e53f59..904bc6dc4 100644
--- a/tests/all/module.rs
+++ b/tests/all/module.rs
@@ -62,7 +62,7 @@ fn aot_compiles() -> Result<()> {
     let mut store = Store::new(&engine, ());
     let instance = Instance::new(&mut store, &module, &[])?;
 
-    let f = instance.get_typed_func::<i32, i32, _>(&mut store, "f")?;
+    let f = instance.get_typed_func::<i32, i32>(&mut store, "f")?;
     assert_eq!(f.call(&mut store, 101)?, 101);
 
     Ok(())
diff --git a/tests/all/module_serialize.rs b/tests/all/module_serialize.rs
index 121afc371..614803019 100644
--- a/tests/all/module_serialize.rs
+++ b/tests/all/module_serialize.rs
@@ -51,7 +51,7 @@ fn test_module_serialize_simple() -> Result<()> {
 
     let mut store = Store::default();
     let instance = unsafe { deserialize_and_instantiate(&mut store, &buffer)? };
-    let run = instance.get_typed_func::<(), i32, _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<(), i32>(&mut store, "run")?;
     let result = run.call(&mut store, ())?;
 
     assert_eq!(42, result);
@@ -98,7 +98,7 @@ fn test_deserialize_from_file() -> Result<()> {
         fs::write(&path, &buffer)?;
         let module = unsafe { Module::deserialize_file(store.engine(), &path)? };
         let instance = Instance::new(&mut store, &module, &[])?;
-        let func = instance.get_typed_func::<(), i32, _>(&mut store, "run")?;
+        let func = instance.get_typed_func::<(), i32>(&mut store, "run")?;
         assert_eq!(func.call(&mut store, ())?, 42);
         Ok(())
     }
diff --git a/tests/all/pooling_allocator.rs b/tests/all/pooling_allocator.rs
index b97ebd474..d2f38924d 100644
--- a/tests/all/pooling_allocator.rs
+++ b/tests/all/pooling_allocator.rs
@@ -67,7 +67,7 @@ fn memory_limit() -> Result<()> {
     {
         let mut store = Store::new(&engine, ());
         let instance = Instance::new(&mut store, &module, &[])?;
-        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, ()).expect("function should not trap"), 0);
         assert_eq!(f.call(&mut store, ()).expect("function should not trap"), 1);
@@ -149,7 +149,7 @@ fn memory_guard_page_trap() -> Result<()> {
         let mut store = Store::new(&engine, ());
         let instance = Instance::new(&mut store, &module, &[])?;
         let m = instance.get_memory(&mut store, "m").unwrap();
-        let f = instance.get_typed_func::<i32, (), _>(&mut store, "f")?;
+        let f = instance.get_typed_func::<i32, ()>(&mut store, "f")?;
 
         let trap = f
             .call(&mut store, 0)
@@ -273,7 +273,7 @@ fn table_limit() -> Result<()> {
     {
         let mut store = Store::new(&engine, ());
         let instance = Instance::new(&mut store, &module, &[])?;
-        let f = instance.get_typed_func::<(), i32, _>(&mut store, "f")?;
+        let f = instance.get_typed_func::<(), i32>(&mut store, "f")?;
 
         for i in 0..TABLE_ELEMENTS {
             assert_eq!(
@@ -611,7 +611,7 @@ fn switch_image_and_non_image() -> Result<()> {
     let assert_zero = || -> Result<()> {
         let mut store = Store::new(&engine, ());
         let instance = Instance::new(&mut store, &module1, &[])?;
-        let func = instance.get_typed_func::<i32, i32, _>(&mut store, "load")?;
+        let func = instance.get_typed_func::<i32, i32>(&mut store, "load")?;
         assert_eq!(func.call(&mut store, 0)?, 0);
         Ok(())
     };
@@ -719,10 +719,10 @@ fn dynamic_memory_pooling_allocator() -> Result<()> {
     let mut store = Store::new(&engine, ());
     let instance = Instance::new(&mut store, &module, &[])?;
 
-    let grow = instance.get_typed_func::<u32, i32, _>(&mut store, "grow")?;
-    let size = instance.get_typed_func::<(), u32, _>(&mut store, "size")?;
-    let i32_load = instance.get_typed_func::<u32, i32, _>(&mut store, "i32.load")?;
-    let i32_store = instance.get_typed_func::<(u32, i32), (), _>(&mut store, "i32.store")?;
+    let grow = instance.get_typed_func::<u32, i32>(&mut store, "grow")?;
+    let size = instance.get_typed_func::<(), u32>(&mut store, "size")?;
+    let i32_load = instance.get_typed_func::<u32, i32>(&mut store, "i32.load")?;
+    let i32_store = instance.get_typed_func::<(u32, i32), ()>(&mut store, "i32.store")?;
     let memory = instance.get_memory(&mut store, "memory").unwrap();
 
     // basic length 1 tests
@@ -757,7 +757,7 @@ fn dynamic_memory_pooling_allocator() -> Result<()> {
     // Re-instantiate in another store.
     store = Store::new(&engine, ());
     let instance = Instance::new(&mut store, &module, &[])?;
-    let i32_load = instance.get_typed_func::<u32, i32, _>(&mut store, "i32.load")?;
+    let i32_load = instance.get_typed_func::<u32, i32>(&mut store, "i32.load")?;
     let memory = instance.get_memory(&mut store, "memory").unwrap();
 
     // Technically this is out of bounds...
@@ -806,8 +806,8 @@ fn zero_memory_pages_disallows_oob() -> Result<()> {
     )?;
     let mut store = Store::new(&engine, ());
     let instance = Instance::new(&mut store, &module, &[])?;
-    let load32 = instance.get_typed_func::<i32, i32, _>(&mut store, "load")?;
-    let store32 = instance.get_typed_func::<i32, (), _>(&mut store, "store")?;
+    let load32 = instance.get_typed_func::<i32, i32>(&mut store, "load")?;
+    let store32 = instance.get_typed_func::<i32, ()>(&mut store, "store")?;
     for i in 0..31 {
         assert!(load32.call(&mut store, 1 << i).is_err());
         assert!(store32.call(&mut store, 1 << i).is_err());
diff --git a/tests/all/relocs.rs b/tests/all/relocs.rs
index c799fe1cb..a27ff6a00 100644
--- a/tests/all/relocs.rs
+++ b/tests/all/relocs.rs
@@ -43,7 +43,7 @@ fn forward_call_works() -> Result<()> {
     )?;
 
     let i = Instance::new(&mut store, &module, &[])?;
-    let foo = i.get_typed_func::<(), i32, _>(&mut store, "foo")?;
+    let foo = i.get_typed_func::<(), i32>(&mut store, "foo")?;
     assert_eq!(foo.call(&mut store, ())?, 4);
     Ok(())
 }
@@ -64,7 +64,7 @@ fn backwards_call_works() -> Result<()> {
     )?;
 
     let i = Instance::new(&mut store, &module, &[])?;
-    let foo = i.get_typed_func::<(), i32, _>(&mut store, "foo")?;
+    let foo = i.get_typed_func::<(), i32>(&mut store, "foo")?;
     assert_eq!(foo.call(&mut store, ())?, 4);
     Ok(())
 }
@@ -108,7 +108,7 @@ fn test_many_call_module(mut store: Store<()>) -> Result<()> {
 
     for i in 0..N {
         let name = i.to_string();
-        let func = instance.get_typed_func::<(), (i32, i32), _>(&mut store, &name)?;
+        let func = instance.get_typed_func::<(), (i32, i32)>(&mut store, &name)?;
         let (a, b) = func.call(&mut store, ())?;
         assert_eq!(a, i + 1);
         assert_eq!(b, i + 2);
diff --git a/tests/all/stack_overflow.rs b/tests/all/stack_overflow.rs
index 9cd90eb9c..67ab7e22a 100644
--- a/tests/all/stack_overflow.rs
+++ b/tests/all/stack_overflow.rs
@@ -24,7 +24,7 @@ fn host_always_has_some_stack() -> anyhow::Result<()> {
     )?;
     let func = Func::wrap(&mut store, test_host_stack);
     let instance = Instance::new(&mut store, &module, &[func.into()])?;
-    let foo = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
+    let foo = instance.get_typed_func::<(), ()>(&mut store, "foo")?;
 
     // Make sure that our function traps and the trap says that the call stack
     // has been exhausted.
diff --git a/tests/all/threads.rs b/tests/all/threads.rs
index 4d05a8fd8..fe497beec 100644
--- a/tests/all/threads.rs
+++ b/tests/all/threads.rs
@@ -82,10 +82,10 @@ fn test_sharing_of_shared_memory() -> Result<()> {
         ]
     });
     let instance1_first_word = instance1
-        .get_typed_func::<(), i32, _>(&mut store, "first_word")?
+        .get_typed_func::<(), i32>(&mut store, "first_word")?
         .call(&mut store, ())?;
     let instance2_first_word = instance2
-        .get_typed_func::<(), i32, _>(&mut store, "first_word")?
+        .get_typed_func::<(), i32>(&mut store, "first_word")?
         .call(&mut store, ())?;
     assert_eq!(shared_memory_first_word, 42);
     assert_eq!(instance1_first_word, 42);
@@ -106,7 +106,7 @@ fn test_probe_shared_memory_size() -> Result<()> {
     let module = Module::new(&engine, wat)?;
     let mut store = Store::new(&engine, ());
     let instance = Instance::new(&mut store, &module, &[])?;
-    let size_fn = instance.get_typed_func::<(), i32, _>(&mut store, "size")?;
+    let size_fn = instance.get_typed_func::<(), i32>(&mut store, "size")?;
     let mut shared_memory = instance.get_shared_memory(&mut store, "memory").unwrap();
 
     assert_eq!(size_fn.call(&mut store, ())?, 1);
@@ -185,7 +185,7 @@ fn test_grow_memory_in_multiple_threads() -> Result<()> {
             let mut store = Store::new(&engine, ());
             let instance = Instance::new(&mut store, &module, &[shared_memory.into()]).unwrap();
             let grow_fn = instance
-                .get_typed_func::<i32, i32, _>(&mut store, "grow")
+                .get_typed_func::<i32, i32>(&mut store, "grow")
                 .unwrap();
             let mut thread_local_observed_sizes: Vec<_> = (0..NUM_GROW_OPS / NUM_THREADS)
                 .map(|_| grow_fn.call(&mut store, 1).unwrap() as u32)
@@ -260,7 +260,7 @@ fn test_memory_size_accessibility() -> Result<()> {
         let mut store = Store::new(&engine, ());
         let instance = Instance::new(&mut store, &module, &[probe_memory.into()]).unwrap();
         let probe_fn = instance
-            .get_typed_func::<(), i32, _>(&mut store, "probe_last_available")
+            .get_typed_func::<(), i32>(&mut store, "probe_last_available")
             .unwrap();
         while !probe_done.load(Ordering::SeqCst) {
             let value = probe_fn.call(&mut store, ()).unwrap() as u32;
diff --git a/tests/all/traps.rs b/tests/all/traps.rs
index c01ddb88e..f1776c875 100644
--- a/tests/all/traps.rs
+++ b/tests/all/traps.rs
@@ -18,7 +18,7 @@ fn test_trap_return() -> Result<()> {
     let hello_func = Func::new(&mut store, hello_type, |_, _, _| bail!("test 123"));
 
     let instance = Instance::new(&mut store, &module, &[hello_func.into()])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
     assert!(format!("{e:?}").contains("test 123"));
@@ -48,7 +48,7 @@ fn test_anyhow_error_return() -> Result<()> {
     });
 
     let instance = Instance::new(&mut store, &module, &[hello_func.into()])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
     assert!(!e.to_string().contains("test 1234"));
@@ -86,7 +86,7 @@ fn test_trap_return_downcast() -> Result<()> {
     });
 
     let instance = Instance::new(&mut store, &module, &[hello_func.into()])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     let e = run_func
         .call(&mut store, ())
@@ -121,7 +121,7 @@ fn test_trap_trace() -> Result<()> {
 
     let module = Module::new(store.engine(), wat)?;
     let instance = Instance::new(&mut store, &module, &[])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
 
@@ -196,7 +196,7 @@ fn test_trap_through_host() -> Result<()> {
         &module,
         &[host_func_a.into(), host_func_b.into()],
     )?;
-    let a = instance.get_typed_func::<(), (), _>(&mut store, "a")?;
+    let a = instance.get_typed_func::<(), ()>(&mut store, "a")?;
     let err = a.call(&mut store, ()).unwrap_err();
     let trace = err.downcast_ref::<WasmBacktrace>().unwrap().frames();
     assert_eq!(trace.len(), 3);
@@ -222,7 +222,7 @@ fn test_trap_backtrace_disabled() -> Result<()> {
 
     let module = Module::new(store.engine(), wat)?;
     let instance = Instance::new(&mut store, &module, &[])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
     assert!(e.downcast_ref::<WasmBacktrace>().is_none());
@@ -245,7 +245,7 @@ fn test_trap_trace_cb() -> Result<()> {
 
     let module = Module::new(store.engine(), wat)?;
     let instance = Instance::new(&mut store, &module, &[fn_func.into()])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
 
@@ -271,7 +271,7 @@ fn test_trap_stack_overflow() -> Result<()> {
 
     let module = Module::new(store.engine(), wat)?;
     let instance = Instance::new(&mut store, &module, &[])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
 
@@ -301,7 +301,7 @@ fn trap_display_pretty() -> Result<()> {
 
     let module = Module::new(store.engine(), wat)?;
     let instance = Instance::new(&mut store, &module, &[])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "bar")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "bar")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
     assert_eq!(
@@ -345,7 +345,7 @@ fn trap_display_multi_module() -> Result<()> {
     "#;
     let module = Module::new(store.engine(), wat)?;
     let instance = Instance::new(&mut store, &module, &[bar])?;
-    let bar2 = instance.get_typed_func::<(), (), _>(&mut store, "bar2")?;
+    let bar2 = instance.get_typed_func::<(), ()>(&mut store, "bar2")?;
 
     let e = bar2.call(&mut store, ()).unwrap_err();
     assert_eq!(
@@ -405,12 +405,12 @@ fn rust_panic_import() -> Result<()> {
     let func = Func::new(&mut store, sig, |_, _, _| panic!("this is a panic"));
     let func2 = Func::wrap(&mut store, || panic!("this is another panic"));
     let instance = Instance::new(&mut store, &module, &[func.into(), func2.into()])?;
-    let func = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
+    let func = instance.get_typed_func::<(), ()>(&mut store, "foo")?;
     let err =
         panic::catch_unwind(AssertUnwindSafe(|| drop(func.call(&mut store, ())))).unwrap_err();
     assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
 
-    let func = instance.get_typed_func::<(), (), _>(&mut store, "bar")?;
+    let func = instance.get_typed_func::<(), ()>(&mut store, "bar")?;
     let err = panic::catch_unwind(AssertUnwindSafe(|| {
         drop(func.call(&mut store, ()));
     }))
@@ -468,7 +468,7 @@ fn rust_catch_panic_import() -> Result<()> {
     });
 
     let instance = Instance::new(&mut store, &module, &[panic.into(), catch_panic.into()])?;
-    let run = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
     let trap = run.call(&mut store, ()).unwrap_err();
     let trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();
     assert_eq!(trace.len(), 1);
@@ -613,7 +613,7 @@ fn present_after_module_drop() -> Result<()> {
     let mut store = Store::<()>::default();
     let module = Module::new(store.engine(), r#"(func (export "foo") unreachable)"#)?;
     let instance = Instance::new(&mut store, &module, &[])?;
-    let func = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
+    let func = instance.get_typed_func::<(), ()>(&mut store, "foo")?;
 
     println!("asserting before we drop modules");
     assert_trap(func.call(&mut store, ()).unwrap_err());
@@ -811,13 +811,13 @@ fn multithreaded_traps() -> Result<()> {
     let instance = Instance::new(&mut store, &module, &[])?;
 
     assert!(instance
-        .get_typed_func::<(), (), _>(&mut store, "run")?
+        .get_typed_func::<(), ()>(&mut store, "run")?
         .call(&mut store, ())
         .is_err());
 
     let handle = std::thread::spawn(move || {
         assert!(instance
-            .get_typed_func::<(), (), _>(&mut store, "run")
+            .get_typed_func::<(), ()>(&mut store, "run")
             .unwrap()
             .call(&mut store, ())
             .is_err());
@@ -843,7 +843,7 @@ fn traps_without_address_map() -> Result<()> {
 
     let module = Module::new(store.engine(), wat)?;
     let instance = Instance::new(&mut store, &module, &[])?;
-    let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
 
@@ -891,7 +891,7 @@ fn catch_trap_calling_across_stores() -> Result<()> {
             let data = ctx.data_mut();
             let func = data
                 .child_instance
-                .get_typed_func::<(), (), _>(&mut data.child_store, "trap")
+                .get_typed_func::<(), ()>(&mut data.child_store, "trap")
                 .expect("trap function should be exported");
 
             let trap = func.call(&mut data.child_store, ()).unwrap_err();
@@ -935,7 +935,7 @@ fn catch_trap_calling_across_stores() -> Result<()> {
 
     let parent_instance = linker.instantiate(&mut store, &parent_module)?;
 
-    let func = parent_instance.get_typed_func::<(), (), _>(&mut store, "run")?;
+    let func = parent_instance.get_typed_func::<(), ()>(&mut store, "run")?;
     func.call(store, ())?;
 
     Ok(())
@@ -994,7 +994,7 @@ async fn async_then_sync_trap() -> Result<()> {
 
         log::info!("Calling `c`...");
         let c = sync_instance
-            .get_typed_func::<(), (), _>(&mut *sync_store, "c")
+            .get_typed_func::<(), ()>(&mut *sync_store, "c")
             .unwrap();
         c.call(sync_store, ())?;
         Ok(())
@@ -1006,7 +1006,7 @@ async fn async_then_sync_trap() -> Result<()> {
 
     log::info!("Calling `a`...");
     let a = async_instance
-        .get_typed_func::<(), (), _>(&mut async_store, "a")
+        .get_typed_func::<(), ()>(&mut async_store, "a")
         .unwrap();
     let trap = a.call_async(&mut async_store, ()).await.unwrap_err();
 
@@ -1074,7 +1074,7 @@ async fn sync_then_async_trap() -> Result<()> {
 
         log::info!("Calling `c`...");
         let c = async_instance
-            .get_typed_func::<(), (), _>(&mut *async_store, "c")
+            .get_typed_func::<(), ()>(&mut *async_store, "c")
             .unwrap();
         tokio::task::block_in_place(|| {
             tokio::runtime::Handle::current()
@@ -1087,7 +1087,7 @@ async fn sync_then_async_trap() -> Result<()> {
 
     log::info!("Calling `a`...");
     let a = sync_instance
-        .get_typed_func::<(), (), _>(&mut sync_store, "a")
+        .get_typed_func::<(), ()>(&mut sync_store, "a")
         .unwrap();
     let trap = a.call(&mut sync_store, ()).unwrap_err();