Repository: bytecodealliance/wasm-tools
Pull request #2069 (2025-02-24 20:47:24)

Refactor/improve parsing of component canonical text format
This commit is an improvement and refactoring to the parsing of `(canon ...)` forms in the text format for components. Previously there was a large amount of duplication to handle the short-hand form of:

```
(core func (canon ...))
```

and the long-hand form of

```
(canon ... (core func))
```

This commit removes this duplication and in the process fixes support for the long-hand format of `(canon ...)`. This is not heavily used in tooling of this workspace but it's mentioned in the specification and should likely be supported regardless.


Patch:
diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs
index 62b855c0..161541f3 100644
--- a/crates/wasmparser/src/validator/component.rs
+++ b/crates/wasmparser/src/validator/component.rs
@@ -1437,7 +1437,7 @@ impl ComponentState {
         };
 
         self.core_funcs
-            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
+            .push(types.intern_func_type(FuncType::new([ValType::I32; 2], []), offset));
         Ok(())
     }
 
@@ -1621,7 +1621,7 @@ impl ComponentState {
         };
 
         self.core_funcs
-            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
+            .push(types.intern_func_type(FuncType::new([ValType::I32; 2], []), offset));
         Ok(())
     }
 
diff --git a/crates/wast/src/component/binary.rs b/crates/wast/src/component/binary.rs
index 1598c6aa..70786fb1 100644
--- a/crates/wast/src/component/binary.rs
+++ b/crates/wast/src/component/binary.rs
@@ -328,152 +328,157 @@ impl<'a> Encoder<'a> {
                     info.opts.iter().map(Into::into),
                 );
             }
-            CanonicalFuncKind::Lower(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .lower(info.func.idx.into(), info.opts.iter().map(Into::into));
-            }
-            CanonicalFuncKind::ResourceNew(info) => {
-                self.core_func_names.push(name);
-                self.funcs.resource_new(info.ty.into());
-            }
-            CanonicalFuncKind::ResourceDrop(info) => {
-                self.core_func_names.push(name);
-                if info.async_ {
-                    self.funcs.resource_drop_async(info.ty.into());
-                } else {
-                    self.funcs.resource_drop(info.ty.into());
+            CanonicalFuncKind::Core(core) => match core {
+                CoreFuncKind::Alias(_) => {
+                    panic!("should have been removed during expansion")
                 }
-            }
-            CanonicalFuncKind::ResourceRep(info) => {
-                self.core_func_names.push(name);
-                self.funcs.resource_rep(info.ty.into());
-            }
-            CanonicalFuncKind::ThreadSpawn(info) => {
-                self.core_func_names.push(name);
-                self.funcs.thread_spawn(info.ty.into());
-            }
-            CanonicalFuncKind::ThreadAvailableParallelism(_info) => {
-                self.core_func_names.push(name);
-                self.funcs.thread_available_parallelism();
-            }
-            CanonicalFuncKind::BackpressureSet => {
-                self.core_func_names.push(name);
-                self.funcs.backpressure_set();
-            }
-            CanonicalFuncKind::TaskReturn(info) => {
-                self.core_func_names.push(name);
-                self.funcs.task_return(
-                    info.result
-                        .as_ref()
-                        .map(|ty| wasm_encoder::ComponentValType::from(ty)),
-                    info.opts.iter().map(Into::into),
-                );
-            }
-            CanonicalFuncKind::Yield(info) => {
-                self.core_func_names.push(name);
-                self.funcs.yield_(info.async_);
-            }
-            CanonicalFuncKind::SubtaskDrop => {
-                self.core_func_names.push(name);
-                self.funcs.subtask_drop();
-            }
-            CanonicalFuncKind::StreamNew(info) => {
-                self.core_func_names.push(name);
-                self.funcs.stream_new(info.ty.into());
-            }
-            CanonicalFuncKind::StreamRead(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .stream_read(info.ty.into(), info.opts.iter().map(Into::into));
-            }
-            CanonicalFuncKind::StreamWrite(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .stream_write(info.ty.into(), info.opts.iter().map(Into::into));
-            }
-            CanonicalFuncKind::StreamCancelRead(info) => {
-                self.core_func_names.push(name);
-                self.funcs.stream_cancel_read(info.ty.into(), info.async_);
-            }
-            CanonicalFuncKind::StreamCancelWrite(info) => {
-                self.core_func_names.push(name);
-                self.funcs.stream_cancel_write(info.ty.into(), info.async_);
-            }
-            CanonicalFuncKind::StreamCloseReadable(info) => {
-                self.core_func_names.push(name);
-                self.funcs.stream_close_readable(info.ty.into());
-            }
-            CanonicalFuncKind::StreamCloseWritable(info) => {
-                self.core_func_names.push(name);
-                self.funcs.stream_close_writable(info.ty.into());
-            }
-            CanonicalFuncKind::FutureNew(info) => {
-                self.core_func_names.push(name);
-                self.funcs.future_new(info.ty.into());
-            }
-            CanonicalFuncKind::FutureRead(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .future_read(info.ty.into(), info.opts.iter().map(Into::into));
-            }
-            CanonicalFuncKind::FutureWrite(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .future_write(info.ty.into(), info.opts.iter().map(Into::into));
-            }
-            CanonicalFuncKind::FutureCancelRead(info) => {
-                self.core_func_names.push(name);
-                self.funcs.future_cancel_read(info.ty.into(), info.async_);
-            }
-            CanonicalFuncKind::FutureCancelWrite(info) => {
-                self.core_func_names.push(name);
-                self.funcs.future_cancel_write(info.ty.into(), info.async_);
-            }
-            CanonicalFuncKind::FutureCloseReadable(info) => {
-                self.core_func_names.push(name);
-                self.funcs.future_close_readable(info.ty.into());
-            }
-            CanonicalFuncKind::FutureCloseWritable(info) => {
-                self.core_func_names.push(name);
-                self.funcs.future_close_writable(info.ty.into());
-            }
-            CanonicalFuncKind::ErrorContextNew(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .error_context_new(info.opts.iter().map(Into::into));
-            }
-            CanonicalFuncKind::ErrorContextDebugMessage(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .error_context_debug_message(info.opts.iter().map(Into::into));
-            }
-            CanonicalFuncKind::ErrorContextDrop => {
-                self.core_func_names.push(name);
-                self.funcs.error_context_drop();
-            }
-            CanonicalFuncKind::WaitableSetNew => {
-                self.core_func_names.push(name);
-                self.funcs.waitable_set_new();
-            }
-            CanonicalFuncKind::WaitableSetWait(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .waitable_set_wait(info.async_, info.memory.idx.into());
-            }
-            CanonicalFuncKind::WaitableSetPoll(info) => {
-                self.core_func_names.push(name);
-                self.funcs
-                    .waitable_set_poll(info.async_, info.memory.idx.into());
-            }
-            CanonicalFuncKind::WaitableSetDrop => {
-                self.core_func_names.push(name);
-                self.funcs.waitable_set_drop();
-            }
-            CanonicalFuncKind::WaitableJoin => {
-                self.core_func_names.push(name);
-                self.funcs.waitable_join();
-            }
+                CoreFuncKind::Lower(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .lower(info.func.idx.into(), info.opts.iter().map(Into::into));
+                }
+                CoreFuncKind::ResourceNew(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.resource_new(info.ty.into());
+                }
+                CoreFuncKind::ResourceDrop(info) => {
+                    self.core_func_names.push(name);
+                    if info.async_ {
+                        self.funcs.resource_drop_async(info.ty.into());
+                    } else {
+                        self.funcs.resource_drop(info.ty.into());
+                    }
+                }
+                CoreFuncKind::ResourceRep(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.resource_rep(info.ty.into());
+                }
+                CoreFuncKind::ThreadSpawn(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.thread_spawn(info.ty.into());
+                }
+                CoreFuncKind::ThreadAvailableParallelism(_info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.thread_available_parallelism();
+                }
+                CoreFuncKind::BackpressureSet => {
+                    self.core_func_names.push(name);
+                    self.funcs.backpressure_set();
+                }
+                CoreFuncKind::TaskReturn(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.task_return(
+                        info.result
+                            .as_ref()
+                            .map(|ty| wasm_encoder::ComponentValType::from(ty)),
+                        info.opts.iter().map(Into::into),
+                    );
+                }
+                CoreFuncKind::Yield(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.yield_(info.async_);
+                }
+                CoreFuncKind::SubtaskDrop => {
+                    self.core_func_names.push(name);
+                    self.funcs.subtask_drop();
+                }
+                CoreFuncKind::StreamNew(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.stream_new(info.ty.into());
+                }
+                CoreFuncKind::StreamRead(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .stream_read(info.ty.into(), info.opts.iter().map(Into::into));
+                }
+                CoreFuncKind::StreamWrite(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .stream_write(info.ty.into(), info.opts.iter().map(Into::into));
+                }
+                CoreFuncKind::StreamCancelRead(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.stream_cancel_read(info.ty.into(), info.async_);
+                }
+                CoreFuncKind::StreamCancelWrite(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.stream_cancel_write(info.ty.into(), info.async_);
+                }
+                CoreFuncKind::StreamCloseReadable(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.stream_close_readable(info.ty.into());
+                }
+                CoreFuncKind::StreamCloseWritable(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.stream_close_writable(info.ty.into());
+                }
+                CoreFuncKind::FutureNew(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.future_new(info.ty.into());
+                }
+                CoreFuncKind::FutureRead(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .future_read(info.ty.into(), info.opts.iter().map(Into::into));
+                }
+                CoreFuncKind::FutureWrite(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .future_write(info.ty.into(), info.opts.iter().map(Into::into));
+                }
+                CoreFuncKind::FutureCancelRead(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.future_cancel_read(info.ty.into(), info.async_);
+                }
+                CoreFuncKind::FutureCancelWrite(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.future_cancel_write(info.ty.into(), info.async_);
+                }
+                CoreFuncKind::FutureCloseReadable(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.future_close_readable(info.ty.into());
+                }
+                CoreFuncKind::FutureCloseWritable(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs.future_close_writable(info.ty.into());
+                }
+                CoreFuncKind::ErrorContextNew(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .error_context_new(info.opts.iter().map(Into::into));
+                }
+                CoreFuncKind::ErrorContextDebugMessage(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .error_context_debug_message(info.opts.iter().map(Into::into));
+                }
+                CoreFuncKind::ErrorContextDrop => {
+                    self.core_func_names.push(name);
+                    self.funcs.error_context_drop();
+                }
+                CoreFuncKind::WaitableSetNew => {
+                    self.core_func_names.push(name);
+                    self.funcs.waitable_set_new();
+                }
+                CoreFuncKind::WaitableSetWait(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .waitable_set_wait(info.async_, info.memory.idx.into());
+                }
+                CoreFuncKind::WaitableSetPoll(info) => {
+                    self.core_func_names.push(name);
+                    self.funcs
+                        .waitable_set_poll(info.async_, info.memory.idx.into());
+                }
+                CoreFuncKind::WaitableSetDrop => {
+                    self.core_func_names.push(name);
+                    self.funcs.waitable_set_drop();
+                }
+                CoreFuncKind::WaitableJoin => {
+                    self.core_func_names.push(name);
+                    self.funcs.waitable_join();
+                }
+            },
         }
 
         self.flush(Some(self.funcs.id()));
diff --git a/crates/wast/src/component/component.rs b/crates/wast/src/component/component.rs
index 30f60154..f55de4e3 100644
--- a/crates/wast/src/component/component.rs
+++ b/crates/wast/src/component/component.rs
@@ -216,6 +216,9 @@ impl<'a> Parse<'a> for ComponentField<'a> {
             if parser.peek::<kw::start>()? {
                 return Ok(Self::Start(parser.parse()?));
             }
+            if parser.peek::<kw::canon>()? {
+                return Ok(Self::CanonicalFunc(parser.parse()?));
+            }
             if parser.peek::<annotation::custom>()? {
                 return Ok(Self::Custom(parser.parse()?));
             }
diff --git a/crates/wast/src/component/expand.rs b/crates/wast/src/component/expand.rs
index 30e65117..01b00d70 100644
--- a/crates/wast/src/component/expand.rs
+++ b/crates/wast/src/component/expand.rs
@@ -264,7 +264,7 @@ impl<'a> Expander<'a> {
             CanonicalFuncKind::Lift { ty, .. } => {
                 self.expand_component_type_use(ty);
             }
-            _ => {}
+            CanonicalFuncKind::Core(_) => {}
         }
     }
 
@@ -280,209 +280,11 @@ impl<'a> Expander<'a> {
                     kind: core::ExportKind::Func,
                 },
             }),
-            CoreFuncKind::Lower(info) => ComponentField::CanonicalFunc(CanonicalFunc {
+            other => ComponentField::CanonicalFunc(CanonicalFunc {
                 span: func.span,
                 id: func.id,
                 name: func.name,
-                kind: CanonicalFuncKind::Lower(info),
-            }),
-            CoreFuncKind::ResourceNew(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::ResourceNew(info),
-            }),
-            CoreFuncKind::ResourceDrop(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::ResourceDrop(info),
-            }),
-            CoreFuncKind::ResourceRep(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::ResourceRep(info),
-            }),
-            CoreFuncKind::ThreadSpawn(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::ThreadSpawn(info),
-            }),
-            CoreFuncKind::ThreadAvailableParallelism(info) => {
-                ComponentField::CanonicalFunc(CanonicalFunc {
-                    span: func.span,
-                    id: func.id,
-                    name: func.name,
-                    kind: CanonicalFuncKind::ThreadAvailableParallelism(info),
-                })
-            }
-            CoreFuncKind::BackpressureSet => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::BackpressureSet,
-            }),
-            CoreFuncKind::TaskReturn(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::TaskReturn(info),
-            }),
-            CoreFuncKind::Yield(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::Yield(info),
-            }),
-            CoreFuncKind::SubtaskDrop => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::SubtaskDrop,
-            }),
-            CoreFuncKind::StreamNew(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::StreamNew(info),
-            }),
-            CoreFuncKind::StreamRead(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::StreamRead(info),
-            }),
-            CoreFuncKind::StreamWrite(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::StreamWrite(info),
-            }),
-            CoreFuncKind::StreamCancelRead(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::StreamCancelRead(info),
-            }),
-            CoreFuncKind::StreamCancelWrite(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::StreamCancelWrite(info),
-            }),
-            CoreFuncKind::StreamCloseReadable(info) => {
-                ComponentField::CanonicalFunc(CanonicalFunc {
-                    span: func.span,
-                    id: func.id,
-                    name: func.name,
-                    kind: CanonicalFuncKind::StreamCloseReadable(info),
-                })
-            }
-            CoreFuncKind::StreamCloseWritable(info) => {
-                ComponentField::CanonicalFunc(CanonicalFunc {
-                    span: func.span,
-                    id: func.id,
-                    name: func.name,
-                    kind: CanonicalFuncKind::StreamCloseWritable(info),
-                })
-            }
-            CoreFuncKind::FutureNew(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::FutureNew(info),
-            }),
-            CoreFuncKind::FutureRead(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::FutureRead(info),
-            }),
-            CoreFuncKind::FutureWrite(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::FutureWrite(info),
-            }),
-            CoreFuncKind::FutureCancelRead(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::FutureCancelRead(info),
-            }),
-            CoreFuncKind::FutureCancelWrite(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::FutureCancelWrite(info),
-            }),
-            CoreFuncKind::FutureCloseReadable(info) => {
-                ComponentField::CanonicalFunc(CanonicalFunc {
-                    span: func.span,
-                    id: func.id,
-                    name: func.name,
-                    kind: CanonicalFuncKind::FutureCloseReadable(info),
-                })
-            }
-            CoreFuncKind::FutureCloseWritable(info) => {
-                ComponentField::CanonicalFunc(CanonicalFunc {
-                    span: func.span,
-                    id: func.id,
-                    name: func.name,
-                    kind: CanonicalFuncKind::FutureCloseWritable(info),
-                })
-            }
-            CoreFuncKind::ErrorContextNew(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::ErrorContextNew(info),
-            }),
-            CoreFuncKind::ErrorContextDebugMessage(info) => {
-                ComponentField::CanonicalFunc(CanonicalFunc {
-                    span: func.span,
-                    id: func.id,
-                    name: func.name,
-                    kind: CanonicalFuncKind::ErrorContextDebugMessage(info),
-                })
-            }
-            CoreFuncKind::ErrorContextDrop => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::ErrorContextDrop,
-            }),
-            CoreFuncKind::WaitableSetNew => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::WaitableSetNew,
-            }),
-            CoreFuncKind::WaitableSetWait(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::WaitableSetWait(info),
-            }),
-            CoreFuncKind::WaitableSetPoll(info) => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::WaitableSetPoll(info),
-            }),
-            CoreFuncKind::WaitableSetDrop => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::WaitableSetDrop,
-            }),
-            CoreFuncKind::WaitableJoin => ComponentField::CanonicalFunc(CanonicalFunc {
-                span: func.span,
-                id: func.id,
-                name: func.name,
-                kind: CanonicalFuncKind::WaitableJoin,
+                kind: CanonicalFuncKind::Core(other),
             }),
         }
     }
diff --git a/crates/wast/src/component/func.rs b/crates/wast/src/component/func.rs
index 680f7e06..c5244754 100644
--- a/crates/wast/src/component/func.rs
+++ b/crates/wast/src/component/func.rs
@@ -1,6 +1,6 @@
 use crate::component::*;
 use crate::kw;
-use crate::parser::{Parse, Parser, Result};
+use crate::parser::{Cursor, Lookahead1, Parse, Parser, Peek, Result};
 use crate::token::{Id, Index, LParen, NameAnnotation, Span};
 
 /// A declared core function.
@@ -25,7 +25,7 @@ impl<'a> Parse<'a> for CoreFunc<'a> {
         parser.parse::<kw::func>()?;
         let id = parser.parse()?;
         let name = parser.parse()?;
-        let kind = parser.parse()?;
+        let kind = parser.parens(|p| p.parse())?;
 
         Ok(Self {
             span,
@@ -83,90 +83,95 @@ pub enum CoreFuncKind<'a> {
 
 impl<'a> Parse<'a> for CoreFuncKind<'a> {
     fn parse(parser: Parser<'a>) -> Result<Self> {
-        parser.parens(|parser| {
-            let mut l = parser.lookahead1();
-            if l.peek::<kw::canon>()? {
-                parser.parse::<kw::canon>()?;
-            } else if l.peek::<kw::alias>()? {
-                return Ok(Self::Alias(parser.parse()?));
-            } else {
-                return Err(l.error());
-            }
-            let mut l = parser.lookahead1();
-            if l.peek::<kw::lower>()? {
-                Ok(CoreFuncKind::Lower(parser.parse()?))
-            } else if l.peek::<kw::resource_new>()? {
-                Ok(CoreFuncKind::ResourceNew(parser.parse()?))
-            } else if l.peek::<kw::resource_drop>()? {
-                Ok(CoreFuncKind::ResourceDrop(parser.parse()?))
-            } else if l.peek::<kw::resource_rep>()? {
-                Ok(CoreFuncKind::ResourceRep(parser.parse()?))
-            } else if l.peek::<kw::thread_spawn>()? {
-                Ok(CoreFuncKind::ThreadSpawn(parser.parse()?))
-            } else if l.peek::<kw::thread_available_parallelism>()? {
-                Ok(CoreFuncKind::ThreadAvailableParallelism(parser.parse()?))
-            } else if l.peek::<kw::backpressure_set>()? {
-                parser.parse::<kw::backpressure_set>()?;
-                Ok(CoreFuncKind::BackpressureSet)
-            } else if l.peek::<kw::task_return>()? {
-                Ok(CoreFuncKind::TaskReturn(parser.parse()?))
-            } else if l.peek::<kw::yield_>()? {
-                Ok(CoreFuncKind::Yield(parser.parse()?))
-            } else if l.peek::<kw::subtask_drop>()? {
-                parser.parse::<kw::subtask_drop>()?;
-                Ok(CoreFuncKind::SubtaskDrop)
-            } else if l.peek::<kw::stream_new>()? {
-                Ok(CoreFuncKind::StreamNew(parser.parse()?))
-            } else if l.peek::<kw::stream_read>()? {
-                Ok(CoreFuncKind::StreamRead(parser.parse()?))
-            } else if l.peek::<kw::stream_write>()? {
-                Ok(CoreFuncKind::StreamWrite(parser.parse()?))
-            } else if l.peek::<kw::stream_cancel_read>()? {
-                Ok(CoreFuncKind::StreamCancelRead(parser.parse()?))
-            } else if l.peek::<kw::stream_cancel_write>()? {
-                Ok(CoreFuncKind::StreamCancelWrite(parser.parse()?))
-            } else if l.peek::<kw::stream_close_readable>()? {
-                Ok(CoreFuncKind::StreamCloseReadable(parser.parse()?))
-            } else if l.peek::<kw::stream_close_writable>()? {
-                Ok(CoreFuncKind::StreamCloseWritable(parser.parse()?))
-            } else if l.peek::<kw::future_new>()? {
-                Ok(CoreFuncKind::FutureNew(parser.parse()?))
-            } else if l.peek::<kw::future_read>()? {
-                Ok(CoreFuncKind::FutureRead(parser.parse()?))
-            } else if l.peek::<kw::future_write>()? {
-                Ok(CoreFuncKind::FutureWrite(parser.parse()?))
-            } else if l.peek::<kw::future_cancel_read>()? {
-                Ok(CoreFuncKind::FutureCancelRead(parser.parse()?))
-            } else if l.peek::<kw::future_cancel_write>()? {
-                Ok(CoreFuncKind::FutureCancelWrite(parser.parse()?))
-            } else if l.peek::<kw::future_close_readable>()? {
-                Ok(CoreFuncKind::FutureCloseReadable(parser.parse()?))
-            } else if l.peek::<kw::future_close_writable>()? {
-                Ok(CoreFuncKind::FutureCloseWritable(parser.parse()?))
-            } else if l.peek::<kw::error_context_new>()? {
-                Ok(CoreFuncKind::ErrorContextNew(parser.parse()?))
-            } else if l.peek::<kw::error_context_debug_message>()? {
-                Ok(CoreFuncKind::ErrorContextDebugMessage(parser.parse()?))
-            } else if l.peek::<kw::error_context_drop>()? {
-                parser.parse::<kw::error_context_drop>()?;
-                Ok(CoreFuncKind::ErrorContextDrop)
-            } else if l.peek::<kw::waitable_set_new>()? {
-                parser.parse::<kw::waitable_set_new>()?;
-                Ok(CoreFuncKind::WaitableSetNew)
-            } else if l.peek::<kw::waitable_set_wait>()? {
-                Ok(CoreFuncKind::WaitableSetWait(parser.parse()?))
-            } else if l.peek::<kw::waitable_set_poll>()? {
-                Ok(CoreFuncKind::WaitableSetPoll(parser.parse()?))
-            } else if l.peek::<kw::waitable_set_drop>()? {
-                parser.parse::<kw::waitable_set_drop>()?;
-                Ok(CoreFuncKind::WaitableSetDrop)
-            } else if l.peek::<kw::waitable_join>()? {
-                parser.parse::<kw::waitable_join>()?;
-                Ok(CoreFuncKind::WaitableJoin)
-            } else {
-                Err(l.error())
-            }
-        })
+        let mut l = parser.lookahead1();
+        if l.peek::<kw::canon>()? {
+            parser.parse::<kw::canon>()?;
+        } else if l.peek::<kw::alias>()? {
+            return Ok(Self::Alias(parser.parse()?));
+        } else {
+            return Err(l.error());
+        }
+
+        CoreFuncKind::parse_lookahead(parser.lookahead1())
+    }
+}
+
+impl<'a> CoreFuncKind<'a> {
+    fn parse_lookahead(mut l: Lookahead1<'a>) -> Result<CoreFuncKind<'a>> {
+        let parser = l.parser();
+        if l.peek::<kw::lower>()? {
+            Ok(CoreFuncKind::Lower(parser.parse()?))
+        } else if l.peek::<kw::resource_new>()? {
+            Ok(CoreFuncKind::ResourceNew(parser.parse()?))
+        } else if l.peek::<kw::resource_drop>()? {
+            Ok(CoreFuncKind::ResourceDrop(parser.parse()?))
+        } else if l.peek::<kw::resource_rep>()? {
+            Ok(CoreFuncKind::ResourceRep(parser.parse()?))
+        } else if l.peek::<kw::thread_spawn>()? {
+            Ok(CoreFuncKind::ThreadSpawn(parser.parse()?))
+        } else if l.peek::<kw::thread_available_parallelism>()? {
+            Ok(CoreFuncKind::ThreadAvailableParallelism(parser.parse()?))
+        } else if l.peek::<kw::backpressure_set>()? {
+            parser.parse::<kw::backpressure_set>()?;
+            Ok(CoreFuncKind::BackpressureSet)
+        } else if l.peek::<kw::task_return>()? {
+            Ok(CoreFuncKind::TaskReturn(parser.parse()?))
+        } else if l.peek::<kw::yield_>()? {
+            Ok(CoreFuncKind::Yield(parser.parse()?))
+        } else if l.peek::<kw::subtask_drop>()? {
+            parser.parse::<kw::subtask_drop>()?;
+            Ok(CoreFuncKind::SubtaskDrop)
+        } else if l.peek::<kw::stream_new>()? {
+            Ok(CoreFuncKind::StreamNew(parser.parse()?))
+        } else if l.peek::<kw::stream_read>()? {
+            Ok(CoreFuncKind::StreamRead(parser.parse()?))
+        } else if l.peek::<kw::stream_write>()? {
+            Ok(CoreFuncKind::StreamWrite(parser.parse()?))
+        } else if l.peek::<kw::stream_cancel_read>()? {
+            Ok(CoreFuncKind::StreamCancelRead(parser.parse()?))
+        } else if l.peek::<kw::stream_cancel_write>()? {
+            Ok(CoreFuncKind::StreamCancelWrite(parser.parse()?))
+        } else if l.peek::<kw::stream_close_readable>()? {
+            Ok(CoreFuncKind::StreamCloseReadable(parser.parse()?))
+        } else if l.peek::<kw::stream_close_writable>()? {
+            Ok(CoreFuncKind::StreamCloseWritable(parser.parse()?))
+        } else if l.peek::<kw::future_new>()? {
+            Ok(CoreFuncKind::FutureNew(parser.parse()?))
+        } else if l.peek::<kw::future_read>()? {
+            Ok(CoreFuncKind::FutureRead(parser.parse()?))
+        } else if l.peek::<kw::future_write>()? {
+            Ok(CoreFuncKind::FutureWrite(parser.parse()?))
+        } else if l.peek::<kw::future_cancel_read>()? {
+            Ok(CoreFuncKind::FutureCancelRead(parser.parse()?))
+        } else if l.peek::<kw::future_cancel_write>()? {
+            Ok(CoreFuncKind::FutureCancelWrite(parser.parse()?))
+        } else if l.peek::<kw::future_close_readable>()? {
+            Ok(CoreFuncKind::FutureCloseReadable(parser.parse()?))
+        } else if l.peek::<kw::future_close_writable>()? {
+            Ok(CoreFuncKind::FutureCloseWritable(parser.parse()?))
+        } else if l.peek::<kw::error_context_new>()? {
+            Ok(CoreFuncKind::ErrorContextNew(parser.parse()?))
+        } else if l.peek::<kw::error_context_debug_message>()? {
+            Ok(CoreFuncKind::ErrorContextDebugMessage(parser.parse()?))
+        } else if l.peek::<kw::error_context_drop>()? {
+            parser.parse::<kw::error_context_drop>()?;
+            Ok(CoreFuncKind::ErrorContextDrop)
+        } else if l.peek::<kw::waitable_set_new>()? {
+            parser.parse::<kw::waitable_set_new>()?;
+            Ok(CoreFuncKind::WaitableSetNew)
+        } else if l.peek::<kw::waitable_set_wait>()? {
+            Ok(CoreFuncKind::WaitableSetWait(parser.parse()?))
+        } else if l.peek::<kw::waitable_set_poll>()? {
+            Ok(CoreFuncKind::WaitableSetPoll(parser.parse()?))
+        } else if l.peek::<kw::waitable_set_drop>()? {
+            parser.parse::<kw::waitable_set_drop>()?;
+            Ok(CoreFuncKind::WaitableSetDrop)
+        } else if l.peek::<kw::waitable_join>()? {
+            parser.parse::<kw::waitable_join>()?;
+            Ok(CoreFuncKind::WaitableJoin)
+        } else {
+            Err(l.error())
+        }
     }
 }
 
@@ -276,8 +281,9 @@ pub struct CanonicalFunc<'a> {
 impl<'a> Parse<'a> for CanonicalFunc<'a> {
     fn parse(parser: Parser<'a>) -> Result<Self> {
         let span = parser.parse::<kw::canon>()?.0;
+        let mut l = parser.lookahead1();
 
-        if parser.peek::<kw::lift>()? {
+        if l.peek::<kw::lift>()? {
             let info = parser.parse()?;
             let (id, name, ty) = parser.parens(|parser| {
                 parser.parse::<kw::func>()?;
@@ -293,44 +299,23 @@ impl<'a> Parse<'a> for CanonicalFunc<'a> {
                 name,
                 kind: CanonicalFuncKind::Lift { info, ty },
             })
-        } else if parser.peek::<kw::lower>()? {
-            Self::parse_core_func(span, parser, CanonicalFuncKind::Lower)
-        } else if parser.peek::<kw::resource_new>()? {
-            Self::parse_core_func(span, parser, CanonicalFuncKind::ResourceNew)
-        } else if parser.peek::<kw::resource_drop>()? {
-            Self::parse_core_func(span, parser, CanonicalFuncKind::ResourceDrop)
-        } else if parser.peek::<kw::resource_rep>()? {
-            Self::parse_core_func(span, parser, CanonicalFuncKind::ResourceRep)
         } else {
-            Err(parser.error("expected `canon lift` or `canon lower`"))
-        }
-    }
-}
-
-impl<'a> CanonicalFunc<'a> {
-    fn parse_core_func<T>(
-        span: Span,
-        parser: Parser<'a>,
-        variant: fn(T) -> CanonicalFuncKind<'a>,
-    ) -> Result<Self>
-    where
-        T: Parse<'a>,
-    {
-        let info = parser.parse()?;
-        let (id, name) = parser.parens(|parser| {
-            parser.parse::<kw::core>()?;
-            parser.parse::<kw::func>()?;
-            let id = parser.parse()?;
-            let name = parser.parse()?;
-            Ok((id, name))
-        })?;
+            let kind = CoreFuncKind::parse_lookahead(l)?;
+            let (id, name) = parser.parens(|parser| {
+                parser.parse::<kw::core>()?;
+                parser.parse::<kw::func>()?;
+                let id = parser.parse()?;
+                let name = parser.parse()?;
+                Ok((id, name))
+            })?;
 
-        Ok(Self {
-            span,
-            id,
-            name,
-            kind: variant(info),
-        })
+            Ok(Self {
+                span,
+                id,
+                name,
+                kind: CanonicalFuncKind::Core(kind),
+            })
+        }
     }
 }
 
@@ -345,42 +330,10 @@ pub enum CanonicalFuncKind<'a> {
         /// Information relating to the lifting of the core function.
         info: CanonLift<'a>,
     },
-    /// A canonical function that is defined in terms of lowering a component function.
-    Lower(CanonLower<'a>),
-
-    ResourceNew(CanonResourceNew<'a>),
-    ResourceDrop(CanonResourceDrop<'a>),
-    ResourceRep(CanonResourceRep<'a>),
 
-    ThreadSpawn(CanonThreadSpawn<'a>),
-    ThreadAvailableParallelism(CanonThreadAvailableParallelism),
-
-    BackpressureSet,
-    TaskReturn(CanonTaskReturn<'a>),
-    Yield(CanonYield),
-    SubtaskDrop,
-    StreamNew(CanonStreamNew<'a>),
-    StreamRead(CanonStreamRead<'a>),
-    StreamWrite(CanonStreamWrite<'a>),
-    StreamCancelRead(CanonStreamCancelRead<'a>),
-    StreamCancelWrite(CanonStreamCancelWrite<'a>),
-    StreamCloseReadable(CanonStreamCloseReadable<'a>),
-    StreamCloseWritable(CanonStreamCloseWritable<'a>),
-    FutureNew(CanonFutureNew<'a>),
-    FutureRead(CanonFutureRead<'a>),
-    FutureWrite(CanonFutureWrite<'a>),
-    FutureCancelRead(CanonFutureCancelRead<'a>),
-    FutureCancelWrite(CanonFutureCancelWrite<'a>),
-    FutureCloseReadable(CanonFutureCloseReadable<'a>),
-    FutureCloseWritable(CanonFutureCloseWritable<'a>),
-    ErrorContextNew(CanonErrorContextNew<'a>),
-    ErrorContextDebugMessage(CanonErrorContextDebugMessage<'a>),
-    ErrorContextDrop,
-    WaitableSetNew,
-    WaitableSetWait(CanonWaitableSetWait<'a>),
-    WaitableSetPoll(CanonWaitableSetPoll<'a>),
-    WaitableSetDrop,
-    WaitableJoin,
+    /// A canonical function that defines a core function, whose variants are
+    /// delegated to `CoreFuncKind`.
+    Core(CoreFuncKind<'a>),
 }
 
 /// Information relating to lifting a core function.
@@ -996,6 +949,28 @@ impl<'a> Parse<'a> for CanonOpt<'a> {
     }
 }
 
+impl Peek for CanonOpt<'_> {
+    fn peek(cursor: Cursor<'_>) -> Result<bool> {
+        Ok(kw::string_utf8::peek(cursor)?
+            || kw::string_utf16::peek(cursor)?
+            || kw::string_latin1_utf16::peek(cursor)?
+            || kw::r#async::peek(cursor)?
+            || match cursor.lparen()? {
+                Some(next) => {
+                    kw::memory::peek(next)?
+                        || kw::realloc::peek(next)?
+                        || kw::post_return::peek(next)?
+                        || kw::callback::peek(next)?
+                }
+                None => false,
+            })
+    }
+
+    fn display() -> &'static str {
+        "canonical option"
+    }
+}
+
 fn parse_trailing_item_ref<T>(kind: T, parser: Parser) -> Result<CoreItemRef<T>> {
     Ok(CoreItemRef {
         kind,
@@ -1007,7 +982,7 @@ fn parse_trailing_item_ref<T>(kind: T, parser: Parser) -> Result<CoreItemRef<T>>
 impl<'a> Parse<'a> for Vec<CanonOpt<'a>> {
     fn parse(parser: Parser<'a>) -> Result<Self> {
         let mut funcs = Vec::new();
-        while !parser.is_empty() {
+        while parser.peek::<CanonOpt<'_>>()? {
             funcs.push(parser.parse()?);
         }
         Ok(funcs)
diff --git a/crates/wast/src/component/resolve.rs b/crates/wast/src/component/resolve.rs
index 916efc4e..118ae197 100644
--- a/crates/wast/src/component/resolve.rs
+++ b/crates/wast/src/component/resolve.rs
@@ -370,94 +370,99 @@ impl<'a> Resolver<'a> {
                 self.core_item_ref(&mut info.func)?;
                 self.canon_opts(&mut info.opts)?;
             }
-            CanonicalFuncKind::Lower(info) => {
-                self.component_item_ref(&mut info.func)?;
-                self.canon_opts(&mut info.opts)?;
-            }
-            CanonicalFuncKind::ResourceNew(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::ResourceRep(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::ResourceDrop(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::ThreadSpawn(info) => {
-                self.resolve_ns(&mut info.ty, Ns::CoreType)?;
-            }
-            CanonicalFuncKind::ThreadAvailableParallelism(_)
-            | CanonicalFuncKind::BackpressureSet
-            | CanonicalFuncKind::Yield(_)
-            | CanonicalFuncKind::SubtaskDrop
-            | CanonicalFuncKind::ErrorContextDrop => {}
-            CanonicalFuncKind::TaskReturn(info) => {
-                if let Some(ty) = &mut info.result {
-                    self.component_val_type(ty)?;
+            CanonicalFuncKind::Core(core) => match core {
+                CoreFuncKind::Alias(_) => {
+                    panic!("should have been removed during expansion")
                 }
-                self.canon_opts(&mut info.opts)?;
-            }
-            CanonicalFuncKind::StreamNew(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::StreamRead(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-                self.canon_opts(&mut info.opts)?;
-            }
-            CanonicalFuncKind::StreamWrite(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-                self.canon_opts(&mut info.opts)?;
-            }
-            CanonicalFuncKind::StreamCancelRead(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::StreamCancelWrite(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::StreamCloseReadable(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::StreamCloseWritable(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::FutureNew(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::FutureRead(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-                self.canon_opts(&mut info.opts)?;
-            }
-            CanonicalFuncKind::FutureWrite(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-                self.canon_opts(&mut info.opts)?;
-            }
-            CanonicalFuncKind::FutureCancelRead(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::FutureCancelWrite(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::FutureCloseReadable(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::FutureCloseWritable(info) => {
-                self.resolve_ns(&mut info.ty, Ns::Type)?;
-            }
-            CanonicalFuncKind::ErrorContextNew(info) => {
-                self.canon_opts(&mut info.opts)?;
-            }
-            CanonicalFuncKind::ErrorContextDebugMessage(info) => {
-                self.canon_opts(&mut info.opts)?;
-            }
-            CanonicalFuncKind::WaitableSetNew => {}
-            CanonicalFuncKind::WaitableSetWait(info) => {
-                self.core_item_ref(&mut info.memory)?;
-            }
-            CanonicalFuncKind::WaitableSetPoll(info) => {
-                self.core_item_ref(&mut info.memory)?;
-            }
-            CanonicalFuncKind::WaitableSetDrop => {}
-            CanonicalFuncKind::WaitableJoin => {}
+                CoreFuncKind::Lower(info) => {
+                    self.component_item_ref(&mut info.func)?;
+                    self.canon_opts(&mut info.opts)?;
+                }
+                CoreFuncKind::ResourceNew(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::ResourceRep(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::ResourceDrop(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::ThreadSpawn(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::CoreType)?;
+                }
+                CoreFuncKind::ThreadAvailableParallelism(_)
+                | CoreFuncKind::BackpressureSet
+                | CoreFuncKind::Yield(_)
+                | CoreFuncKind::SubtaskDrop
+                | CoreFuncKind::ErrorContextDrop => {}
+                CoreFuncKind::TaskReturn(info) => {
+                    if let Some(ty) = &mut info.result {
+                        self.component_val_type(ty)?;
+                    }
+                    self.canon_opts(&mut info.opts)?;
+                }
+                CoreFuncKind::StreamNew(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::StreamRead(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                    self.canon_opts(&mut info.opts)?;
+                }
+                CoreFuncKind::StreamWrite(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                    self.canon_opts(&mut info.opts)?;
+                }
+                CoreFuncKind::StreamCancelRead(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::StreamCancelWrite(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::StreamCloseReadable(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::StreamCloseWritable(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::FutureNew(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::FutureRead(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                    self.canon_opts(&mut info.opts)?;
+                }
+                CoreFuncKind::FutureWrite(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                    self.canon_opts(&mut info.opts)?;
+                }
+                CoreFuncKind::FutureCancelRead(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::FutureCancelWrite(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::FutureCloseReadable(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::FutureCloseWritable(info) => {
+                    self.resolve_ns(&mut info.ty, Ns::Type)?;
+                }
+                CoreFuncKind::ErrorContextNew(info) => {
+                    self.canon_opts(&mut info.opts)?;
+                }
+                CoreFuncKind::ErrorContextDebugMessage(info) => {
+                    self.canon_opts(&mut info.opts)?;
+                }
+                CoreFuncKind::WaitableSetNew => {}
+                CoreFuncKind::WaitableSetWait(info) => {
+                    self.core_item_ref(&mut info.memory)?;
+                }
+                CoreFuncKind::WaitableSetPoll(info) => {
+                    self.core_item_ref(&mut info.memory)?;
+                }
+                CoreFuncKind::WaitableSetDrop => {}
+                CoreFuncKind::WaitableJoin => {}
+            },
         }
 
         Ok(())
@@ -963,38 +968,7 @@ impl<'a> ComponentState<'a> {
             ComponentField::Type(t) => self.types.register(t.id, "type")?,
             ComponentField::CanonicalFunc(f) => match &f.kind {
                 CanonicalFuncKind::Lift { .. } => self.funcs.register(f.id, "func")?,
-                CanonicalFuncKind::Lower(_)
-                | CanonicalFuncKind::ResourceNew(_)
-                | CanonicalFuncKind::ResourceRep(_)
-                | CanonicalFuncKind::ResourceDrop(_)
-                | CanonicalFuncKind::ThreadSpawn(_)
-                | CanonicalFuncKind::ThreadAvailableParallelism(_)
-                | CanonicalFuncKind::BackpressureSet
-                | CanonicalFuncKind::TaskReturn(_)
-                | CanonicalFuncKind::Yield(_)
-                | CanonicalFuncKind::SubtaskDrop
-                | CanonicalFuncKind::StreamNew(_)
-                | CanonicalFuncKind::StreamRead(_)
-                | CanonicalFuncKind::StreamWrite(_)
-                | CanonicalFuncKind::StreamCancelRead(_)
-                | CanonicalFuncKind::StreamCancelWrite(_)
-                | CanonicalFuncKind::StreamCloseReadable(_)
-                | CanonicalFuncKind::StreamCloseWritable(_)
-                | CanonicalFuncKind::FutureNew(_)
-                | CanonicalFuncKind::FutureRead(_)
-                | CanonicalFuncKind::FutureWrite(_)
-                | CanonicalFuncKind::FutureCancelRead(_)
-                | CanonicalFuncKind::FutureCancelWrite(_)
-                | CanonicalFuncKind::FutureCloseReadable(_)
-                | CanonicalFuncKind::FutureCloseWritable(_)
-                | CanonicalFuncKind::ErrorContextNew(_)
-                | CanonicalFuncKind::ErrorContextDebugMessage(_)
-                | CanonicalFuncKind::ErrorContextDrop
-                | CanonicalFuncKind::WaitableSetNew
-                | CanonicalFuncKind::WaitableSetWait(_)
-                | CanonicalFuncKind::WaitableSetPoll(_)
-                | CanonicalFuncKind::WaitableSetDrop
-                | CanonicalFuncKind::WaitableJoin => self.core_funcs.register(f.id, "core func")?,
+                CanonicalFuncKind::Core(_) => self.core_funcs.register(f.id, "core func")?,
             },
             ComponentField::CoreFunc(_) | ComponentField::Func(_) => {
                 unreachable!("should be expanded already")
diff --git a/crates/wast/src/parser.rs b/crates/wast/src/parser.rs
index 8af05833..eab0df56 100644
--- a/crates/wast/src/parser.rs
+++ b/crates/wast/src/parser.rs
@@ -1388,7 +1388,7 @@ impl<'a> Cursor<'a> {
     }
 }
 
-impl Lookahead1<'_> {
+impl<'a> Lookahead1<'a> {
     /// Attempts to see if `T` is the next token in the [`Parser`] this
     /// [`Lookahead1`] references.
     ///
@@ -1402,6 +1402,11 @@ impl Lookahead1<'_> {
         })
     }
 
+    /// Returns the underlying parser that this lookahead is looking at.
+    pub fn parser(&self) -> Parser<'a> {
+        self.parser
+    }
+
     /// Generates an error message saying that one of the tokens passed to
     /// [`Lookahead1::peek`] method was expected.
     ///
diff --git a/crates/wit-component/src/validation.rs b/crates/wit-component/src/validation.rs
index aeb62614..c78ff8c5 100644
--- a/crates/wit-component/src/validation.rs
+++ b/crates/wit-component/src/validation.rs
@@ -888,7 +888,7 @@ impl ImportMap {
             if async_ {
                 bail!("async `future.close-readable` calls not supported");
             }
-            validate_func_sig(name, &FuncType::new([ValType::I32], []), ty)?;
+            validate_func_sig(name, &FuncType::new([ValType::I32; 2], []), ty)?;
             Import::FutureCloseReadable(info)
         } else if let Some(info) = prefixed_payload("[stream-new-") {
             if async_ {
@@ -918,7 +918,7 @@ impl ImportMap {
             if async_ {
                 bail!("async `stream.close-readable` calls not supported");
             }
-            validate_func_sig(name, &FuncType::new([ValType::I32], []), ty)?;
+            validate_func_sig(name, &FuncType::new([ValType::I32; 2], []), ty)?;
             Import::StreamCloseReadable(info)
         } else {
             return Ok(None);
diff --git a/crates/wit-parser/src/resolve.rs b/crates/wit-parser/src/resolve.rs
index 764d64a7..2f8de7c1 100644
--- a/crates/wit-parser/src/resolve.rs
+++ b/crates/wit-parser/src/resolve.rs
@@ -2644,7 +2644,13 @@ impl Remap {
             worlds: Default::default(),
         });
         let prev = resolve.package_names.insert(unresolved.name.clone(), pkgid);
-        assert!(prev.is_none());
+        if let Some(prev) = prev {
+            resolve.package_names.insert(unresolved.name.clone(), prev);
+            bail!(
+                "attempting to re-add package `{}` when it's already present in this `Resolve`",
+                unresolved.name,
+            );
+        }
 
         self.process_foreign_deps(resolve, pkgid, &unresolved)?;
 
diff --git a/src/bin/wasm-tools/metadata.rs b/src/bin/wasm-tools/metadata.rs
index cfa83536..364b902d 100644
--- a/src/bin/wasm-tools/metadata.rs
+++ b/src/bin/wasm-tools/metadata.rs
@@ -54,7 +54,7 @@ impl ShowOpts {
         if self.json {
             write!(output, "{}", serde_json::to_string(&payload)?)?;
         } else {
-            fmt_payload(&payload, &mut output)?;
+            write_table(&payload, &mut output)?;
         }
         Ok(())
     }
@@ -89,7 +89,9 @@ impl AddOpts {
     }
 }
 
-fn fmt_payload(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
+/// Write a table containing a wasm binary's metadata to a writer
+fn write_table(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
+    // Prepare a table and get the individual metadata
     let mut table = Table::new();
     table
         .load_preset(UTF8_FULL)
@@ -110,43 +112,60 @@ fn fmt_payload(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
         version,
     } = payload.metadata();
 
-    // Print the basic information
+    // Add the basic information to the table first
     let kind = match payload {
         Payload::Component { .. } => "component",
         Payload::Module(_) => "module",
     };
     table.add_row(vec!["kind", &kind]);
-    let name = name.as_deref().unwrap_or("<unknown>");
-    table.add_row(vec!["name", &name]);
     table.add_row(vec![
         "range",
         &format!("0x{:x}..0x{:x}", range.start, range.end),
     ]);
+    let name = name.as_deref().unwrap_or("<unknown>");
+    table.add_row(vec!["name", &name]);
 
-    // Print the OCI annotations
+    // Add the OCI annotations to the table
     if let Some(description) = description {
         table.add_row(vec!["description", &description.to_string()]);
     }
-    if let Some(licenses) = licenses {
-        table.add_row(vec!["licenses", &licenses.to_string()]);
-    }
     if let Some(authors) = authors {
         table.add_row(vec!["authors", &authors.to_string()]);
     }
+    if let Some(version) = version {
+        table.add_row(vec!["version", &version.to_string()]);
+    }
+    if let Some(revision) = revision {
+        table.add_row(vec!["revision", &revision.to_string()]);
+    }
+    if let Some(licenses) = licenses {
+        table.add_row(vec!["licenses", &licenses.to_string()]);
+    }
     if let Some(source) = source {
         table.add_row(vec!["source", &source.to_string()]);
     }
     if let Some(homepage) = homepage {
         table.add_row(vec!["homepage", &homepage.to_string()]);
     }
-    if let Some(revision) = revision {
-        table.add_row(vec!["revision", &revision.to_string()]);
-    }
-    if let Some(version) = version {
-        table.add_row(vec!["version", &version.to_string()]);
-    }
 
+    // Add the producer section to the table
     if let Some(producers) = producers {
+        // Ensure the "language" fields are listed first
+        let mut producers = producers
+            .iter()
+            .map(|(n, p)| (n.clone(), p))
+            .collect::<Vec<_>>();
+        producers.sort_by(|(a, _), (b, _)| {
+            if a == "language" {
+                std::cmp::Ordering::Less
+            } else if b == "language" {
+                std::cmp::Ordering::Greater
+            } else {
+                a.cmp(b)
+            }
+        });
+
+        // Add the producers to the table
         for (name, pairs) in producers.iter() {
             for (field, version) in pairs.iter() {
                 match version.len() {
@@ -160,9 +179,10 @@ fn fmt_payload(payload: &Payload, f: &mut Box<dyn WriteColor>) -> Result<()> {
     // Write the table to the writer
     writeln!(f, "{table}")?;
 
+    // Recursively print any children
     if let Payload::Component { children, .. } = payload {
         for payload in children {
-            fmt_payload(payload, f)?;
+            write_table(payload, f)?;
         }
     }
 


Test patch:
diff --git a/crates/wit-component/tests/components/async-streams-and-futures/component.wat b/crates/wit-component/tests/components/async-streams-and-futures/component.wat
index 4e0883c6..0f3af2f0 100644
--- a/crates/wit-component/tests/components/async-streams-and-futures/component.wat
+++ b/crates/wit-component/tests/components/async-streams-and-futures/component.wat
@@ -19,9 +19,8 @@
     (type (;1;) (func (result i32)))
     (type (;2;) (func (param i32 i32 i32) (result i32)))
     (type (;3;) (func (param i32) (result i32)))
-    (type (;4;) (func (param i32)))
-    (type (;5;) (func (param i32 i32)))
-    (type (;6;) (func (param i32 i32 i32 i32) (result i32)))
+    (type (;4;) (func (param i32 i32)))
+    (type (;5;) (func (param i32 i32 i32 i32) (result i32)))
     (import "$root" "[async]foo" (func (;0;) (type 0)))
     (import "foo:foo/bar" "[async]foo" (func (;1;) (type 0)))
     (import "$root" "[stream-new-2]foo" (func (;2;) (type 1)))
@@ -30,96 +29,96 @@
     (import "$root" "[stream-cancel-read-2]foo" (func (;5;) (type 3)))
     (import "$root" "[stream-cancel-write-2]foo" (func (;6;) (type 3)))
     (import "$root" "[stream-close-readable-2]foo" (func (;7;) (type 4)))
-    (import "$root" "[stream-close-writable-2]foo" (func (;8;) (type 5)))
+    (import "$root" "[stream-close-writable-2]foo" (func (;8;) (type 4)))
     (import "foo:foo/bar" "[stream-new-2]foo" (func (;9;) (type 1)))
     (import "foo:foo/bar" "[stream-read-2]foo" (func (;10;) (type 2)))
     (import "foo:foo/bar" "[stream-write-2]foo" (func (;11;) (type 2)))
     (import "foo:foo/bar" "[stream-cancel-read-2]foo" (func (;12;) (type 3)))
     (import "foo:foo/bar" "[stream-cancel-write-2]foo" (func (;13;) (type 3)))
     (import "foo:foo/bar" "[stream-close-readable-2]foo" (func (;14;) (type 4)))
-    (import "foo:foo/bar" "[stream-close-writable-2]foo" (func (;15;) (type 5)))
+    (import "foo:foo/bar" "[stream-close-writable-2]foo" (func (;15;) (type 4)))
     (import "$root" "[future-new-0]foo" (func (;16;) (type 1)))
     (import "$root" "[future-read-0]foo" (func (;17;) (type 0)))
     (import "$root" "[future-write-0]foo" (func (;18;) (type 0)))
     (import "$root" "[future-cancel-read-0]foo" (func (;19;) (type 3)))
     (import "$root" "[future-cancel-write-0]foo" (func (;20;) (type 3)))
     (import "$root" "[future-close-readable-0]foo" (func (;21;) (type 4)))
-    (import "$root" "[future-close-writable-0]foo" (func (;22;) (type 5)))
+    (import "$root" "[future-close-writable-0]foo" (func (;22;) (type 4)))
     (import "foo:foo/bar" "[future-new-0]foo" (func (;23;) (type 1)))
     (import "foo:foo/bar" "[future-read-0]foo" (func (;24;) (type 0)))
     (import "foo:foo/bar" "[future-write-0]foo" (func (;25;) (type 0)))
     (import "foo:foo/bar" "[future-cancel-read-0]foo" (func (;26;) (type 3)))
     (import "foo:foo/bar" "[future-cancel-write-0]foo" (func (;27;) (type 3)))
     (import "foo:foo/bar" "[future-close-readable-0]foo" (func (;28;) (type 4)))
-    (import "foo:foo/bar" "[future-close-writable-0]foo" (func (;29;) (type 5)))
+    (import "foo:foo/bar" "[future-close-writable-0]foo" (func (;29;) (type 4)))
     (import "$root" "[future-new-1]foo" (func (;30;) (type 1)))
     (import "$root" "[future-read-1]foo" (func (;31;) (type 0)))
     (import "$root" "[future-write-1]foo" (func (;32;) (type 0)))
     (import "$root" "[future-cancel-read-1]foo" (func (;33;) (type 3)))
     (import "$root" "[future-cancel-write-1]foo" (func (;34;) (type 3)))
     (import "$root" "[future-close-readable-1]foo" (func (;35;) (type 4)))
-    (import "$root" "[future-close-writable-1]foo" (func (;36;) (type 5)))
+    (import "$root" "[future-close-writable-1]foo" (func (;36;) (type 4)))
     (import "foo:foo/bar" "[future-new-1]foo" (func (;37;) (type 1)))
     (import "foo:foo/bar" "[future-read-1]foo" (func (;38;) (type 0)))
     (import "foo:foo/bar" "[future-write-1]foo" (func (;39;) (type 0)))
     (import "foo:foo/bar" "[future-cancel-read-1]foo" (func (;40;) (type 3)))
     (import "foo:foo/bar" "[future-cancel-write-1]foo" (func (;41;) (type 3)))
     (import "foo:foo/bar" "[future-close-readable-1]foo" (func (;42;) (type 4)))
-    (import "foo:foo/bar" "[future-close-writable-1]foo" (func (;43;) (type 5)))
+    (import "foo:foo/bar" "[future-close-writable-1]foo" (func (;43;) (type 4)))
     (import "[export]$root" "[stream-new-2]foo" (func (;44;) (type 1)))
     (import "[export]$root" "[stream-read-2]foo" (func (;45;) (type 2)))
     (import "[export]$root" "[stream-write-2]foo" (func (;46;) (type 2)))
     (import "[export]$root" "[stream-cancel-read-2]foo" (func (;47;) (type 3)))
     (import "[export]$root" "[stream-cancel-write-2]foo" (func (;48;) (type 3)))
     (import "[export]$root" "[stream-close-readable-2]foo" (func (;49;) (type 4)))
-    (import "[export]$root" "[stream-close-writable-2]foo" (func (;50;) (type 5)))
+    (import "[export]$root" "[stream-close-writable-2]foo" (func (;50;) (type 4)))
     (import "[export]foo:foo/bar" "[stream-new-2]foo" (func (;51;) (type 1)))
     (import "[export]foo:foo/bar" "[stream-read-2]foo" (func (;52;) (type 2)))
     (import "[export]foo:foo/bar" "[stream-write-2]foo" (func (;53;) (type 2)))
     (import "[export]foo:foo/bar" "[stream-cancel-read-2]foo" (func (;54;) (type 3)))
     (import "[export]foo:foo/bar" "[stream-cancel-write-2]foo" (func (;55;) (type 3)))
     (import "[export]foo:foo/bar" "[stream-close-readable-2]foo" (func (;56;) (type 4)))
-    (import "[export]foo:foo/bar" "[stream-close-writable-2]foo" (func (;57;) (type 5)))
+    (import "[export]foo:foo/bar" "[stream-close-writable-2]foo" (func (;57;) (type 4)))
     (import "[export]$root" "[future-new-0]foo" (func (;58;) (type 1)))
     (import "[export]$root" "[future-read-0]foo" (func (;59;) (type 0)))
     (import "[export]$root" "[future-write-0]foo" (func (;60;) (type 0)))
     (import "[export]$root" "[future-cancel-read-0]foo" (func (;61;) (type 3)))
     (import "[export]$root" "[future-cancel-write-0]foo" (func (;62;) (type 3)))
     (import "[export]$root" "[future-close-readable-0]foo" (func (;63;) (type 4)))
-    (import "[export]$root" "[future-close-writable-0]foo" (func (;64;) (type 5)))
+    (import "[export]$root" "[future-close-writable-0]foo" (func (;64;) (type 4)))
     (import "[export]foo:foo/bar" "[future-new-0]foo" (func (;65;) (type 1)))
     (import "[export]foo:foo/bar" "[future-read-0]foo" (func (;66;) (type 0)))
     (import "[export]foo:foo/bar" "[future-write-0]foo" (func (;67;) (type 0)))
     (import "[export]foo:foo/bar" "[future-cancel-read-0]foo" (func (;68;) (type 3)))
     (import "[export]foo:foo/bar" "[future-cancel-write-0]foo" (func (;69;) (type 3)))
     (import "[export]foo:foo/bar" "[future-close-readable-0]foo" (func (;70;) (type 4)))
-    (import "[export]foo:foo/bar" "[future-close-writable-0]foo" (func (;71;) (type 5)))
+    (import "[export]foo:foo/bar" "[future-close-writable-0]foo" (func (;71;) (type 4)))
     (import "[export]$root" "[future-new-1]foo" (func (;72;) (type 1)))
     (import "[export]$root" "[future-read-1]foo" (func (;73;) (type 0)))
     (import "[export]$root" "[future-write-1]foo" (func (;74;) (type 0)))
     (import "[export]$root" "[future-cancel-read-1]foo" (func (;75;) (type 3)))
     (import "[export]$root" "[future-cancel-write-1]foo" (func (;76;) (type 3)))
     (import "[export]$root" "[future-close-readable-1]foo" (func (;77;) (type 4)))
-    (import "[export]$root" "[future-close-writable-1]foo" (func (;78;) (type 5)))
+    (import "[export]$root" "[future-close-writable-1]foo" (func (;78;) (type 4)))
     (import "[export]foo:foo/bar" "[future-new-1]foo" (func (;79;) (type 1)))
     (import "[export]foo:foo/bar" "[future-read-1]foo" (func (;80;) (type 0)))
     (import "[export]foo:foo/bar" "[future-write-1]foo" (func (;81;) (type 0)))
     (import "[export]foo:foo/bar" "[future-cancel-read-1]foo" (func (;82;) (type 3)))
     (import "[export]foo:foo/bar" "[future-cancel-write-1]foo" (func (;83;) (type 3)))
     (import "[export]foo:foo/bar" "[future-close-readable-1]foo" (func (;84;) (type 4)))
-    (import "[export]foo:foo/bar" "[future-close-writable-1]foo" (func (;85;) (type 5)))
+    (import "[export]foo:foo/bar" "[future-close-writable-1]foo" (func (;85;) (type 4)))
     (memory (;0;) 1)
     (export "[async-stackful]foo" (func 86))
     (export "[async-stackful]foo:foo/bar#foo" (func 87))
     (export "memory" (memory 0))
     (export "cabi_realloc" (func 88))
-    (func (;86;) (type 5) (param i32 i32)
+    (func (;86;) (type 4) (param i32 i32)
       unreachable
     )
-    (func (;87;) (type 5) (param i32 i32)
+    (func (;87;) (type 4) (param i32 i32)
       unreachable
     )
-    (func (;88;) (type 6) (param i32 i32 i32 i32) (result i32)
+    (func (;88;) (type 5) (param i32 i32 i32 i32) (result i32)
       unreachable
     )
     (@producers
diff --git a/crates/wit-component/tests/components/async-streams-and-futures/module.wat b/crates/wit-component/tests/components/async-streams-and-futures/module.wat
index 934fa4bb..952d7699 100644
--- a/crates/wit-component/tests/components/async-streams-and-futures/module.wat
+++ b/crates/wit-component/tests/components/async-streams-and-futures/module.wat
@@ -6,84 +6,84 @@
   (func (import "$root" "[stream-write-2]foo") (param i32 i32 i32) (result i32))
   (func (import "$root" "[stream-cancel-read-2]foo") (param i32) (result i32))
   (func (import "$root" "[stream-cancel-write-2]foo") (param i32) (result i32))
-  (func (import "$root" "[stream-close-readable-2]foo") (param i32))
+  (func (import "$root" "[stream-close-readable-2]foo") (param i32 i32))
   (func (import "$root" "[stream-close-writable-2]foo") (param i32 i32))
   (func (import "foo:foo/bar" "[stream-new-2]foo") (result i32))
   (func (import "foo:foo/bar" "[stream-read-2]foo") (param i32 i32 i32) (result i32))
   (func (import "foo:foo/bar" "[stream-write-2]foo") (param i32 i32 i32) (result i32))
   (func (import "foo:foo/bar" "[stream-cancel-read-2]foo") (param i32) (result i32))
   (func (import "foo:foo/bar" "[stream-cancel-write-2]foo") (param i32) (result i32))
-  (func (import "foo:foo/bar" "[stream-close-readable-2]foo") (param i32))
+  (func (import "foo:foo/bar" "[stream-close-readable-2]foo") (param i32 i32))
   (func (import "foo:foo/bar" "[stream-close-writable-2]foo") (param i32 i32))
   (func (import "$root" "[future-new-0]foo") (result i32))
   (func (import "$root" "[future-read-0]foo") (param i32 i32) (result i32))
   (func (import "$root" "[future-write-0]foo") (param i32 i32) (result i32))
   (func (import "$root" "[future-cancel-read-0]foo") (param i32) (result i32))
   (func (import "$root" "[future-cancel-write-0]foo") (param i32) (result i32))
-  (func (import "$root" "[future-close-readable-0]foo") (param i32))
+  (func (import "$root" "[future-close-readable-0]foo") (param i32 i32))
   (func (import "$root" "[future-close-writable-0]foo") (param i32 i32))
   (func (import "foo:foo/bar" "[future-new-0]foo") (result i32))
   (func (import "foo:foo/bar" "[future-read-0]foo") (param i32 i32) (result i32))
   (func (import "foo:foo/bar" "[future-write-0]foo") (param i32 i32) (result i32))
   (func (import "foo:foo/bar" "[future-cancel-read-0]foo") (param i32) (result i32))
   (func (import "foo:foo/bar" "[future-cancel-write-0]foo") (param i32) (result i32))
-  (func (import "foo:foo/bar" "[future-close-readable-0]foo") (param i32))
+  (func (import "foo:foo/bar" "[future-close-readable-0]foo") (param i32 i32))
   (func (import "foo:foo/bar" "[future-close-writable-0]foo") (param i32 i32))
   (func (import "$root" "[future-new-1]foo") (result i32))
   (func (import "$root" "[future-read-1]foo") (param i32 i32) (result i32))
   (func (import "$root" "[future-write-1]foo") (param i32 i32) (result i32))
   (func (import "$root" "[future-cancel-read-1]foo") (param i32) (result i32))
   (func (import "$root" "[future-cancel-write-1]foo") (param i32) (result i32))
-  (func (import "$root" "[future-close-readable-1]foo") (param i32))
+  (func (import "$root" "[future-close-readable-1]foo") (param i32 i32))
   (func (import "$root" "[future-close-writable-1]foo") (param i32 i32))
   (func (import "foo:foo/bar" "[future-new-1]foo") (result i32))
   (func (import "foo:foo/bar" "[future-read-1]foo") (param i32 i32) (result i32))
   (func (import "foo:foo/bar" "[future-write-1]foo") (param i32 i32) (result i32))
   (func (import "foo:foo/bar" "[future-cancel-read-1]foo") (param i32) (result i32))
   (func (import "foo:foo/bar" "[future-cancel-write-1]foo") (param i32) (result i32))
-  (func (import "foo:foo/bar" "[future-close-readable-1]foo") (param i32))
+  (func (import "foo:foo/bar" "[future-close-readable-1]foo") (param i32 i32))
   (func (import "foo:foo/bar" "[future-close-writable-1]foo") (param i32 i32))
   (func (import "[export]$root" "[stream-new-2]foo") (result i32))
   (func (import "[export]$root" "[stream-read-2]foo") (param i32 i32 i32) (result i32))
   (func (import "[export]$root" "[stream-write-2]foo") (param i32 i32 i32) (result i32))
   (func (import "[export]$root" "[stream-cancel-read-2]foo") (param i32) (result i32))
   (func (import "[export]$root" "[stream-cancel-write-2]foo") (param i32) (result i32))
-  (func (import "[export]$root" "[stream-close-readable-2]foo") (param i32))
+  (func (import "[export]$root" "[stream-close-readable-2]foo") (param i32 i32))
   (func (import "[export]$root" "[stream-close-writable-2]foo") (param i32 i32))
   (func (import "[export]foo:foo/bar" "[stream-new-2]foo") (result i32))
   (func (import "[export]foo:foo/bar" "[stream-read-2]foo") (param i32 i32 i32) (result i32))
   (func (import "[export]foo:foo/bar" "[stream-write-2]foo") (param i32 i32 i32) (result i32))
   (func (import "[export]foo:foo/bar" "[stream-cancel-read-2]foo") (param i32) (result i32))
   (func (import "[export]foo:foo/bar" "[stream-cancel-write-2]foo") (param i32) (result i32))
-  (func (import "[export]foo:foo/bar" "[stream-close-readable-2]foo") (param i32))
+  (func (import "[export]foo:foo/bar" "[stream-close-readable-2]foo") (param i32 i32))
   (func (import "[export]foo:foo/bar" "[stream-close-writable-2]foo") (param i32 i32))
   (func (import "[export]$root" "[future-new-0]foo") (result i32))
   (func (import "[export]$root" "[future-read-0]foo") (param i32 i32) (result i32))
   (func (import "[export]$root" "[future-write-0]foo") (param i32 i32) (result i32))
   (func (import "[export]$root" "[future-cancel-read-0]foo") (param i32) (result i32))
   (func (import "[export]$root" "[future-cancel-write-0]foo") (param i32) (result i32))
-  (func (import "[export]$root" "[future-close-readable-0]foo") (param i32))
+  (func (import "[export]$root" "[future-close-readable-0]foo") (param i32 i32))
   (func (import "[export]$root" "[future-close-writable-0]foo") (param i32 i32))
   (func (import "[export]foo:foo/bar" "[future-new-0]foo") (result i32))
   (func (import "[export]foo:foo/bar" "[future-read-0]foo") (param i32 i32) (result i32))
   (func (import "[export]foo:foo/bar" "[future-write-0]foo") (param i32 i32) (result i32))
   (func (import "[export]foo:foo/bar" "[future-cancel-read-0]foo") (param i32) (result i32))
   (func (import "[export]foo:foo/bar" "[future-cancel-write-0]foo") (param i32) (result i32))
-  (func (import "[export]foo:foo/bar" "[future-close-readable-0]foo") (param i32))
+  (func (import "[export]foo:foo/bar" "[future-close-readable-0]foo") (param i32 i32))
   (func (import "[export]foo:foo/bar" "[future-close-writable-0]foo") (param i32 i32))
   (func (import "[export]$root" "[future-new-1]foo") (result i32))
   (func (import "[export]$root" "[future-read-1]foo") (param i32 i32) (result i32))
   (func (import "[export]$root" "[future-write-1]foo") (param i32 i32) (result i32))
   (func (import "[export]$root" "[future-cancel-read-1]foo") (param i32) (result i32))
   (func (import "[export]$root" "[future-cancel-write-1]foo") (param i32) (result i32))
-  (func (import "[export]$root" "[future-close-readable-1]foo") (param i32))
+  (func (import "[export]$root" "[future-close-readable-1]foo") (param i32 i32))
   (func (import "[export]$root" "[future-close-writable-1]foo") (param i32 i32))
   (func (import "[export]foo:foo/bar" "[future-new-1]foo") (result i32))
   (func (import "[export]foo:foo/bar" "[future-read-1]foo") (param i32 i32) (result i32))
   (func (import "[export]foo:foo/bar" "[future-write-1]foo") (param i32 i32) (result i32))
   (func (import "[export]foo:foo/bar" "[future-cancel-read-1]foo") (param i32) (result i32))
   (func (import "[export]foo:foo/bar" "[future-cancel-write-1]foo") (param i32) (result i32))
-  (func (import "[export]foo:foo/bar" "[future-close-readable-1]foo") (param i32))
+  (func (import "[export]foo:foo/bar" "[future-close-readable-1]foo") (param i32 i32))
   (func (import "[export]foo:foo/bar" "[future-close-writable-1]foo") (param i32 i32))
   (func (export "[async-stackful]foo") (param i32 i32) unreachable)
   (func (export "[async-stackful]foo:foo/bar#foo") (param i32 i32) unreachable)
diff --git a/tests/cli/add-metadata-merge-sections.wat.stdout b/tests/cli/add-metadata-merge-sections.wat.stdout
index 49ed566d..c6491c6f 100644
--- a/tests/cli/add-metadata-merge-sections.wat.stdout
+++ b/tests/cli/add-metadata-merge-sections.wat.stdout
@@ -3,10 +3,10 @@
 ╞══════════╪═══════════╡
 │ kind     ┆ module    │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name     ┆ <unknown> │
-├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range    ┆ 0x0..0x36 │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name     ┆ <unknown> │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ language ┆ foo [3]   │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ language ┆ bar [1]   │
diff --git a/tests/cli/add-metadata-overwrite-name.wat.stdout b/tests/cli/add-metadata-overwrite-name.wat.stdout
index 6803d701..3b5e74ed 100644
--- a/tests/cli/add-metadata-overwrite-name.wat.stdout
+++ b/tests/cli/add-metadata-overwrite-name.wat.stdout
@@ -3,7 +3,7 @@
 ╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ foo       │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x0..0x15 │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ foo       │
 ╰───────┴───────────╯
diff --git a/tests/cli/add-metadata.wat.stdout b/tests/cli/add-metadata.wat.stdout
index b83255d9..3e88493c 100644
--- a/tests/cli/add-metadata.wat.stdout
+++ b/tests/cli/add-metadata.wat.stdout
@@ -3,10 +3,10 @@
 ╞══════════════╪════════════╡
 │ kind         ┆ module     │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
-│ name         ┆ foo        │
-├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ range        ┆ 0x0..0x54  │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ name         ┆ foo        │
+├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ language     ┆ bar [1]    │
 ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ processed-by ┆ baz [1]    │
diff --git a/tests/cli/metadata-add-component.wat.stdout b/tests/cli/metadata-add-component.wat.stdout
index 72c06737..f0d29b40 100644
--- a/tests/cli/metadata-add-component.wat.stdout
+++ b/tests/cli/metadata-add-component.wat.stdout
@@ -3,10 +3,10 @@
 ╞══════════╪═══════════╡
 │ kind     ┆ component │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name     ┆ foo       │
-├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range    ┆ 0x0..0x65 │
 ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name     ┆ foo       │
+├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ language ┆ foo [1]   │
 ╰──────────┴───────────╯
 ╭───────┬───────────╮
@@ -14,7 +14,7 @@
 ╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ <unknown> │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0xa..0x31 │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ <unknown> │
 ╰───────┴───────────╯
diff --git a/tests/cli/metadata-component.wat.stdout b/tests/cli/metadata-component.wat.stdout
index d262ff85..5dd1cdb2 100644
--- a/tests/cli/metadata-component.wat.stdout
+++ b/tests/cli/metadata-component.wat.stdout
@@ -3,25 +3,25 @@
 ╞═══════╪═══════════╡
 │ kind  ┆ component │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ my-name   │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x0..0x88 │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ my-name   │
 ╰───────┴───────────╯
 ╭───────┬───────────╮
 │ KIND  ┆ VALUE     │
 ╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ submodule │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0xa..0x25 │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ submodule │
 ╰───────┴───────────╯
 ╭───────┬───────────────────╮
 │ KIND  ┆ VALUE             │
 ╞═══════╪═══════════════════╡
 │ kind  ┆ module            │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ another submodule │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x27..0x4a        │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ another submodule │
 ╰───────┴───────────────────╯
diff --git a/tests/cli/metadata.wat.stdout b/tests/cli/metadata.wat.stdout
index 9dc357ab..4919b01d 100644
--- a/tests/cli/metadata.wat.stdout
+++ b/tests/cli/metadata.wat.stdout
@@ -3,7 +3,7 @@
 ╞═══════╪═══════════╡
 │ kind  ┆ module    │
 ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
-│ name  ┆ <unknown> │
-├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
 │ range ┆ 0x0..0x8  │
+├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
+│ name  ┆ <unknown> │
 ╰───────┴───────────╯
diff --git a/tests/local/component-model-async/futures.wast b/tests/local/component-model-async/futures.wast
index 89678f25..a003b586 100644
--- a/tests/local/component-model-async/futures.wast
+++ b/tests/local/component-model-async/futures.wast
@@ -169,7 +169,7 @@
 ;; future.close-readable
 (component
   (core module $m
-    (import "" "future.close-readable" (func $future-close-readable (param i32)))
+    (import "" "future.close-readable" (func $future-close-readable (param i32 i32)))
   )
   (type $future-type (future u8))
   (core func $future-close-readable (canon future.close-readable $future-type))
@@ -180,7 +180,7 @@
 (assert_invalid
   (component
     (core module $m
-      (import "" "future.close-readable" (func $future-close-readable (param i32 i32) (result i32)))
+      (import "" "future.close-readable" (func $future-close-readable (param i32) (result i32)))
     )
     (type $future-type (future u8))
     (core func $future-close-readable (canon future.close-readable $future-type))
diff --git a/tests/local/component-model-async/streams.wast b/tests/local/component-model-async/streams.wast
index 0606c1c9..b71991ad 100644
--- a/tests/local/component-model-async/streams.wast
+++ b/tests/local/component-model-async/streams.wast
@@ -169,7 +169,7 @@
 ;; stream.close-readable
 (component
   (core module $m
-    (import "" "stream.close-readable" (func $stream-close-readable (param i32)))
+    (import "" "stream.close-readable" (func $stream-close-readable (param i32 i32)))
   )
   (type $stream-type (stream u8))
   (core func $stream-close-readable (canon stream.close-readable $stream-type))
@@ -180,7 +180,7 @@
 (assert_invalid
   (component
     (core module $m
-      (import "" "stream.close-readable" (func $stream-close-readable (param i32 i32) (result i32)))
+      (import "" "stream.close-readable" (func $stream-close-readable (param i32) (result i32)))
     )
     (type $stream-type (stream u8))
     (core func $stream-close-readable (canon stream.close-readable $stream-type))
diff --git a/tests/local/component-model-async/task-builtins.wast b/tests/local/component-model-async/task-builtins.wast
index b63ea92c..d13d5088 100644
--- a/tests/local/component-model-async/task-builtins.wast
+++ b/tests/local/component-model-async/task-builtins.wast
@@ -201,3 +201,64 @@
   )
   "type mismatch for export `subtask.drop` of module instantiation argument ``"
 )
+
+;; different forms of canonical intrinsics
+
+(component
+  (core func (canon backpressure.set))
+  (canon backpressure.set (core func))
+  (core func (canon task.return))
+  (canon task.return (core func))
+  (core func (canon subtask.drop))
+  (canon subtask.drop (core func))
+
+  (core module $m
+    (memory (export "m") 1)
+    (func (export "r") (param i32 i32 i32 i32) (result i32) unreachable)
+  )
+  (core instance $i (instantiate $m))
+  (alias core export $i "m" (core memory $m))
+  (alias core export $i "r" (core func $r))
+
+  (type $r (resource (rep i32)))
+  (core func (canon resource.drop $r async))
+  (canon resource.drop $r async (core func))
+
+  (type $s (stream))
+  (type $f (future))
+  (core func (canon future.new $f))
+  (canon future.new $f (core func))
+  (core func (canon stream.new $s))
+  (canon stream.new $s (core func))
+  (core func (canon future.cancel-read $f))
+  (canon future.cancel-read $f (core func))
+  (core func (canon stream.cancel-read $s))
+  (canon stream.cancel-read $s (core func))
+  (core func (canon future.cancel-write $f))
+  (canon future.cancel-write $f (core func))
+  (core func (canon stream.cancel-write $s))
+  (canon stream.cancel-write $s (core func))
+  (core func (canon future.close-readable $f))
+  (canon future.close-readable $f (core func))
+  (core func (canon future.close-writable $f))
+  (canon future.close-writable $f (core func))
+  (core func (canon stream.close-readable $s))
+  (canon stream.close-readable $s (core func))
+  (core func (canon stream.close-writable $s))
+  (canon stream.close-writable $s (core func))
+  (core func (canon future.read $f (memory $m)))
+  (canon future.read $f (memory $m) (core func))
+  (core func (canon future.write $f (memory $m)))
+  (canon future.write $f (memory $m) (core func))
+  (core func (canon stream.read $s (memory $m)))
+  (canon stream.read $s (memory $m) (core func))
+  (core func (canon stream.write $s (memory $m)))
+  (canon stream.write $s (memory $m) (core func))
+
+  (core func (canon error-context.new (memory $m)))
+  (canon error-context.new (memory $m) (core func))
+  (core func (canon error-context.debug-message (memory $m) (realloc $r)))
+  (canon error-context.debug-message (memory $m) (realloc $r) (core func))
+  (core func (canon error-context.drop))
+  (canon error-context.drop (core func))
+)
diff --git a/tests/local/component-model/resources.wast b/tests/local/component-model/resources.wast
index ef9a4224..50736d66 100644
--- a/tests/local/component-model/resources.wast
+++ b/tests/local/component-model/resources.wast
@@ -1151,3 +1151,14 @@
     (type (func (result (option (list $t)))))
   )
   "function result cannot contain a `borrow` type")
+
+;; forms of canon builtins
+(component
+  (type $r (resource (rep i32)))
+  (core func (canon resource.new $r))
+  (canon resource.new $r (core func))
+  (core func (canon resource.drop $r))
+  (canon resource.drop $r (core func))
+  (core func (canon resource.rep $r))
+  (canon resource.rep $r (core func))
+)
diff --git a/tests/snapshots/local/component-model-async/futures.wast/13.print b/tests/snapshots/local/component-model-async/futures.wast/13.print
index 77546833..9ba2e601 100644
--- a/tests/snapshots/local/component-model-async/futures.wast/13.print
+++ b/tests/snapshots/local/component-model-async/futures.wast/13.print
@@ -1,6 +1,6 @@
 (component
   (core module $m (;0;)
-    (type (;0;) (func (param i32)))
+    (type (;0;) (func (param i32 i32)))
     (import "" "future.close-readable" (func $future-close-readable (;0;) (type 0)))
   )
   (type $future-type (;0;) (future u8))
diff --git a/tests/snapshots/local/component-model-async/streams.wast/13.print b/tests/snapshots/local/component-model-async/streams.wast/13.print
index 55c45e4b..d50386ff 100644
--- a/tests/snapshots/local/component-model-async/streams.wast/13.print
+++ b/tests/snapshots/local/component-model-async/streams.wast/13.print
@@ -1,6 +1,6 @@
 (component
   (core module $m (;0;)
-    (type (;0;) (func (param i32)))
+    (type (;0;) (func (param i32 i32)))
     (import "" "stream.close-readable" (func $stream-close-readable (;0;) (type 0)))
   )
   (type $stream-type (;0;) (stream u8))
diff --git a/tests/snapshots/local/component-model-async/task-builtins.wast.json b/tests/snapshots/local/component-model-async/task-builtins.wast.json
index 688b2f8e..dfe9b963 100644
--- a/tests/snapshots/local/component-model-async/task-builtins.wast.json
+++ b/tests/snapshots/local/component-model-async/task-builtins.wast.json
@@ -137,6 +137,12 @@
       "filename": "task-builtins.20.wasm",
       "module_type": "binary",
       "text": "type mismatch for export `subtask.drop` of module instantiation argument ``"
+    },
+    {
+      "type": "module",
+      "line": 207,
+      "filename": "task-builtins.21.wasm",
+      "module_type": "binary"
     }
   ]
 }
\ No newline at end of file
diff --git a/tests/snapshots/local/component-model-async/task-builtins.wast/21.print b/tests/snapshots/local/component-model-async/task-builtins.wast/21.print
new file mode 100644
index 00000000..2816de96
--- /dev/null
+++ b/tests/snapshots/local/component-model-async/task-builtins.wast/21.print
@@ -0,0 +1,59 @@
+(component
+  (core func (;0;) (canon backpressure.set))
+  (core func (;1;) (canon backpressure.set))
+  (core func (;2;) (canon task.return))
+  (core func (;3;) (canon task.return))
+  (core func (;4;) (canon subtask.drop))
+  (core func (;5;) (canon subtask.drop))
+  (core module $m (;0;)
+    (type (;0;) (func (param i32 i32 i32 i32) (result i32)))
+    (memory (;0;) 1)
+    (export "m" (memory 0))
+    (export "r" (func 0))
+    (func (;0;) (type 0) (param i32 i32 i32 i32) (result i32)
+      unreachable
+    )
+  )
+  (core instance $i (;0;) (instantiate $m))
+  (alias core export $i "m" (core memory $m (;0;)))
+  (alias core export $i "r" (core func $r (;6;)))
+  (type $r (;0;) (resource (rep i32)))
+  (core func (;7;) (canon resource.drop $r async))
+  (core func (;8;) (canon resource.drop $r async))
+  (type $s (;1;) (stream))
+  (type $f (;2;) (future))
+  (core func (;9;) (canon future.new $f))
+  (core func (;10;) (canon future.new $f))
+  (core func (;11;) (canon stream.new $s))
+  (core func (;12;) (canon stream.new $s))
+  (core func (;13;) (canon future.cancel-read $f))
+  (core func (;14;) (canon future.cancel-read $f))
+  (core func (;15;) (canon stream.cancel-read $s))
+  (core func (;16;) (canon stream.cancel-read $s))
+  (core func (;17;) (canon future.cancel-write $f))
+  (core func (;18;) (canon future.cancel-write $f))
+  (core func (;19;) (canon stream.cancel-write $s))
+  (core func (;20;) (canon stream.cancel-write $s))
+  (core func (;21;) (canon future.close-readable $f))
+  (core func (;22;) (canon future.close-readable $f))
+  (core func (;23;) (canon future.close-writable $f))
+  (core func (;24;) (canon future.close-writable $f))
+  (core func (;25;) (canon stream.close-readable $s))
+  (core func (;26;) (canon stream.close-readable $s))
+  (core func (;27;) (canon stream.close-writable $s))
+  (core func (;28;) (canon stream.close-writable $s))
+  (core func (;29;) (canon future.read $f (memory $m)))
+  (core func (;30;) (canon future.read $f (memory $m)))
+  (core func (;31;) (canon future.write $f (memory $m)))
+  (core func (;32;) (canon future.write $f (memory $m)))
+  (core func (;33;) (canon stream.read $s (memory $m)))
+  (core func (;34;) (canon stream.read $s (memory $m)))
+  (core func (;35;) (canon stream.write $s (memory $m)))
+  (core func (;36;) (canon stream.write $s (memory $m)))
+  (core func (;37;) (canon error-context.new (memory $m)))
+  (core func (;38;) (canon error-context.new (memory $m)))
+  (core func (;39;) (canon error-context.debug-message (memory $m) (realloc $r)))
+  (core func (;40;) (canon error-context.debug-message (memory $m) (realloc $r)))
+  (core func (;41;) (canon error-context.drop))
+  (core func (;42;) (canon error-context.drop))
+)
diff --git a/tests/snapshots/local/component-model/resources.wast.json b/tests/snapshots/local/component-model/resources.wast.json
index b7038888..bec3298b 100644
--- a/tests/snapshots/local/component-model/resources.wast.json
+++ b/tests/snapshots/local/component-model/resources.wast.json
@@ -755,6 +755,12 @@
       "filename": "resources.113.wasm",
       "module_type": "binary",
       "text": "function result cannot contain a `borrow` type"
+    },
+    {
+      "type": "module",
+      "line": 1156,
+      "filename": "resources.114.wasm",
+      "module_type": "binary"
     }
   ]
 }
\ No newline at end of file
diff --git a/tests/snapshots/local/component-model/resources.wast/114.print b/tests/snapshots/local/component-model/resources.wast/114.print
new file mode 100644
index 00000000..d14469aa
--- /dev/null
+++ b/tests/snapshots/local/component-model/resources.wast/114.print
@@ -0,0 +1,9 @@
+(component
+  (type $r (;0;) (resource (rep i32)))
+  (core func (;0;) (canon resource.new $r))
+  (core func (;1;) (canon resource.new $r))
+  (core func (;2;) (canon resource.drop $r))
+  (core func (;3;) (canon resource.drop $r))
+  (core func (;4;) (canon resource.rep $r))
+  (core func (;5;) (canon resource.rep $r))
+)