Repository: bytecodealliance/wasm-tools
Pull request #1794 (2024-09-17 22:34:01)

Start removing custom translation in wasm-mutate
Now that `wasm_encoder::reencode` exists that's the better option to use for reencoding modules. This commit removes one of the major users of the equivalent `Translator` trait in `wasm_mutate` to start down the path of removing that trait entirely and instead relying on the support in `wasm_encoder`.


Patch:
diff --git a/crates/fuzz-stats/src/bin/failed-instantiations.rs b/crates/fuzz-stats/src/bin/failed-instantiations.rs
index 82a80e06..dfe162e3 100644
--- a/crates/fuzz-stats/src/bin/failed-instantiations.rs
+++ b/crates/fuzz-stats/src/bin/failed-instantiations.rs
@@ -99,6 +99,9 @@ impl State {
         let mut config = wasm_smith::Config::arbitrary(&mut u)?;
         config.allow_start_export = false;
 
+        config.exceptions_enabled = false; // Not implemented by Wasmtime
+        config.threads_enabled = false; // not enabled by default in Wasmtime
+
         // NB: just added "table64" support to this and wasmtime doesn't
         // implement that yet
         config.memory64_enabled = false;
diff --git a/crates/wasm-encoder/src/reencode.rs b/crates/wasm-encoder/src/reencode.rs
index 918a8fb4..dd054624 100644
--- a/crates/wasm-encoder/src/reencode.rs
+++ b/crates/wasm-encoder/src/reencode.rs
@@ -486,6 +486,14 @@ pub trait Reencode {
     ) -> Result<(), Error<Self::Error>> {
         utils::parse_custom_name_subsection(self, names, section)
     }
+
+    fn data_count(&mut self, count: u32) -> u32 {
+        count
+    }
+
+    fn start_section(&mut self, start: u32) -> u32 {
+        self.function_index(start)
+    }
 }
 
 /// An error when re-encoding from `wasmparser` to `wasm-encoder`.
@@ -498,6 +506,8 @@ pub enum Error<E = Infallible> {
     /// The const expression is invalid: not actually constant or something like
     /// that.
     InvalidConstExpr,
+    /// The code section size listed was not valid for the wasm binary provided.
+    InvalidCodeSectionSize,
     /// There was a section that does not belong into a core wasm module.
     UnexpectedNonCoreModuleSection,
     /// There was a section that does not belong into a compoennt module.
@@ -539,6 +549,7 @@ impl<E: std::fmt::Display> std::fmt::Display for Error<E> {
             Self::UnsupportedCoreTypeInComponent => {
                 fmt.write_str("unsupported core type in a component")
             }
+            Self::InvalidCodeSectionSize => fmt.write_str("invalid code section size"),
         }
     }
 }
@@ -552,7 +563,8 @@ impl<E: 'static + std::error::Error> std::error::Error for Error<E> {
             | Self::CanonicalizedHeapTypeReference
             | Self::UnexpectedNonCoreModuleSection
             | Self::UnexpectedNonComponentSection
-            | Self::UnsupportedCoreTypeInComponent => None,
+            | Self::UnsupportedCoreTypeInComponent
+            | Self::InvalidCodeSectionSize => None,
         }
     }
 }
@@ -588,11 +600,10 @@ pub mod utils {
             reencoder.intersperse_section_hook(module, after, before)
         }
 
-        let mut sections = parser.parse_all(data);
-        let mut next_section = sections.next();
+        let orig_offset = parser.offset() as usize;
         let mut last_section = None;
 
-        'outer: while let Some(section) = next_section {
+        for section in parser.parse_all(data) {
             match section? {
                 wasmparser::Payload::Version {
                     encoding: wasmparser::Encoding::Module,
@@ -697,7 +708,7 @@ pub mod utils {
                         Some(crate::SectionId::Start),
                     )?;
                     module.section(&crate::StartSection {
-                        function_index: reencoder.function_index(func),
+                        function_index: reencoder.start_section(func),
                     });
                 }
                 wasmparser::Payload::ElementSection(section) => {
@@ -718,6 +729,7 @@ pub mod utils {
                         &mut last_section,
                         Some(crate::SectionId::DataCount),
                     )?;
+                    let count = reencoder.data_count(count);
                     module.section(&crate::DataCountSection { count });
                 }
                 wasmparser::Payload::DataSection(section) => {
@@ -731,7 +743,7 @@ pub mod utils {
                     reencoder.parse_data_section(&mut data, section)?;
                     module.section(&data);
                 }
-                wasmparser::Payload::CodeSectionStart { count, .. } => {
+                wasmparser::Payload::CodeSectionStart { range, .. } => {
                     handle_intersperse_section_hook(
                         reencoder,
                         module,
@@ -739,39 +751,29 @@ pub mod utils {
                         Some(crate::SectionId::Code),
                     )?;
                     let mut codes = crate::CodeSection::new();
-                    for _ in 0..count {
-                        if let Some(Ok(wasmparser::Payload::CodeSectionEntry(section))) =
-                            sections.next()
-                        {
-                            reencoder.parse_function_body(&mut codes, section)?;
-                        } else {
-                            return Err(Error::UnexpectedNonCoreModuleSection);
-                        }
-                    }
-                    module.section(&codes);
-                }
-                wasmparser::Payload::CodeSectionEntry(section) => {
-                    handle_intersperse_section_hook(
-                        reencoder,
-                        module,
-                        &mut last_section,
-                        Some(crate::SectionId::Code),
-                    )?;
-                    // we can't do better than start a new code section here
-                    let mut codes = crate::CodeSection::new();
-                    reencoder.parse_function_body(&mut codes, section)?;
-                    while let Some(section) = sections.next() {
-                        let section = section?;
-                        if let wasmparser::Payload::CodeSectionEntry(section) = section {
-                            reencoder.parse_function_body(&mut codes, section)?;
-                        } else {
-                            module.section(&codes);
-                            next_section = Some(Ok(section));
-                            continue 'outer;
-                        }
-                    }
+
+                    // Convert from `range` to a byte range within `data` while
+                    // accounting for various offsets. Then create a
+                    // `CodeSectionReader` (which notably the payload does not
+                    // give us here) and recurse with that. This means that
+                    // users overridding `parse_code_section` always get that
+                    // function called.
+                    let section = match data.get(range.start - orig_offset..range.end - orig_offset)
+                    {
+                        Some(section) => section,
+                        None => return Err(Error::InvalidCodeSectionSize),
+                    };
+                    let reader = wasmparser::BinaryReader::new(section, range.start);
+                    let section = wasmparser::CodeSectionReader::new(reader)?;
+                    reencoder.parse_code_section(&mut codes, section)?;
                     module.section(&codes);
                 }
+
+                // Parsing of code section entries (function bodies) happens
+                // above during the handling of the code section. That means
+                // that we just skip all these payloads.
+                wasmparser::Payload::CodeSectionEntry(_) => {}
+
                 wasmparser::Payload::ModuleSection { .. }
                 | wasmparser::Payload::InstanceSection(_)
                 | wasmparser::Payload::CoreTypeSection(_)
@@ -795,8 +797,6 @@ pub mod utils {
                     handle_intersperse_section_hook(reencoder, module, &mut last_section, None)?;
                 }
             }
-
-            next_section = sections.next();
         }
 
         Ok(())
@@ -1413,7 +1413,20 @@ pub mod utils {
                 table_index,
                 offset_expr,
             } => elements.active(
-                table_index.map(|t| reencoder.table_index(t)),
+                // Inform the reencoder that a table index is being used even if
+                // it's not actually present here. That helps wasm-mutate for
+                // example which wants to track uses to know when it's ok to
+                // remove a table.
+                //
+                // If the table index is still zero though go ahead and pass
+                // `None` here since that implicitly references table 0. Note
+                // that this means that this does not round-trip the encoding of
+                // `Some(0)` since that reencodes to `None`, but that's seen as
+                // hopefully ok.
+                match reencoder.table_index(table_index.unwrap_or(0)) {
+                    0 => None,
+                    i => Some(i),
+                },
                 &reencoder.const_expr(offset_expr)?,
                 elems,
             ),
diff --git a/crates/wasm-mutate/Cargo.toml b/crates/wasm-mutate/Cargo.toml
index df82b2f4..35829397 100644
--- a/crates/wasm-mutate/Cargo.toml
+++ b/crates/wasm-mutate/Cargo.toml
@@ -24,3 +24,4 @@ anyhow = { workspace = true }
 wat = { path = "../wat" }
 wasmprinter = { path = "../wasmprinter" }
 env_logger = { workspace = true }
+wasmparser = { workspace = true, features = ['validate', 'features'] }
diff --git a/crates/wasm-mutate/src/error.rs b/crates/wasm-mutate/src/error.rs
index c73df584..c01a6440 100644
--- a/crates/wasm-mutate/src/error.rs
+++ b/crates/wasm-mutate/src/error.rs
@@ -56,6 +56,16 @@ impl From<wasmparser::BinaryReaderError> for Error {
     }
 }
 
+impl From<wasm_encoder::reencode::Error<Error>> for Error {
+    fn from(e: wasm_encoder::reencode::Error<Error>) -> Self {
+        match e {
+            wasm_encoder::reencode::Error::ParseError(e) => Error::parse(e),
+            wasm_encoder::reencode::Error::UserError(e) => e,
+            other => Error::other(other.to_string()),
+        }
+    }
+}
+
 /// The kind of error.
 #[derive(thiserror::Error, Debug)]
 pub enum ErrorKind {
diff --git a/crates/wasm-mutate/src/info.rs b/crates/wasm-mutate/src/info.rs
index 15a10c7f..5126db05 100644
--- a/crates/wasm-mutate/src/info.rs
+++ b/crates/wasm-mutate/src/info.rs
@@ -1,6 +1,6 @@
 use crate::{
     module::{PrimitiveTypeInfo, TypeInfo},
-    Result,
+    Error, Result,
 };
 use std::collections::HashSet;
 use std::ops::Range;
@@ -92,7 +92,7 @@ impl<'a> ModuleInfo<'a> {
 
                     // Save function types
                     for ty in reader.into_iter_err_on_gc_types() {
-                        info.types_map.push(ty?.into());
+                        info.types_map.push(ty?.try_into()?);
                     }
                 }
                 Payload::ImportSection(reader) => {
@@ -107,7 +107,7 @@ impl<'a> ModuleInfo<'a> {
                                 info.imported_functions_count += 1;
                             }
                             wasmparser::TypeRef::Global(ty) => {
-                                let ty = PrimitiveTypeInfo::try_from(ty.content_type).unwrap();
+                                let ty = PrimitiveTypeInfo::try_from(ty.content_type)?;
                                 info.global_types.push(ty);
                                 info.imported_globals_count += 1;
                             }
@@ -162,7 +162,7 @@ impl<'a> ModuleInfo<'a> {
                     for ty in reader {
                         let ty = ty?;
                         // We only need the type of the global, not necessarily if is mutable or not
-                        let ty = PrimitiveTypeInfo::try_from(ty.ty.content_type).unwrap();
+                        let ty = PrimitiveTypeInfo::try_from(ty.ty.content_type)?;
                         info.global_types.push(ty);
                     }
                 }
@@ -209,7 +209,7 @@ impl<'a> ModuleInfo<'a> {
                 Payload::End(_) => {
                     break;
                 }
-                _ => todo!("{:?} not implemented", payload),
+                _ => return Err(Error::unsupported(format!("section: {payload:?}"))),
             }
             wasm = &wasm[consumed..];
         }
diff --git a/crates/wasm-mutate/src/module.rs b/crates/wasm-mutate/src/module.rs
index d6ef3846..0fd6755a 100644
--- a/crates/wasm-mutate/src/module.rs
+++ b/crates/wasm-mutate/src/module.rs
@@ -1,4 +1,4 @@
-use crate::Result;
+use crate::{Error, Result};
 use wasm_encoder::{BlockType, HeapType, RefType, ValType};
 
 #[derive(Debug, Copy, Clone, PartialEq)]
@@ -25,43 +25,49 @@ pub enum TypeInfo {
     // TODO: module linking support will require instance and module types.
 }
 
-impl From<wasmparser::ValType> for PrimitiveTypeInfo {
-    fn from(value: wasmparser::ValType) -> Self {
-        match value {
+impl TryFrom<wasmparser::ValType> for PrimitiveTypeInfo {
+    type Error = Error;
+
+    fn try_from(value: wasmparser::ValType) -> Result<Self> {
+        Ok(match value {
             wasmparser::ValType::I32 => PrimitiveTypeInfo::I32,
             wasmparser::ValType::I64 => PrimitiveTypeInfo::I64,
             wasmparser::ValType::F32 => PrimitiveTypeInfo::F32,
             wasmparser::ValType::F64 => PrimitiveTypeInfo::F64,
             wasmparser::ValType::V128 => PrimitiveTypeInfo::V128,
-            wasmparser::ValType::Ref(t) => t.into(),
-        }
+            wasmparser::ValType::Ref(t) => t.try_into()?,
+        })
     }
 }
 
-impl From<wasmparser::RefType> for PrimitiveTypeInfo {
-    fn from(value: wasmparser::RefType) -> Self {
-        match value {
+impl TryFrom<wasmparser::RefType> for PrimitiveTypeInfo {
+    type Error = Error;
+
+    fn try_from(value: wasmparser::RefType) -> Result<Self> {
+        Ok(match value {
             wasmparser::RefType::FUNCREF => PrimitiveTypeInfo::FuncRef,
             wasmparser::RefType::EXTERNREF => PrimitiveTypeInfo::ExternRef,
-            _ => unimplemented!(),
-        }
+            other => return Err(Error::unsupported(format!("type {other:?}"))),
+        })
     }
 }
 
-impl From<wasmparser::FuncType> for TypeInfo {
-    fn from(ft: wasmparser::FuncType) -> Self {
-        TypeInfo::Func(FuncInfo {
+impl TryFrom<wasmparser::FuncType> for TypeInfo {
+    type Error = Error;
+
+    fn try_from(ft: wasmparser::FuncType) -> Result<Self> {
+        Ok(TypeInfo::Func(FuncInfo {
             params: ft
                 .params()
                 .iter()
-                .map(|&t| PrimitiveTypeInfo::from(t))
-                .collect(),
+                .map(|&t| PrimitiveTypeInfo::try_from(t))
+                .collect::<Result<_>>()?,
             returns: ft
                 .results()
                 .iter()
-                .map(|&t| PrimitiveTypeInfo::from(t))
-                .collect(),
-        })
+                .map(|&t| PrimitiveTypeInfo::try_from(t))
+                .collect::<Result<_>>()?,
+        }))
     }
 }
 
diff --git a/crates/wasm-mutate/src/mutators/peephole.rs b/crates/wasm-mutate/src/mutators/peephole.rs
index dd10d94e..fbdf49d0 100644
--- a/crates/wasm-mutate/src/mutators/peephole.rs
+++ b/crates/wasm-mutate/src/mutators/peephole.rs
@@ -89,7 +89,7 @@ impl PeepholeMutator {
                 }
                 for _ in 0..localsreader.get_count() {
                     let (count, ty) = localsreader.read()?;
-                    let tymapped = PrimitiveTypeInfo::from(ty);
+                    let tymapped = PrimitiveTypeInfo::try_from(ty)?;
                     for _ in 0..count {
                         all_locals.push(tymapped);
                     }
diff --git a/crates/wasm-mutate/src/mutators/peephole/eggsy/analysis.rs b/crates/wasm-mutate/src/mutators/peephole/eggsy/analysis.rs
index a5e5a9ca..ddfb67cb 100644
--- a/crates/wasm-mutate/src/mutators/peephole/eggsy/analysis.rs
+++ b/crates/wasm-mutate/src/mutators/peephole/eggsy/analysis.rs
@@ -290,7 +290,7 @@ impl PeepholeMutationAnalysis {
             Lang::TableSet(..) => Ok(PrimitiveTypeInfo::Empty),
             Lang::TableGet(idx, _) => {
                 let ty = self.table_types[*idx as usize];
-                Ok(ty.element_type.into())
+                ty.element_type.try_into()
             }
             Lang::I32UseGlobal(_) => Ok(PrimitiveTypeInfo::I32),
             Lang::I64UseGlobal(_) => Ok(PrimitiveTypeInfo::I64),
diff --git a/crates/wasm-mutate/src/mutators/remove_item.rs b/crates/wasm-mutate/src/mutators/remove_item.rs
index c155fc90..81419944 100644
--- a/crates/wasm-mutate/src/mutators/remove_item.rs
+++ b/crates/wasm-mutate/src/mutators/remove_item.rs
@@ -7,19 +7,13 @@
 //! mutator largely translates between `wasmparser` structures and
 //! `wasm_encoder` structures.
 
-use crate::mutators::translate::ConstExprKind;
-use crate::mutators::{translate, Item, Mutator, Translator};
+use crate::mutators::{Item, Mutator};
 use crate::Error;
 use crate::{ModuleInfo, Result, WasmMutate};
 use rand::Rng;
 use std::collections::HashSet;
+use wasm_encoder::reencode::Reencode;
 use wasm_encoder::*;
-use wasmparser::{
-    CodeSectionReader, DataSectionReader, ElementSectionReader, ExportSectionReader, ExternalKind,
-    FromReader, FunctionSectionReader, GlobalSectionReader, ImportSectionReader,
-    MemorySectionReader, Operator, TableInit, TableSectionReader, TagSectionReader,
-    TypeSectionReader,
-};
 
 /// Mutator that removes a random item in a wasm module (function, global,
 /// table, etc).
@@ -39,12 +33,14 @@ impl Mutator for RemoveItemMutator {
         log::trace!("attempting to remove {:?} index {}", self.0, idx);
 
         let result = RemoveItem {
+            info: config.info(),
             item: self.0,
             idx,
             referenced_functions: HashSet::new(),
             function_reference_action: Funcref::Save,
+            used_index_that_was_removed: false,
         }
-        .remove(config.info());
+        .remove();
         match result {
             Ok(result) => {
                 log::debug!("removed {:?} index {}", self.0, idx);
@@ -99,11 +95,13 @@ impl Item {
     }
 }
 
-struct RemoveItem {
+struct RemoveItem<'a> {
+    info: &'a ModuleInfo<'a>,
     item: Item,
     idx: u32,
     function_reference_action: Funcref,
     referenced_functions: HashSet<u32>,
+    used_index_that_was_removed: bool,
 }
 
 enum Funcref {
@@ -116,248 +114,27 @@ enum Funcref {
     RequireReferenced,
 }
 
-impl RemoveItem {
-    fn remove(&mut self, info: &ModuleInfo) -> Result<Module> {
+type ReencodeResult<T, E = Error> = Result<T, wasm_encoder::reencode::Error<E>>;
+
+impl RemoveItem<'_> {
+    fn remove(&mut self) -> Result<Module> {
         // This is the main workhorse loop of the module translation. This will
         // iterate over the original wasm sections, raw, and create the new
         // module section-by-section. Sections are rewritten on-the-fly.
         let mut module = Module::new();
-        for (i, section) in info.raw_sections.iter().enumerate() {
-            let mut reader = info.get_binary_reader(i);
-            crate::module::match_section_id! {
-                match section.id;
-
-                Custom => {
-                    module.section(section);
-                },
-
-                Type => {
-                    self.filter_out(
-                        &mut module,
-                        0,
-                        TypeSectionReader::new(reader)?.into_iter_err_on_gc_types(),
-                        Item::Type,
-                        |me, ty, section| {
-                            me.translate_func_type(ty,section)?;
-                            Ok(())
-                        },
-                    )?;
-                },
-
-                Import => {
-                    // The import section is a little special because it defines
-                    // items in multiple index spaces. This means that the
-                    // `filter_out` helper can't be used and we have to process
-                    // everything manually here.
-                    let mut result = ImportSection::new();
-                    let mut function = 0;
-                    let mut global = 0;
-                    let mut table = 0;
-                    let mut memory = 0;
-                    let mut tag = 0;
-                    for item in ImportSectionReader::new(reader)? {
-                        let item = item?;
-                        match &item.ty {
-                            wasmparser::TypeRef::Func(ty) => {
-                                if self.item != Item::Function || self.idx != function {
-                                    let ty = self.remap(Item::Type, *ty)?;
-                                    result.import(item.module, item.name, EntityType::Function(ty));
-                                }
-                                function += 1;
-                            }
-                            wasmparser::TypeRef::Table(ty) => {
-                                if self.item != Item::Table || self.idx != table {
-                                    let ty = self.translate_table_type(ty)?;
-                                    result.import(item.module, item.name, ty);
-                                }
-                                table += 1;
-                            }
-                            wasmparser::TypeRef::Memory(ty) => {
-                                if self.item != Item::Memory || self.idx != memory {
-                                    let ty = self.translate_memory_type(ty)?;
-                                    result.import(item.module, item.name, ty);
-                                }
-                                memory += 1;
-                            }
-                            wasmparser::TypeRef::Global(ty) => {
-                                if self.item != Item::Global || self.idx != global {
-                                    let ty = self.translate_global_type(ty)?;
-                                    result.import(item.module, item.name, ty);
-                                }
-                                global += 1;
-                            }
-                            wasmparser::TypeRef::Tag(ty) => {
-                                if self.item != Item::Tag || self.idx != tag {
-                                    let ty = self.translate_tag_type(ty)?;
-                                    result.import(item.module, item.name, ty);
-                                }
-                                tag += 1;
-                            }
-                        }
-                    }
-                    module.section(&result);
-                },
-
-                Function => {
-                    self.filter_out(
-                        &mut module,
-                        info.num_imported_functions(),
-                        FunctionSectionReader::new(reader)?,
-                        Item::Function,
-                        |me, idx, section: &mut FunctionSection| {
-                            let idx = me.remap(Item::Type, idx)?;
-                            section.function(idx);
-                            Ok(())
-                        },
-                    )?;
-                },
-
-                Table => {
-                    self.filter_out(
-                        &mut module,
-                        info.num_imported_tables(),
-                        TableSectionReader::new(reader)?,
-                        Item::Table,
-                        |me, table, section: &mut TableSection| {
-                            let ty = me.translate_table_type(&table.ty)?;
-                            match &table.init {
-                                TableInit::RefNull => {
-                                    section.table(ty);
-                                }
-                                TableInit::Expr(expr) => {
-                                    let init = me.translate_const_expr(
-                                        expr,
-                                        &table.ty.element_type.into(),
-                                        ConstExprKind::TableInit,
-                                    )?;
-                                    section.table_with_init(ty, &init);
-                                }
-                            }
-                            Ok(())
-                        },
-                    )?;
-                },
-
-                Memory => {
-                    self.filter_out(
-                        &mut module,
-                        info.num_imported_memories(),
-                        MemorySectionReader::new(reader)?,
-                        Item::Memory,
-                        |me, ty, section: &mut MemorySection| {
-                            let ty = me.translate_memory_type(&ty)?;
-                            section.memory(ty);
-                            Ok(())
-                        },
-                    )?;
-                },
-
-                Global => {
-                    self.filter_out(
-                        &mut module,
-                        info.num_imported_globals(),
-                        GlobalSectionReader::new(reader)?,
-                        Item::Global,
-                        |me, ty, section| me.translate_global(ty, section),
-                    )?;
-                },
-
-                Export => {
-                    let mut result = ExportSection::new();
-                    for item in ExportSectionReader::new(reader)? {
-                        let item = item?;
-                        let (kind, index) = match &item.kind {
-                            ExternalKind::Func => {
-                                (ExportKind::Func, self.remap(Item::Function, item.index)?)
-                            }
-                            ExternalKind::Table => {
-                                (ExportKind::Table, self.remap(Item::Table, item.index)?)
-                            }
-                            ExternalKind::Memory => {
-                                (ExportKind::Memory, self.remap(Item::Memory, item.index)?)
-                            }
-                            ExternalKind::Tag => (ExportKind::Tag, self.remap(Item::Tag, item.index)?),
-                            ExternalKind::Global => {
-                                (ExportKind::Global, self.remap(Item::Global, item.index)?)
-                            }
-                        };
-                        result.export(item.name, kind, index);
-                    }
-                    module.section(&result);
-                },
-
-                Start => {
-                    let function_index = reader.read_var_u32()?;
-                    self.function_reference_action = Funcref::Skip;
-                    let function_index = self.remap(Item::Function, function_index)?;
-                    self.function_reference_action = Funcref::Save;
-                    module.section(&StartSection { function_index });
-                },
-
-                Element => {
-                    self.filter_out(
-                        &mut module,
-                        0,
-                        ElementSectionReader::new(reader)?,
-                        Item::Element,
-                        |me, ty, section| me.translate_element(ty, section),
-                    )?;
-                },
-
-                Code => {
-                    // In the code section we require that all functions
-                    // referenced in `ref.func` are referenced elsewhere in the
-                    // module, so indicate so in our internal state here.
-                    self.function_reference_action = Funcref::RequireReferenced;
-                    self.filter_out(
-                        &mut module,
-                        info.num_imported_functions(),
-                        CodeSectionReader::new(reader)?,
-                        Item::Function,
-                        |me, body, section| me.translate_code(body, section),
-                    )?;
-                },
-
-                Data => {
-                    self.filter_out(
-                        &mut module,
-                        0,
-                        DataSectionReader::new(reader)?,
-                        Item::Data,
-                        |me, ty, section| me.translate_data(ty, section),
-                    )?;
-                },
-
-                DataCount => {
-                    let count = reader.read_var_u32()?;
-                    // Note that the data count section is decremented here if
-                    // we're removing a data item, otherwise it's preserved
-                    // as-is.
-                    let count = if self.item == Item::Data {
-                        count - 1
-                    } else {
-                        count
-                    };
-                    module.section(&DataCountSection { count });
-                },
-
-                Tag => {
-                    self.filter_out(
-                        &mut module,
-                        info.num_imported_tags(),
-                        TagSectionReader::new(reader)?,
-                        Item::Tag,
-                        |me, ty, section: &mut TagSection| {
-                            let ty = me.translate_tag_type(&ty)?;
-                            section.tag(ty);
-                            Ok(())
-                        },
-                    )?;
-                },
-
-                _ => panic!("unknown id: {}", section.id),
-            };
+        self.parse_core_module(
+            &mut module,
+            wasmparser::Parser::new(0),
+            self.info.input_wasm,
+        )?;
+
+        // If an index was used that was actually being removed then flag this
+        // module as no longer applicable to mutate because the item wasn't
+        // actually a candidate for removal.
+        if self.used_index_that_was_removed {
+            return Err(Error::no_mutations_applicable());
         }
+
         Ok(module)
     }
 
@@ -367,42 +144,33 @@ impl RemoveItem {
     /// The `section` given, which has items of type `section_item`, will be
     /// iterated over and translated with the `encode` callback. The `encode`
     /// callback is only called for items we're actually preserving in this
-    /// module. The section is finally added to `module` at the end of
-    /// translation.
-    ///
-    /// The `offset` provided is the initial offset in the index space, for
-    /// example the global section starts at the offset equal to the number of
-    /// imported globals because local globals are numbered afterwards.
-    fn filter_out<'a, S, T>(
+    /// module.
+    fn filter_out<'a, T>(
         &mut self,
-        module: &mut Module,
-        offset: u32,
-        section: impl IntoIterator<Item = wasmparser::Result<S>>,
+        section: impl IntoIterator<Item = wasmparser::Result<T>>,
         section_item: Item,
-        encode: impl Fn(&mut Self, S, &mut T) -> Result<()>,
-    ) -> Result<()>
-    where
-        S: FromReader<'a>,
-        T: Default + Section,
-    {
-        let mut result = T::default();
-        let mut index = offset;
+        mut encode: impl FnMut(&mut Self, T) -> ReencodeResult<()>,
+    ) -> ReencodeResult<()> {
+        // Calculate the initial index by taking into account any imported items
+        // in this namespace (note that the filtering of imports doesn't use
+        // this function).
+        let mut index = match section_item {
+            Item::Function => self.info.num_imported_functions(),
+            Item::Table => self.info.num_imported_tables(),
+            Item::Tag => self.info.num_imported_tags(),
+            Item::Memory => self.info.num_imported_memories(),
+            Item::Global => self.info.num_imported_globals(),
+            Item::Data | Item::Element | Item::Type => 0,
+        };
         for item in section {
             let item = item?;
             if index != self.idx || section_item != self.item {
-                encode(self, item, &mut result)?;
+                encode(self, item)?;
             }
             index += 1;
         }
-        module.section(&result);
         Ok(())
     }
-}
-
-impl Translator for RemoveItem {
-    fn as_obj(&mut self) -> &mut dyn Translator {
-        self
-    }
 
     /// This is "the point" of this type. This function remaps an `idx`
     /// provided, in the `item` index space, to a new index.
@@ -421,7 +189,7 @@ impl Translator for RemoveItem {
     ///   try something else.
     /// * Finally our index is larger than the one being removed which means we
     ///   now decrement it by one to account for the removed item.
-    fn remap(&mut self, item: Item, idx: u32) -> Result<u32> {
+    fn remap(&mut self, item: Item, idx: u32) -> u32 {
         // If we're before the code section then all function references, no
         // matter where they are, are considered "referencing functions" so we
         // save the indices of that which is referenced.
@@ -433,19 +201,220 @@ impl Translator for RemoveItem {
 
         if item != self.item || idx < self.idx {
             // Different kind of item or a later item was removed, index doesn't change
-            Ok(idx)
+            idx
         } else if idx == self.idx {
             // If we're removing a referenced item then that means that this
-            // mutation fails.
-            Err(Error::no_mutations_applicable())
+            // mutation fails. Flag this for later failure and otherwise pass
+            // through the index as-is.
+            self.used_index_that_was_removed = true;
+            idx
         } else {
             // Otherwise this item comes after the item being removed, so
             // this item's index has decreased by one.
-            Ok(idx - 1)
+            idx - 1
+        }
+    }
+}
+
+impl Reencode for RemoveItem<'_> {
+    type Error = Error;
+
+    fn function_index(&mut self, idx: u32) -> u32 {
+        self.remap(Item::Function, idx)
+    }
+
+    fn table_index(&mut self, idx: u32) -> u32 {
+        self.remap(Item::Table, idx)
+    }
+
+    fn memory_index(&mut self, idx: u32) -> u32 {
+        self.remap(Item::Memory, idx)
+    }
+
+    fn tag_index(&mut self, idx: u32) -> u32 {
+        self.remap(Item::Tag, idx)
+    }
+
+    fn global_index(&mut self, idx: u32) -> u32 {
+        self.remap(Item::Global, idx)
+    }
+
+    fn type_index(&mut self, idx: u32) -> u32 {
+        self.remap(Item::Type, idx)
+    }
+
+    fn data_index(&mut self, idx: u32) -> u32 {
+        self.remap(Item::Data, idx)
+    }
+
+    fn element_index(&mut self, idx: u32) -> u32 {
+        self.remap(Item::Element, idx)
+    }
+
+    fn parse_type_section(
+        &mut self,
+        types: &mut wasm_encoder::TypeSection,
+        section: wasmparser::TypeSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.filter_out(section, Item::Type, |me, rec_group| {
+            me.parse_recursive_type_group(types.ty(), rec_group)?;
+            Ok(())
+        })
+    }
+
+    fn parse_import_section(
+        &mut self,
+        imports: &mut wasm_encoder::ImportSection,
+        section: wasmparser::ImportSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        // The import section is a little special because it defines
+        // items in multiple index spaces. This means that the
+        // `filter_out` helper can't be used and we have to process
+        // everything manually here.
+        let mut function = 0;
+        let mut global = 0;
+        let mut table = 0;
+        let mut memory = 0;
+        let mut tag = 0;
+        for item in section {
+            let item = item?;
+            let retain;
+            match &item.ty {
+                wasmparser::TypeRef::Func(_) => {
+                    retain = self.item != Item::Function || self.idx != function;
+                    function += 1;
+                }
+                wasmparser::TypeRef::Table(_) => {
+                    retain = self.item != Item::Table || self.idx != table;
+                    table += 1;
+                }
+                wasmparser::TypeRef::Memory(_) => {
+                    retain = self.item != Item::Memory || self.idx != memory;
+                    memory += 1;
+                }
+                wasmparser::TypeRef::Global(_) => {
+                    retain = self.item != Item::Global || self.idx != global;
+                    global += 1;
+                }
+                wasmparser::TypeRef::Tag(_) => {
+                    retain = self.item != Item::Tag || self.idx != tag;
+                    tag += 1;
+                }
+            }
+            if retain {
+                self.parse_import(imports, item)?;
+            }
+        }
+        Ok(())
+    }
+
+    fn parse_function_section(
+        &mut self,
+        funcs: &mut wasm_encoder::FunctionSection,
+        section: wasmparser::FunctionSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.filter_out(section, Item::Function, |me, func| {
+            funcs.function(me.type_index(func));
+            Ok(())
+        })
+    }
+
+    fn parse_table_section(
+        &mut self,
+        tables: &mut wasm_encoder::TableSection,
+        section: wasmparser::TableSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.filter_out(section, Item::Table, |me, table| {
+            me.parse_table(tables, table)?;
+            Ok(())
+        })
+    }
+
+    fn parse_memory_section(
+        &mut self,
+        memories: &mut wasm_encoder::MemorySection,
+        section: wasmparser::MemorySectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.filter_out(section, Item::Memory, |me, memory| {
+            memories.memory(me.memory_type(memory));
+            Ok(())
+        })
+    }
+
+    fn parse_global_section(
+        &mut self,
+        globals: &mut wasm_encoder::GlobalSection,
+        section: wasmparser::GlobalSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.filter_out(section, Item::Global, |me, global| {
+            me.parse_global(globals, global)?;
+            Ok(())
+        })
+    }
+
+    fn parse_element_section(
+        &mut self,
+        elements: &mut wasm_encoder::ElementSection,
+        section: wasmparser::ElementSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.filter_out(section, Item::Element, |me, elem| {
+            me.parse_element(elements, elem)?;
+            Ok(())
+        })
+    }
+
+    fn parse_data_section(
+        &mut self,
+        ret: &mut wasm_encoder::DataSection,
+        section: wasmparser::DataSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.filter_out(section, Item::Data, |me, data| {
+            me.parse_data(ret, data)?;
+            Ok(())
+        })
+    }
+
+    fn parse_tag_section(
+        &mut self,
+        tags: &mut wasm_encoder::TagSection,
+        section: wasmparser::TagSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.filter_out(section, Item::Tag, |me, tag| {
+            tags.tag(me.tag_type(tag));
+            Ok(())
+        })
+    }
+
+    fn data_count(&mut self, count: u32) -> u32 {
+        // Note that the data count section is decremented here if
+        // we're removing a data item, otherwise it's preserved
+        // as-is.
+        if self.item == Item::Data {
+            count - 1
+        } else {
+            count
         }
     }
 
-    fn translate_op(&mut self, op: &Operator<'_>) -> Result<Instruction<'static>> {
+    fn start_section(&mut self, func: u32) -> u32 {
+        self.function_reference_action = Funcref::Skip;
+        let func = self.remap(Item::Function, func);
+        self.function_reference_action = Funcref::Save;
+        func
+    }
+
+    fn parse_code_section(
+        &mut self,
+        code: &mut wasm_encoder::CodeSection,
+        section: wasmparser::CodeSectionReader<'_>,
+    ) -> ReencodeResult<()> {
+        self.function_reference_action = Funcref::RequireReferenced;
+        self.filter_out(section, Item::Function, |me, body| {
+            me.parse_function_body(code, body)
+        })
+    }
+
+    fn instruction<'a>(&mut self, op: wasmparser::Operator<'a>) -> ReencodeResult<Instruction<'a>> {
         // The reason for this is that in the code section instructions
         // such as `ref.func 0` are only valid if function 0 is
         // otherwise referenced somewhere in the module via things like
@@ -457,15 +426,15 @@ impl Translator for RemoveItem {
         // instruction it'll return an error if the index isn't
         // otherwise referenced (probably because we removed the one
         // item that referenced it).
-        if let Operator::RefFunc { function_index } = op {
+        if let wasmparser::Operator::RefFunc { function_index } = op {
             if let Funcref::RequireReferenced = self.function_reference_action {
-                if !self.referenced_functions.contains(function_index) {
-                    return Err(Error::no_mutations_applicable());
+                if !self.referenced_functions.contains(&function_index) {
+                    self.used_index_that_was_removed = true;
                 }
             }
         }
 
-        translate::op(self, op)
+        wasm_encoder::reencode::utils::instruction(self, op)
     }
 }
 
diff --git a/crates/wasm-mutate/src/mutators/translate.rs b/crates/wasm-mutate/src/mutators/translate.rs
index db60a0e5..fe57fe6c 100644
--- a/crates/wasm-mutate/src/mutators/translate.rs
+++ b/crates/wasm-mutate/src/mutators/translate.rs
@@ -1,6 +1,6 @@
 use crate::{Error, Result};
 use wasm_encoder::*;
-use wasmparser::{DataKind, ElementKind, FunctionBody, Global, Operator};
+use wasmparser::{ElementKind, Global, Operator};
 
 #[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)]
 pub enum Item {
@@ -20,30 +20,11 @@ pub enum ConstExprKind {
     ElementOffset,
     ElementFunction,
     DataOffset,
-    TableInit,
 }
 
 pub trait Translator {
     fn as_obj(&mut self) -> &mut dyn Translator;
 
-    fn translate_func_type(&mut self, ty: wasmparser::FuncType, s: &mut TypeSection) -> Result<()> {
-        func_type(self.as_obj(), ty, s)
-    }
-
-    fn translate_table_type(
-        &mut self,
-        ty: &wasmparser::TableType,
-    ) -> Result<wasm_encoder::TableType> {
-        table_type(self.as_obj(), ty)
-    }
-
-    fn translate_memory_type(
-        &mut self,
-        ty: &wasmparser::MemoryType,
-    ) -> Result<wasm_encoder::MemoryType> {
-        memory_type(self.as_obj(), ty)
-    }
-
     fn translate_global_type(
         &mut self,
         ty: &wasmparser::GlobalType,
@@ -51,10 +32,6 @@ pub trait Translator {
         global_type(self.as_obj(), ty)
     }
 
-    fn translate_tag_type(&mut self, ty: &wasmparser::TagType) -> Result<wasm_encoder::TagType> {
-        tag_type(self.as_obj(), ty)
-    }
-
     fn translate_ty(&mut self, t: &wasmparser::ValType) -> Result<ValType> {
         ty(self.as_obj(), t)
     }
@@ -88,14 +65,6 @@ pub trait Translator {
         element(self.as_obj(), e, s)
     }
 
-    fn translate_data(&mut self, d: wasmparser::Data<'_>, s: &mut DataSection) -> Result<()> {
-        data(self.as_obj(), d, s)
-    }
-
-    fn translate_code(&mut self, body: FunctionBody<'_>, s: &mut CodeSection) -> Result<()> {
-        code(self.as_obj(), body, s)
-    }
-
     fn translate_op(&mut self, e: &Operator<'_>) -> Result<Instruction<'static>> {
         op(self.as_obj(), e)
     }
@@ -129,50 +98,6 @@ impl Translator for DefaultTranslator {
     }
 }
 
-pub fn func_type(
-    t: &mut dyn Translator,
-    ty: wasmparser::FuncType,
-    s: &mut TypeSection,
-) -> Result<()> {
-    s.ty().function(
-        ty.params()
-            .iter()
-            .map(|ty| t.translate_ty(ty))
-            .collect::<Result<Vec<_>>>()?,
-        ty.results()
-            .iter()
-            .map(|ty| t.translate_ty(ty))
-            .collect::<Result<Vec<_>>>()?,
-    );
-    Ok(())
-}
-
-pub fn table_type(
-    t: &mut dyn Translator,
-    ty: &wasmparser::TableType,
-) -> Result<wasm_encoder::TableType> {
-    Ok(wasm_encoder::TableType {
-        element_type: t.translate_refty(&ty.element_type)?,
-        minimum: ty.initial,
-        maximum: ty.maximum,
-        table64: ty.table64,
-        shared: ty.shared,
-    })
-}
-
-pub fn memory_type(
-    _t: &mut dyn Translator,
-    ty: &wasmparser::MemoryType,
-) -> Result<wasm_encoder::MemoryType> {
-    Ok(wasm_encoder::MemoryType {
-        memory64: ty.memory64,
-        minimum: ty.initial,
-        maximum: ty.maximum,
-        shared: ty.shared,
-        page_size_log2: ty.page_size_log2,
-    })
-}
-
 pub fn global_type(
     t: &mut dyn Translator,
     ty: &wasmparser::GlobalType,
@@ -184,13 +109,6 @@ pub fn global_type(
     })
 }
 
-pub fn tag_type(t: &mut dyn Translator, ty: &wasmparser::TagType) -> Result<wasm_encoder::TagType> {
-    Ok(wasm_encoder::TagType {
-        kind: TagKind::Exception,
-        func_type_idx: t.remap(Item::Type, ty.func_type_idx)?,
-    })
-}
-
 pub fn ty(t: &mut dyn Translator, ty: &wasmparser::ValType) -> Result<ValType> {
     match ty {
         wasmparser::ValType::I32 => Ok(ValType::I32),
@@ -425,49 +343,3 @@ pub fn memarg(t: &mut dyn Translator, memarg: &wasmparser::MemArg) -> Result<Mem
         memory_index: t.remap(Item::Memory, memarg.memory)?,
     })
 }
-
-pub fn data(t: &mut dyn Translator, data: wasmparser::Data<'_>, s: &mut DataSection) -> Result<()> {
-    let offset;
-    let mode = match &data.kind {
-        DataKind::Active {
-            memory_index,
-            offset_expr,
-        } => {
-            offset = t.translate_const_expr(
-                offset_expr,
-                &wasmparser::ValType::I32,
-                ConstExprKind::DataOffset,
-            )?;
-            DataSegmentMode::Active {
-                memory_index: t.remap(Item::Memory, *memory_index)?,
-                offset: &offset,
-            }
-        }
-        DataKind::Passive => DataSegmentMode::Passive,
-    };
-    s.segment(DataSegment {
-        mode,
-        data: data.data.iter().copied(),
-    });
-    Ok(())
-}
-
-pub fn code(t: &mut dyn Translator, body: FunctionBody<'_>, s: &mut CodeSection) -> Result<()> {
-    let locals = body
-        .get_locals_reader()?
-        .into_iter()
-        .map(|local| {
-            let (cnt, ty) = local?;
-            Ok((cnt, t.translate_ty(&ty)?))
-        })
-        .collect::<Result<Vec<_>>>()?;
-    let mut func = Function::new(locals);
-
-    let reader = body.get_operators_reader()?;
-    for op in reader {
-        let op = op?;
-        func.instruction(&t.translate_op(&op)?);
-    }
-    s.function(&func);
-    Ok(())
-}
diff --git a/crates/wasm-smith/src/config.rs b/crates/wasm-smith/src/config.rs
index f628b7c7..97c707a0 100644
--- a/crates/wasm-smith/src/config.rs
+++ b/crates/wasm-smith/src/config.rs
@@ -299,8 +299,8 @@ define_config! {
         /// Determines whether the exception-handling proposal is enabled for
         /// generating instructions.
         ///
-        /// Defaults to `false`.
-        pub exceptions_enabled: bool = false,
+        /// Defaults to `true`.
+        pub exceptions_enabled: bool = true,
 
         /// Export all WebAssembly objects in the module. Defaults to false.
         ///
@@ -310,8 +310,8 @@ define_config! {
         /// Determines whether the GC proposal is enabled when generating a Wasm
         /// module.
         ///
-        /// Defaults to `false`.
-        pub gc_enabled: bool = false,
+        /// Defaults to `true`.
+        pub gc_enabled: bool = true,
 
         /// Determines whether the custom-page-sizes proposal is enabled when
         /// generating a Wasm module.
@@ -532,14 +532,14 @@ define_config! {
         /// Determines whether the reference types proposal is enabled for
         /// generating instructions.
         ///
-        /// Defaults to `false`.
-        pub reference_types_enabled: bool = false,
+        /// Defaults to `true`.
+        pub reference_types_enabled: bool = true,
 
         /// Determines whether the Relaxed SIMD proposal is enabled for
         /// generating instructions.
         ///
-        /// Defaults to `false`.
-        pub relaxed_simd_enabled: bool = false,
+        /// Defaults to `true`.
+        pub relaxed_simd_enabled: bool = true,
 
         /// Determines whether the nontrapping-float-to-int-conversions propsal
         /// is enabled.
@@ -555,14 +555,14 @@ define_config! {
         /// Determines whether the SIMD proposal is enabled for generating
         /// instructions.
         ///
-        /// Defaults to `false`.
-        pub simd_enabled: bool = false,
+        /// Defaults to `true`.
+        pub simd_enabled: bool = true,
 
         /// Determines whether the tail calls proposal is enabled for generating
         /// instructions.
         ///
-        /// Defaults to `false`.
-        pub tail_call_enabled: bool = false,
+        /// Defaults to `true`.
+        pub tail_call_enabled: bool = true,
 
         /// Whether every Wasm table must have a maximum size
         /// specified. Defaults to `false`.
@@ -575,8 +575,8 @@ define_config! {
         ///
         /// [threads proposal]: https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md
         ///
-        /// Defaults to `false`.
-        pub threads_enabled: bool = false,
+        /// Defaults to `true`.
+        pub threads_enabled: bool = true,
 
         /// Indicates whether wasm-smith is allowed to generate invalid function
         /// bodies.
@@ -654,6 +654,7 @@ impl<'a> Arbitrary<'a> for Config {
 
         let reference_types_enabled: bool = u.arbitrary()?;
         let max_tables = if reference_types_enabled { 100 } else { 1 };
+        let simd_enabled: bool = u.arbitrary()?;
 
         Ok(Config {
             max_types: u.int_in_range(0..=MAX_MAXIMUM)?,
@@ -679,6 +680,11 @@ impl<'a> Arbitrary<'a> for Config {
             max_nesting_depth: u.int_in_range(0..=10)?,
             saturating_float_to_int_enabled: u.arbitrary()?,
             sign_extension_ops_enabled: u.arbitrary()?,
+            relaxed_simd_enabled: simd_enabled && u.arbitrary()?,
+            exceptions_enabled: u.arbitrary()?,
+            threads_enabled: u.arbitrary()?,
+            tail_call_enabled: u.arbitrary()?,
+            gc_enabled: reference_types_enabled && u.arbitrary()?,
             allowed_instructions: {
                 use flagset::Flags;
                 let mut allowed = Vec::new();
@@ -714,20 +720,17 @@ impl<'a> Arbitrary<'a> for Config {
             max_values: 0,
             memory_offset_choices: MemoryOffsetChoices::default(),
             allow_start_export: true,
-            relaxed_simd_enabled: false,
-            exceptions_enabled: false,
-            memory64_enabled: false,
             max_type_size: 1000,
             canonicalize_nans: false,
             available_imports: None,
             exports: None,
-            threads_enabled: false,
             export_everything: false,
-            tail_call_enabled: false,
-            gc_enabled: false,
-            custom_page_sizes_enabled: false,
             generate_custom_sections: false,
             allow_invalid_funcs: false,
+
+            // Proposals that are not stage4+ are disabled by default.
+            memory64_enabled: false,
+            custom_page_sizes_enabled: false,
         })
     }
 }
diff --git a/crates/wasmparser/src/parser.rs b/crates/wasmparser/src/parser.rs
index 4c0c4a83..bfa0bdfe 100644
--- a/crates/wasmparser/src/parser.rs
+++ b/crates/wasmparser/src/parser.rs
@@ -407,6 +407,11 @@ impl Parser {
         self.features = features;
     }
 
+    /// Returns the original offset that this parser is currently at.
+    pub fn offset(&self) -> u64 {
+        self.offset
+    }
+
     /// Attempts to parse a chunk of data.
     ///
     /// This method will attempt to parse the next incremental portion of a
diff --git a/crates/wit-parser/src/resolve.rs b/crates/wit-parser/src/resolve.rs
index 3a9ee24e..bd03376f 100644
--- a/crates/wit-parser/src/resolve.rs
+++ b/crates/wit-parser/src/resolve.rs
@@ -19,6 +19,8 @@ use crate::{
     WorldKey, WorldSpan,
 };
 
+mod clone;
+
 /// Representation of a fully resolved set of WIT packages.
 ///
 /// This structure contains a graph of WIT packages and all of their contents
@@ -747,6 +749,8 @@ package {name} is defined in two different locations:\n\
         let from_world = &self.worlds[from];
         let into_world = &self.worlds[into];
 
+        log::trace!("merging {} into {}", from_world.name, into_world.name);
+
         // First walk over all the imports of `from` world and figure out what
         // to do with them.
         //
@@ -755,13 +759,15 @@ package {name} is defined in two different locations:\n\
         // same. Otherwise queue up a new import since if `from` has more
         // imports than `into` then it's fine to add new imports.
         for (name, from_import) in from_world.imports.iter() {
+            let name_str = self.name_world_key(name);
             match into_world.imports.get(name) {
                 Some(into_import) => {
-                    let name = self.name_world_key(name);
+                    log::trace!("info/from shared import on `{name_str}`");
                     self.merge_world_item(from_import, into_import)
-                        .with_context(|| format!("failed to merge world import {name}"))?;
+                        .with_context(|| format!("failed to merge world import {name_str}"))?;
                 }
                 None => {
+                    log::trace!("new import: `{name_str}`");
                     new_imports.push((name.clone(), from_import.clone()));
                 }
             }
@@ -788,13 +794,15 @@ package {name} is defined in two different locations:\n\
         // Next walk over exports of `from` and process these similarly to
         // imports.
         for (name, from_export) in from_world.exports.iter() {
+            let name_str = self.name_world_key(name);
             match into_world.exports.get(name) {
                 Some(into_export) => {
-                    let name = self.name_world_key(name);
+                    log::trace!("info/from shared export on `{name_str}`");
                     self.merge_world_item(from_export, into_export)
-                        .with_context(|| format!("failed to merge world export {name}"))?;
+                        .with_context(|| format!("failed to merge world export {name_str}"))?;
                 }
                 None => {
+                    log::trace!("new export `{name_str}`");
                     // See comments in `ensure_can_add_world_export` for why
                     // this is slightly different than imports.
                     self.ensure_can_add_world_export(
@@ -811,14 +819,33 @@ package {name} is defined in two different locations:\n\
             }
         }
 
+        // For all the new imports and exports they may need to be "cloned" to
+        // be able to belong to the new world. For example:
+        //
+        // * Anonymous interfaces have a `package` field which points to the
+        //   package of the containing world, but `from` and `into` may not be
+        //   in the same package.
+        //
+        // * Type imports have an `owner` field that point to `from`, but they
+        //   now need to point to `into` instead.
+        //
+        // Cloning is no trivial task, however, so cloning is delegated to a
+        // submodule to perform a "deep" clone and copy items into new arena
+        // entries as necessary.
+        let mut cloner = clone::Cloner::new(self, TypeOwner::World(from), TypeOwner::World(into));
+        cloner.register_world_type_overlap(from, into);
+        for (name, item) in new_imports.iter_mut().chain(&mut new_exports) {
+            cloner.world_item(name, item);
+        }
+
         // Insert any new imports and new exports found first.
-        let into = &mut self.worlds[into];
+        let into_world = &mut self.worlds[into];
         for (name, import) in new_imports {
-            let prev = into.imports.insert(name, import);
+            let prev = into_world.imports.insert(name, import);
             assert!(prev.is_none());
         }
         for (name, export) in new_exports {
-            let prev = into.exports.insert(name, export);
+            let prev = into_world.exports.insert(name, export);
             assert!(prev.is_none());
         }
 
@@ -1428,7 +1455,13 @@ package {name} is defined in two different locations:\n\
             for (name, item) in world.imports.iter().chain(world.exports.iter()) {
                 log::debug!("validating world item: {}", self.name_world_key(name));
                 match item {
-                    WorldItem::Interface { .. } => {}
+                    WorldItem::Interface { id, .. } => {
+                        // anonymous interfaces must belong to the same package
+                        // as the world's package.
+                        if matches!(name, WorldKey::Name(_)) {
+                            assert_eq!(self.interfaces[*id].package, world.package);
+                        }
+                    }
                     WorldItem::Function(f) => {
                         assert!(!matches!(name, WorldKey::Interface(_)));
                         assert_eq!(f.name, name.clone().unwrap_name());
@@ -1438,12 +1471,7 @@ package {name} is defined in two different locations:\n\
                         assert!(types.insert(*ty));
                         let ty = &self.types[*ty];
                         assert_eq!(ty.name, Some(name.clone().unwrap_name()));
-
-                        // TODO: `Resolve::merge_worlds` doesn't uphold this
-                        // invariant, and that should be fixed.
-                        if false {
-                            assert_eq!(ty.owner, TypeOwner::World(id));
-                        }
+                        assert_eq!(ty.owner, TypeOwner::World(id));
                     }
                 }
             }
diff --git a/crates/wit-parser/src/resolve/clone.rs b/crates/wit-parser/src/resolve/clone.rs
new file mode 100644
index 00000000..21885df5
--- /dev/null
+++ b/crates/wit-parser/src/resolve/clone.rs
@@ -0,0 +1,199 @@
+//! A helper, non public, module to assist with cloning items within a
+//! `Resolve`.
+//!
+//! Cloning items is not as simple as calling `Clone` due to the nature of how
+//! `TypeId` tracks relationships between interfaces and types. A full deep
+//! clone requires walking the full structure and allocating new id links. This
+//! is akin to, for example, creating a deep copy of an `Rc<T>` by calling
+//! `Clone for T`.
+//!
+//! This is currently used when merging worlds together to help copy anonymously
+//! named items from one world to another.
+//!
+//! The general structure of this module is that each method takes a mutable
+//! reference to an AST item and updates it as necessary internally, delegating
+//! to other methods for internal AST items.
+//!
+//! This module does not at the time of this writing have full support for
+//! cloning everything within a `Resolve`.
+
+use crate::*;
+use std::collections::HashMap;
+
+pub struct Cloner<'a> {
+    resolve: &'a mut Resolve,
+    prev_owner: TypeOwner,
+    new_owner: TypeOwner,
+
+    /// This map keeps track, in the current scope of types, of all copied
+    /// types. This deduplicates copying types to ensure that they're only
+    /// copied at most once.
+    types: HashMap<TypeId, TypeId>,
+}
+
+impl<'a> Cloner<'a> {
+    pub fn new(
+        resolve: &'a mut Resolve,
+        prev_owner: TypeOwner,
+        new_owner: TypeOwner,
+    ) -> Cloner<'a> {
+        Cloner {
+            prev_owner,
+            new_owner,
+            resolve,
+            types: Default::default(),
+        }
+    }
+
+    pub fn register_world_type_overlap(&mut self, from: WorldId, into: WorldId) {
+        let into = &self.resolve.worlds[into];
+        let from = &self.resolve.worlds[from];
+        for (name, into_import) in into.imports.iter() {
+            let WorldKey::Name(_) = name else { continue };
+            let WorldItem::Type(into_id) = into_import else {
+                continue;
+            };
+            let Some(WorldItem::Type(from_id)) = from.imports.get(name) else {
+                continue;
+            };
+            self.types.insert(*from_id, *into_id);
+        }
+    }
+
+    pub fn world_item(&mut self, key: &WorldKey, item: &mut WorldItem) {
+        match key {
+            WorldKey::Name(_) => {}
+            WorldKey::Interface(_) => return,
+        }
+
+        match item {
+            WorldItem::Type(t) => {
+                self.type_id(t);
+            }
+            WorldItem::Function(f) => {
+                self.function(f);
+            }
+            WorldItem::Interface { id, .. } => {
+                self.interface(id);
+            }
+        }
+    }
+
+    fn type_id(&mut self, ty: &mut TypeId) {
+        if !self.types.contains_key(ty) {
+            let mut new = self.resolve.types[*ty].clone();
+            self.type_def(&mut new);
+            let id = self.resolve.types.alloc(new);
+            self.types.insert(*ty, id);
+        }
+        *ty = self.types[ty];
+    }
+
+    fn type_def(&mut self, def: &mut TypeDef) {
+        if def.owner != TypeOwner::None {
+            assert_eq!(def.owner, self.prev_owner);
+            def.owner = self.new_owner;
+        }
+        match &mut def.kind {
+            TypeDefKind::Type(Type::Id(id)) => {
+                if self.resolve.types[*id].owner == self.prev_owner {
+                    self.type_id(id);
+                } else {
+                    // ..
+                }
+            }
+            TypeDefKind::Type(_)
+            | TypeDefKind::Resource
+            | TypeDefKind::Flags(_)
+            | TypeDefKind::Enum(_) => {}
+            TypeDefKind::Handle(Handle::Own(ty) | Handle::Borrow(ty)) => {
+                self.type_id(ty);
+            }
+            TypeDefKind::Option(ty) | TypeDefKind::List(ty) => {
+                self.ty(ty);
+            }
+            TypeDefKind::Tuple(list) => {
+                for ty in list.types.iter_mut() {
+                    self.ty(ty);
+                }
+            }
+            TypeDefKind::Record(r) => {
+                for field in r.fields.iter_mut() {
+                    self.ty(&mut field.ty);
+                }
+            }
+            TypeDefKind::Variant(r) => {
+                for case in r.cases.iter_mut() {
+                    if let Some(ty) = &mut case.ty {
+                        self.ty(ty);
+                    }
+                }
+            }
+            TypeDefKind::Result(r) => {
+                if let Some(ok) = &mut r.ok {
+                    self.ty(ok);
+                }
+                if let Some(err) = &mut r.err {
+                    self.ty(err);
+                }
+            }
+            TypeDefKind::Future(f) => {
+                if let Some(ty) = f {
+                    self.ty(ty);
+                }
+            }
+            TypeDefKind::Stream(_) => unimplemented!(),
+            TypeDefKind::Unknown => {}
+        }
+    }
+
+    fn ty(&mut self, ty: &mut Type) {
+        match ty {
+            Type::Id(id) => self.type_id(id),
+            _ => {}
+        }
+    }
+
+    fn function(&mut self, func: &mut Function) {
+        match &mut func.kind {
+            FunctionKind::Freestanding => {}
+            FunctionKind::Method(id) | FunctionKind::Static(id) | FunctionKind::Constructor(id) => {
+                self.type_id(id)
+            }
+        }
+        for (_, ty) in func.params.iter_mut() {
+            self.ty(ty);
+        }
+        match &mut func.results {
+            Results::Named(named) => {
+                for (_, ty) in named {
+                    self.ty(ty);
+                }
+            }
+            Results::Anon(ty) => self.ty(ty),
+        }
+    }
+
+    fn interface(&mut self, id: &mut InterfaceId) {
+        let mut new = self.resolve.interfaces[*id].clone();
+        let next_id = self.resolve.interfaces.next_id();
+        let mut clone = Cloner::new(
+            self.resolve,
+            TypeOwner::Interface(*id),
+            TypeOwner::Interface(next_id),
+        );
+        for id in new.types.values_mut() {
+            clone.type_id(id);
+        }
+        for func in new.functions.values_mut() {
+            clone.function(func);
+        }
+        new.package = Some(match self.new_owner {
+            TypeOwner::Interface(id) => self.resolve.interfaces[id].package.unwrap(),
+            TypeOwner::World(id) => self.resolve.worlds[id].package.unwrap(),
+            TypeOwner::None => unreachable!(),
+        });
+        *id = self.resolve.interfaces.alloc(new);
+        assert_eq!(*id, next_id);
+    }
+}
diff --git a/fuzz/src/lib.rs b/fuzz/src/lib.rs
index 4f1de6de..72219d10 100644
--- a/fuzz/src/lib.rs
+++ b/fuzz/src/lib.rs
@@ -23,18 +23,10 @@ pub fn generate_valid_module(
 
     // These are disabled in the swarm config by default, but we want to test
     // them. Use the input data to determine whether these features are enabled.
-    config.simd_enabled = u.arbitrary()?;
-    config.relaxed_simd_enabled = config.simd_enabled && u.arbitrary()?;
     config.memory64_enabled = u.arbitrary()?;
-    config.threads_enabled = u.arbitrary()?;
-    config.exceptions_enabled = u.arbitrary()?;
     config.canonicalize_nans = u.arbitrary()?;
-    config.tail_call_enabled = u.arbitrary()?;
     config.custom_page_sizes_enabled = u.arbitrary()?;
 
-    config.gc_enabled = u.arbitrary()?;
-    config.reference_types_enabled = config.reference_types_enabled || config.gc_enabled;
-
     configure(&mut config, u)?;
 
     // Use wasm-smith to generate an arbitrary module and convert it to wasm
@@ -81,7 +73,21 @@ pub fn generate_valid_component(
 }
 
 pub fn validator_for_config(config: &Config) -> wasmparser::Validator {
-    let mut features = WasmFeatures::default();
+    // Start with the bare-bones set of features that wasm started with. Then
+    // wasm-smith doesn't have knobs to enable/disable mutable globals so
+    // unconditionally enable that as well.
+    let mut features = WasmFeatures::WASM1 | WasmFeatures::MUTABLE_GLOBAL;
+
+    // Next conditionally enable/disable features based on `config`.
+    features.set(
+        WasmFeatures::SIGN_EXTENSION,
+        config.sign_extension_ops_enabled,
+    );
+    features.set(WasmFeatures::TAIL_CALL, config.tail_call_enabled);
+    features.set(
+        WasmFeatures::SATURATING_FLOAT_TO_INT,
+        config.saturating_float_to_int_enabled,
+    );
     features.set(WasmFeatures::MULTI_VALUE, config.multi_value_enabled);
     features.set(WasmFeatures::MULTI_MEMORY, config.max_memories > 1);
     features.set(WasmFeatures::BULK_MEMORY, config.bulk_memory_enabled);
diff --git a/fuzz/src/mutate.rs b/fuzz/src/mutate.rs
index b67e356f..88b51c89 100644
--- a/fuzz/src/mutate.rs
+++ b/fuzz/src/mutate.rs
@@ -11,9 +11,10 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
 
     let mut seed = 0;
     let mut preserve_semantics = false;
-    let (wasm, _config) = crate::generate_valid_module(u, |config, u| {
-        config.exceptions_enabled = false;
-        config.gc_enabled = false;
+    let (wasm, _config) = crate::generate_valid_module(u, |_config, u| {
+        // NB: wasm-mutate is a general-purpose tool so unsupported proposals by
+        // wasm-mutate are not disabled here. Those must be rejected with a
+        // first-class error in wasm-mutate instead of panicking.
         seed = u.arbitrary()?;
         preserve_semantics = u.arbitrary()?;
         Ok(())


Test patch:
diff --git a/crates/wasm-smith/tests/common/mod.rs b/crates/wasm-smith/tests/common/mod.rs
index 688bb87f..ae8cf676 100644
--- a/crates/wasm-smith/tests/common/mod.rs
+++ b/crates/wasm-smith/tests/common/mod.rs
@@ -25,6 +25,7 @@ pub fn parser_features_from_config(config: &Config) -> WasmFeatures {
     features.set(WasmFeatures::TAIL_CALL, config.tail_call_enabled);
     features.set(WasmFeatures::FUNCTION_REFERENCES, config.gc_enabled);
     features.set(WasmFeatures::GC, config.gc_enabled);
+    features.set(WasmFeatures::THREADS, config.threads_enabled);
     features.set(
         WasmFeatures::CUSTOM_PAGE_SIZES,
         config.custom_page_sizes_enabled,
diff --git a/crates/wasm-smith/tests/core.rs b/crates/wasm-smith/tests/core.rs
index d7972f29..279dca2f 100644
--- a/crates/wasm-smith/tests/core.rs
+++ b/crates/wasm-smith/tests/core.rs
@@ -93,6 +93,8 @@ fn smoke_can_smith_valid_webassembly_one_point_oh() {
         cfg.relaxed_simd_enabled = false;
         cfg.exceptions_enabled = false;
         cfg.memory64_enabled = false;
+        cfg.reference_types_enabled = false;
+        cfg.gc_enabled = false;
         cfg.max_memories = 1;
         cfg.max_tables = 1;
         let features = parser_features_from_config(&cfg);
diff --git a/tests/cli/print-interfaces-in-world-correctly.wit b/tests/cli/print-interfaces-in-world-correctly.wit
new file mode 100644
index 00000000..cc090e91
--- /dev/null
+++ b/tests/cli/print-interfaces-in-world-correctly.wit
@@ -0,0 +1,24 @@
+// RUN: component wit %
+
+package foo:bar;
+
+world foo {
+  import a: interface {
+    use local.{t1};
+    use a:b/foreign.{t2};
+  }
+  export a: interface {
+    use local.{t1};
+    use a:b/foreign.{t2};
+  }
+}
+
+interface local {
+  type t1 = u32;
+}
+
+package a:b {
+  interface foreign {
+    type t2 = u32;
+  }
+}
diff --git a/tests/cli/print-interfaces-in-world-correctly.wit.stdout b/tests/cli/print-interfaces-in-world-correctly.wit.stdout
new file mode 100644
index 00000000..56ae5efa
--- /dev/null
+++ b/tests/cli/print-interfaces-in-world-correctly.wit.stdout
@@ -0,0 +1,25 @@
+/// RUN: component wit %
+package foo:bar;
+
+interface local {
+  type t1 = u32;
+}
+
+world foo {
+  import local;
+  import a:b/foreign;
+  import a: interface {
+    use local.{t1};
+    use a:b/foreign.{t2};
+  }
+
+  export a: interface {
+    use local.{t1};
+    use a:b/foreign.{t2};
+  }
+}
+package a:b {
+  interface foreign {
+    type t2 = u32;
+  }
+}
diff --git a/tests/cli/reparent-anonymous-interfaces-on-merge.wit b/tests/cli/reparent-anonymous-interfaces-on-merge.wit
new file mode 100644
index 00000000..62979034
--- /dev/null
+++ b/tests/cli/reparent-anonymous-interfaces-on-merge.wit
@@ -0,0 +1,19 @@
+// RUN: component embed --dummy --world w1 % | \
+//      component embed         --world w2 % | \
+//      component embed         --world w3 % | \
+//      component embed         --world w4 % | \
+//      component wit
+
+package a:b;
+
+world w1 {}
+world w2 {
+  import a: interface {}
+}
+world w3 {
+  export a: interface {}
+}
+world w4 {
+  import b: interface {}
+  export b: interface {}
+}
diff --git a/tests/cli/reparent-anonymous-interfaces-on-merge.wit.stdout b/tests/cli/reparent-anonymous-interfaces-on-merge.wit.stdout
new file mode 100644
index 00000000..2b8ca640
--- /dev/null
+++ b/tests/cli/reparent-anonymous-interfaces-on-merge.wit.stdout
@@ -0,0 +1,32 @@
+package root:root;
+
+world root {
+  import a: interface {
+  }
+  import b: interface {
+  }
+
+  export a: interface {
+  }
+  export b: interface {
+  }
+}
+package a:b {
+  world w1 {
+  }
+  world w2 {
+    import a: interface {
+    }
+  }
+  world w3 {
+    export a: interface {
+    }
+  }
+  world w4 {
+    import b: interface {
+    }
+
+    export b: interface {
+    }
+  }
+}
diff --git a/tests/cli/world-merge-add-resource-func.wit b/tests/cli/world-merge-add-resource-func.wit
new file mode 100644
index 00000000..f1e0e3ef
--- /dev/null
+++ b/tests/cli/world-merge-add-resource-func.wit
@@ -0,0 +1,16 @@
+// RUN: component embed --dummy --world a % | \
+//      component embed         --world b % | \
+//      component wit
+
+
+package a:b;
+
+world a {
+  resource a;
+}
+
+world b {
+  resource a {
+    constructor();
+  }
+}
diff --git a/tests/cli/world-merge-add-resource-func.wit.stdout b/tests/cli/world-merge-add-resource-func.wit.stdout
new file mode 100644
index 00000000..43a3bb6d
--- /dev/null
+++ b/tests/cli/world-merge-add-resource-func.wit.stdout
@@ -0,0 +1,17 @@
+package root:root;
+
+world root {
+  resource a {
+    constructor();
+  }
+}
+package a:b {
+  world a {
+    resource a;
+  }
+  world b {
+    resource a {
+      constructor();
+    }
+  }
+}