Repository: bytecodealliance/wasm-tools
Pull request #2161 (2025-04-28 18:11:55)

Add support for `include`  to `wit-smith`
This commit updates the fuzz-generation of WIT documents to use `include` in worlds. Getting this implemented was surprisingly tricky and required some careful balancing of various constructs in generation in addition to support for round-tripping.

My hope is that this makes it easier to next add support for stability in fuzzing to enable the fuzzers to find https://github.com/bytecodealliance/wasm-tools/issues/2113


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 37d28184..a540e3bf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2105,6 +2105,7 @@ dependencies = [
  "env_logger",
  "libfuzzer-sys",
  "log",
+ "rand",
  "tempfile",
  "wasm-encoder 0.229.0",
  "wasm-mutate",
diff --git a/Cargo.toml b/Cargo.toml
index 7ce17299..b0b1736a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -65,6 +65,8 @@ rust-2024-incompatible-pat = 'warn'
 missing-unsafe-on-extern = 'warn'
 unsafe-op-in-unsafe-fn = 'warn'
 
+unexpected_cfgs = { level = 'warn', check-cfg = ['cfg(fuzzing)'] }
+
 [workspace.lints.clippy]
 # The default set of lints in Clippy is viewed as "too noisy" right now so
 # they're all turned off by default. Selective lints are then enabled below as
diff --git a/crates/wit-component/src/encoding/wit.rs b/crates/wit-component/src/encoding/wit.rs
index 5e2b0b02..5c433724 100644
--- a/crates/wit-component/src/encoding/wit.rs
+++ b/crates/wit-component/src/encoding/wit.rs
@@ -71,30 +71,8 @@ pub fn encode_world(resolve: &Resolve, world_id: WorldId) -> Result<ComponentTyp
     let world = &resolve.worlds[world_id];
     log::trace!("encoding world {}", world.name);
 
-    // This sort is similar in purpose to the sort below in
-    // `encode_instance`, but different in its sort. The purpose here is
-    // to ensure that when a document is either printed as WIT or
-    // encoded as wasm that decoding from those artifacts produces the
-    // same WIT package. Namely both encoding processes should encode
-    // things in the same order.
-    //
-    // When printing worlds in WIT freestanding function imports are
-    // printed first, then types. Resource functions are attached to
-    // types which means that they all come last. Sort all
-    // resource-related functions here to the back of the `imports` list
-    // while keeping everything else in front, using a stable sort to
-    // preserve preexisting ordering.
-    let mut imports = world.imports.iter().collect::<Vec<_>>();
-    imports.sort_by_key(|(_name, import)| match import {
-        WorldItem::Function(f) => match f.kind {
-            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => 0,
-            _ => 1,
-        },
-        _ => 0,
-    });
-
     // Encode the imports
-    for (name, import) in imports {
+    for (name, import) in world.imports.iter() {
         let name = resolve.name_world_key(name);
         log::trace!("encoding import {name}");
         let ty = match import {
diff --git a/crates/wit-component/src/printing.rs b/crates/wit-component/src/printing.rs
index 3292fd05..5a657935 100644
--- a/crates/wit-component/src/printing.rs
+++ b/crates/wit-component/src/printing.rs
@@ -383,12 +383,32 @@ impl<O: Output> WitPrinter<O> {
         Ok(())
     }
 
+    /// Prints the world `id` within `resolve`.
+    ///
+    /// This is a little tricky to preserve round-tripping that WIT wants. This
+    /// function inherently can't preserve ordering of imports because resource
+    /// functions aren't guaranteed to be all adjacent to the resource itself
+    /// they're attached to. That means that at the very least, when printing
+    /// resource functions, items may be printed out-of-order.
+    ///
+    /// To help solve this the printing here is kept in sync with WIT encoding
+    /// of worlds which is to print items in the order of:
+    ///
+    /// * Any imported interface. Ordering between interfaces is preserved.
+    /// * Any types, including resource functions on those types. Ordering
+    ///   between types is preserved.
+    /// * Any functions, which may refer to those types. Ordering between
+    ///   functions is preserved.
+    ///
+    /// This keeps things printed in a roughly topological fashion and makes
+    /// round-tripping a bit more reliable.
     fn print_world(&mut self, resolve: &Resolve, id: WorldId) -> Result<()> {
         let prev_items = mem::replace(&mut self.any_items, false);
         let world = &resolve.worlds[id];
         let pkgid = world.package.unwrap();
         let mut types = Vec::new();
         let mut resource_funcs = HashMap::new();
+        let mut function_imports_to_print = Vec::new();
         for (name, import) in world.imports.iter() {
             match import {
                 WorldItem::Type(t) => match name {
@@ -401,6 +421,8 @@ impl<O: Output> WitPrinter<O> {
                             resource_funcs.entry(id).or_insert(Vec::new()).push(f);
                             continue;
                         }
+                        function_imports_to_print.push((name, import));
+                        continue;
                     }
                     self.print_world_item(resolve, name, import, pkgid, "import")?;
                     // Don't put a blank line between imports, but count
@@ -416,6 +438,11 @@ impl<O: Output> WitPrinter<O> {
             types.into_iter(),
             &resource_funcs,
         )?;
+
+        for (name, import) in function_imports_to_print {
+            self.print_world_item(resolve, name, import, pkgid, "import")?;
+            self.any_items = true;
+        }
         if !world.exports.is_empty() {
             self.new_item();
         }
diff --git a/crates/wit-parser/src/resolve.rs b/crates/wit-parser/src/resolve.rs
index 8950dcd1..f2ebd1c8 100644
--- a/crates/wit-parser/src/resolve.rs
+++ b/crates/wit-parser/src/resolve.rs
@@ -1931,7 +1931,52 @@ package {name} is defined in two different locations:\n\
         // topological order between them.
         let mut new_imports = IndexMap::new();
         let world = &self.worlds[world_id];
-        for (name, item) in world.imports.iter() {
+
+        // Sort the imports by "class" to ensure that this matches the order
+        // that items are printed and that items are in topological order.
+        //
+        // When printing worlds in WIT:
+        //
+        // * interfaces come first
+        // * types are next
+        //   * type imports are first
+        //   * type definitions are next
+        //   * resource definitions have methods printed inline
+        // * freestanding functions are last
+        //
+        // This reflects the topological order between items where types
+        // can refer to imports and functions can refer to these types. Ordering
+        // within a single class (e.g. imports depending on each other, types
+        // referring to each other) is already preserved by other passes in this
+        // file and general AST resolution. That means that a stable sort here
+        // can be used to ensure that each class is in the right location
+        // relative to the others.
+        //
+        // Overall this ensures that round-trips of WIT through wasm should
+        // always produce the same result.
+        let sort_key = |resolve: &Resolve, item: &WorldItem| match item {
+            WorldItem::Interface { .. } => 0,
+            WorldItem::Type(ty) => {
+                let ty = &resolve.types[*ty];
+                match ty.kind {
+                    TypeDefKind::Type(Type::Id(t)) if resolve.types[t].owner != ty.owner => 1,
+                    _ => 2,
+                }
+            }
+            WorldItem::Function(f) => {
+                if f.kind.resource().is_none() {
+                    3
+                } else {
+                    4
+                }
+            }
+        };
+
+        // Sort world items when we start to elaborate the world to start with a
+        // topological view of items.
+        let mut world_imports = world.imports.iter().collect::<Vec<_>>();
+        world_imports.sort_by_key(|(_name, import)| sort_key(self, import));
+        for (name, item) in world_imports {
             match item {
                 // Interfaces get their dependencies added first followed by the
                 // interface itself.
@@ -1987,6 +2032,11 @@ package {name} is defined in two different locations:\n\
 
         self.elaborate_world_exports(&export_interfaces, &mut new_imports, &mut new_exports)?;
 
+        // In addition to sorting at the start of elaboration also sort here at
+        // the end of elaboration to handle types being interspersed with
+        // interfaces as they're found.
+        new_imports.sort_by_cached_key(|_name, import| sort_key(self, import));
+
         // And with all that done the world is updated in-place with
         // imports/exports.
         log::trace!("imports = {:?}", new_imports);
diff --git a/crates/wit-smith/src/generate.rs b/crates/wit-smith/src/generate.rs
index d02edc41..02b5de3d 100644
--- a/crates/wit-smith/src/generate.rs
+++ b/crates/wit-smith/src/generate.rs
@@ -1,30 +1,27 @@
 use crate::config::Config;
 use arbitrary::{Arbitrary, Result, Unstructured};
-use indexmap::IndexMap;
+use indexmap::{IndexMap, IndexSet};
 use semver::Version;
 use std::collections::hash_map::{Entry, HashMap};
 use std::collections::HashSet;
 use std::fmt::Write;
+use std::mem;
 use std::rc::Rc;
 use std::str;
 use wit_parser::*;
 
 pub struct Generator {
     config: Config,
-    packages: PackageList,
+    packages: Packages,
     next_interface_id: u32,
 }
 
-type TypeList = Vec<Type>;
-type InterfaceList = IndexMap<String, FileInterface>;
-type PackageList = Vec<(PackageName, InterfaceList)>;
-
 struct InterfaceGenerator<'a> {
     generator: &'a Generator,
     file: &'a mut File,
     config: &'a Config,
     unique_names: HashSet<String>,
-    types_in_interface: TypeList,
+    types_in_interface: Vec<Type>,
 }
 
 #[derive(Clone)]
@@ -34,9 +31,17 @@ struct Type {
     is_resource: bool,
 }
 
+#[derive(Default)]
+struct Packages {
+    list: Vec<Package>,
+    packages_with_interfaces: Vec<usize>,
+    packages_with_worlds: Vec<usize>,
+}
+
 pub struct Package {
     pub name: PackageName,
     pub sources: SourceMap,
+    file: File,
 }
 
 #[derive(Clone)]
@@ -56,23 +61,26 @@ impl Generator {
     }
 
     pub fn generate(&mut self, u: &mut Unstructured<'_>) -> Result<Vec<Package>> {
-        let mut packages = Vec::new();
         let mut names = HashSet::new();
-        while packages.len() < self.config.max_packages && packages.is_empty() {
-            let (pkg, interfaces) = self.gen_package(u, &mut names)?;
-            if interfaces.len() > 0 {
-                self.packages.push((pkg.name.clone(), interfaces));
+        while self.packages.list.len() < self.config.max_packages && self.packages.list.is_empty() {
+            let pkg = self.gen_package(u, &mut names)?;
+            let i = self.packages.list.len();
+            if pkg.file.interfaces.len() > 0 {
+                self.packages.packages_with_interfaces.push(i);
+            }
+            if pkg.file.worlds.len() > 0 {
+                self.packages.packages_with_worlds.push(i);
             }
-            packages.push(pkg);
+            self.packages.list.push(pkg);
         }
-        Ok(packages)
+        Ok(mem::take(&mut self.packages.list))
     }
 
     fn gen_package(
         &mut self,
         u: &mut Unstructured<'_>,
         names: &mut HashSet<String>,
-    ) -> Result<(Package, InterfaceList)> {
+    ) -> Result<Package> {
         let namespace = gen_unique_name(u, names)?;
         let name = gen_unique_name(u, names)?;
         let version = if u.arbitrary()? {
@@ -86,6 +94,7 @@ impl Generator {
                 name,
                 version,
             },
+            file: File::default(),
             sources: SourceMap::new(),
         };
 
@@ -101,7 +110,6 @@ impl Generator {
         let mut empty = true;
         let mut files = vec![File::default()];
         let mut package_names = HashSet::new();
-        let mut package = File::default();
         log::debug!("===================== new package ====================");
         while items < self.config.max_pkg_items {
             items += 1;
@@ -114,15 +122,7 @@ impl Generator {
             let file = match files.get_mut(i) {
                 Some(file) => file,
                 None => {
-                    files.push(File {
-                        items: Vec::new(),
-                        namespace: package
-                            .interfaces
-                            .iter()
-                            .map(|(k, _)| (k.clone(), Definition::Package))
-                            .collect(),
-                        interfaces: package.interfaces.clone(),
-                    });
+                    files.push(ret.file.clone());
                     files.last_mut().unwrap()
                 }
             };
@@ -137,15 +137,37 @@ impl Generator {
 
             match generate {
                 Generate::World => {
-                    let name = file.gen_unique_package_name(u, &mut package_names)?;
+                    let name =
+                        file.gen_unique_package_name(u, &mut package_names, DefinitionKind::World)?;
                     log::debug!("new world `{name}` in {i}");
                     let world = self.gen_world(u, &name, file)?;
                     file.items.push(world);
 
+                    // Insert the world at the package and file level, asserting
+                    // uniqueness.
+                    assert!(ret.file.worlds.insert(name.clone()));
+                    assert!(file.worlds.insert(name.clone()));
+                    let prev = ret.file.namespace.insert(
+                        name.clone(),
+                        (DefinitionLevel::Package, DefinitionKind::World),
+                    );
+                    assert!(prev.is_none());
+
+                    // Insert the definition into all other files as well.
+                    for file in files.iter_mut() {
+                        if file.insert_definition(&name, DefinitionKind::World) {
+                            assert!(file.worlds.insert(name.clone()));
+                        }
+                    }
+
                     empty = false;
                 }
                 Generate::Interface => {
-                    let name = file.gen_unique_package_name(u, &mut package_names)?;
+                    let name = file.gen_unique_package_name(
+                        u,
+                        &mut package_names,
+                        DefinitionKind::Interface,
+                    )?;
                     log::debug!("new interface `{name}` in {i}");
                     let id = self.next_interface_id;
                     self.next_interface_id += 1;
@@ -162,10 +184,16 @@ impl Generator {
 
                     // This interface is defined at the package level, and it
                     // must be unique.
-                    let prev = package
+                    let prev = ret
+                        .file
                         .interfaces
                         .insert(interface.name.clone(), interface.clone());
                     assert!(prev.is_none());
+                    let prev = ret.file.namespace.insert(
+                        interface.name.clone(),
+                        (DefinitionLevel::Package, DefinitionKind::Interface),
+                    );
+                    assert!(prev.is_none());
 
                     // This is also defined at the file level, and it must be
                     // unique here too.
@@ -176,7 +204,12 @@ impl Generator {
 
                     // Insert the definition into all other files as well.
                     for file in files.iter_mut() {
-                        file.insert_definition(interface.clone());
+                        if file.insert_definition(&interface.name, DefinitionKind::Interface) {
+                            let prev = file
+                                .interfaces
+                                .insert(interface.name.clone(), interface.clone());
+                            assert!(prev.is_none());
+                        }
                     }
 
                     empty = false;
@@ -184,24 +217,38 @@ impl Generator {
                 Generate::Use => {
                     let mut piece = String::new();
                     piece.push_str("use ");
-                    let (name, id, types) = match self.gen_path(u, &mut package, &mut piece)? {
-                        Some(i) => i,
-                        None => continue,
-                    };
+                    let (name, id, types) =
+                        match self.gen_interface_path(u, &mut ret.file, &mut piece)? {
+                            Some(i) => i,
+                            None => continue,
+                        };
                     let name = name.to_string();
                     let types = types.clone();
+                    // If this interface's name already exist within this `file`
+                    // then this must be renamed with `as`. If the name exists
+                    // only at the package level then it's ok to replace it with
+                    // something else.
+                    //
+                    // If the name doesn't exist then use the fuzz input to
+                    // determine whether a rename should happen.
                     let name =
-                        if file.namespace.get(&name) == Some(&Definition::File) || u.arbitrary()? {
-                            let name = file.gen_unique_file_name(u)?;
+                        if matches!(file.namespace.get(&name), Some((DefinitionLevel::File, _)))
+                            || u.arbitrary()?
+                        {
+                            let name = file.gen_unique_file_name(u, DefinitionKind::Interface)?;
                             piece.push_str(" as %");
                             piece.push_str(&name);
                             name
                         } else {
-                            file.namespace.insert(name.clone(), Definition::File);
+                            file.namespace.insert(
+                                name.clone(),
+                                (DefinitionLevel::File, DefinitionKind::Interface),
+                            );
                             name
                         };
                     piece.push_str(";");
                     log::debug!("new use `{name}` in {i}");
+                    file.worlds.swap_remove(&name);
                     file.interfaces
                         .insert(name.clone(), FileInterface { name, id, types });
                     file.items.push(piece)
@@ -240,7 +287,7 @@ impl Generator {
             log::trace!("{s}");
             ret.sources.push(format!("wit{i}.wit").as_ref(), &s);
         }
-        Ok((ret, package.interfaces))
+        Ok(ret)
     }
 
     fn gen_world(
@@ -257,18 +304,18 @@ impl Generator {
         u: &mut Unstructured<'_>,
         name: Option<&str>,
         file: &mut File,
-    ) -> Result<(String, TypeList)> {
+    ) -> Result<(String, Vec<Type>)> {
         let mut generator = InterfaceGenerator::new(self, file);
         let ret = generator.gen_interface(u, name)?;
         Ok((ret, generator.types_in_interface))
     }
 
-    fn gen_path<'a>(
+    fn gen_interface_path<'a>(
         &'a self,
         u: &mut Unstructured<'_>,
         file: &'a mut File,
         dst: &mut String,
-    ) -> Result<Option<(&'a str, u32, &'a Rc<TypeList>)>> {
+    ) -> Result<Option<(&'a str, u32, &'a Rc<Vec<Type>>)>> {
         enum Choice {
             Interfaces,
             Packages,
@@ -277,9 +324,10 @@ impl Generator {
         if !file.interfaces.is_empty() {
             choices.push(Choice::Interfaces);
         }
-        if !self.packages.is_empty() {
+        if !self.packages.packages_with_interfaces.is_empty() {
             choices.push(Choice::Packages);
         }
+
         if choices.is_empty() {
             return Ok(None);
         }
@@ -290,30 +338,90 @@ impl Generator {
                 // Once a name is used from a file's local namespace then it
                 // can't be overridden in that namespace so switch it to a file
                 // definition from whatever it previously was.
-                file.namespace.insert(name.clone(), Definition::File);
+                file.namespace.insert(
+                    name.clone(),
+                    (DefinitionLevel::File, DefinitionKind::Interface),
+                );
+                file.worlds.swap_remove(name);
                 dst.push_str("%");
                 dst.push_str(&i.name);
                 Some((&i.name, i.id, &i.types))
             }
             Choice::Packages => {
-                let (pkg, ifaces) = u.choose(&self.packages)?;
+                let pkg = u.choose(&self.packages.packages_with_interfaces)?;
+                let pkg = &self.packages.list[*pkg];
                 dst.push_str("%");
-                dst.push_str(&pkg.namespace);
+                dst.push_str(&pkg.name.namespace);
                 dst.push_str(":");
                 dst.push_str("%");
-                dst.push_str(&pkg.name);
+                dst.push_str(&pkg.name.name);
                 dst.push_str("/");
-                let i = u.int_in_range(0..=ifaces.len() - 1)?;
-                let i = &ifaces[i];
+                let i = u.int_in_range(0..=pkg.file.interfaces.len() - 1)?;
+                let i = &pkg.file.interfaces[i];
                 dst.push_str("%");
                 dst.push_str(&i.name);
-                if let Some(version) = &pkg.version {
+                if let Some(version) = &pkg.name.version {
                     dst.push_str(&format!("@{version}"));
                 }
                 Some((&i.name, i.id, &i.types))
             }
         })
     }
+
+    fn gen_world_path<'a>(
+        &'a self,
+        u: &mut Unstructured<'_>,
+        file: &'a mut File,
+        dst: &mut String,
+    ) -> Result<Option<&'a str>> {
+        enum Choice {
+            Worlds,
+            Packages,
+        }
+        let mut choices = Vec::new();
+        if !file.worlds.is_empty() {
+            choices.push(Choice::Worlds);
+        }
+        if !self.packages.packages_with_worlds.is_empty() {
+            choices.push(Choice::Packages);
+        }
+
+        if choices.is_empty() {
+            return Ok(None);
+        }
+        Ok(match u.choose(&choices)? {
+            Choice::Worlds => {
+                let i = u.int_in_range(0..=file.worlds.len() - 1)?;
+                let name = &file.worlds[i];
+                dst.push_str("%");
+                dst.push_str(&name);
+                // Same as `gen_interface_path`, once a name is used as a world
+                // it's forced to always be a world so update its definition to
+                // be a file-level world.
+                file.namespace
+                    .insert(name.clone(), (DefinitionLevel::File, DefinitionKind::World));
+                Some(name)
+            }
+            Choice::Packages => {
+                let pkg = u.choose(&self.packages.packages_with_worlds)?;
+                let pkg = &self.packages.list[*pkg];
+                dst.push_str("%");
+                dst.push_str(&pkg.name.namespace);
+                dst.push_str(":");
+                dst.push_str("%");
+                dst.push_str(&pkg.name.name);
+                dst.push_str("/");
+                let i = u.int_in_range(0..=pkg.file.worlds.len() - 1)?;
+                let w = &pkg.file.worlds[i];
+                dst.push_str("%");
+                dst.push_str(&w);
+                if let Some(version) = &pkg.name.version {
+                    dst.push_str(&format!("@{version}"));
+                }
+                Some(w)
+            }
+        })
+    }
 }
 
 impl<'a> InterfaceGenerator<'a> {
@@ -406,6 +514,7 @@ impl<'a> InterfaceGenerator<'a> {
             AnonInterface(Direction),
             Type,
             Use,
+            Include,
         }
 
         let mut parts = Vec::new();
@@ -423,6 +532,7 @@ impl<'a> InterfaceGenerator<'a> {
                 ItemKind::Interface(dir) => (Some(dir), false),
                 ItemKind::Type => (None, true),
                 ItemKind::Use => (None, false),
+                ItemKind::Include => (None, false),
             };
 
             let mut part = String::new();
@@ -454,7 +564,7 @@ impl<'a> InterfaceGenerator<'a> {
                     self.gen_func_sig(u, &mut part, false)?;
                 }
                 ItemKind::Interface(dir) => {
-                    let id = match self.generator.gen_path(u, self.file, &mut part)? {
+                    let id = match self.generator.gen_interface_path(u, self.file, &mut part)? {
                         Some((_name, id, _types)) => id,
                         // If an interface couldn't be chosen or wasn't
                         // chosen then skip this import. A unique name was
@@ -506,6 +616,20 @@ impl<'a> InterfaceGenerator<'a> {
                         continue;
                     }
                 }
+
+                ItemKind::Include => {
+                    part.push_str("include ");
+                    if self
+                        .generator
+                        .gen_world_path(u, self.file, &mut part)?
+                        .is_none()
+                    {
+                        // If an interface couldn't be chosen or wasn't
+                        // chosen then skip this include.
+                        continue;
+                    }
+                    part.push_str(";");
+                }
             }
             parts.push(part);
         }
@@ -578,10 +702,11 @@ impl<'a> InterfaceGenerator<'a> {
 
     fn gen_use(&mut self, u: &mut Unstructured<'_>, part: &mut String) -> Result<bool> {
         let mut path = String::new();
-        let (_name, _id, types) = match self.generator.gen_path(u, self.file, &mut path)? {
-            Some(types) => types,
-            None => return Ok(false),
-        };
+        let (_name, _id, types) =
+            match self.generator.gen_interface_path(u, self.file, &mut path)? {
+                Some(types) => types,
+                None => return Ok(false),
+            };
         part.push_str("use ");
         part.push_str(&path);
         part.push_str(".{");
@@ -963,31 +1088,39 @@ fn shuffle<T>(u: &mut Unstructured<'_>, mut slice: &mut [T]) -> Result<()> {
     Ok(())
 }
 
-#[derive(Default)]
+#[derive(Clone, Default)]
 struct File {
     items: Vec<String>,
-    namespace: HashMap<String, Definition>,
+    namespace: HashMap<String, (DefinitionLevel, DefinitionKind)>,
     interfaces: IndexMap<String, FileInterface>,
+    worlds: IndexSet<String>,
 }
 
 #[derive(Clone)]
 struct FileInterface {
     name: String,
     id: u32,
-    types: Rc<TypeList>,
+    types: Rc<Vec<Type>>,
 }
 
-#[derive(PartialEq)]
-enum Definition {
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum DefinitionLevel {
     Package,
     File,
 }
 
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum DefinitionKind {
+    World,
+    Interface,
+}
+
 impl File {
     fn gen_unique_package_name(
         &mut self,
         u: &mut Unstructured<'_>,
         names: &mut HashSet<String>,
+        kind: DefinitionKind,
     ) -> Result<String> {
         let mut name = gen_name(u)?;
         loop {
@@ -998,32 +1131,36 @@ impl File {
             }
 
             // Then make sure it's file-unique too
-            if self.claim_file_name(&mut name) {
+            if self.claim_file_name(&mut name, kind) {
                 break;
             }
         }
         Ok(name)
     }
 
-    fn gen_unique_file_name(&mut self, u: &mut Unstructured<'_>) -> Result<String> {
+    fn gen_unique_file_name(
+        &mut self,
+        u: &mut Unstructured<'_>,
+        kind: DefinitionKind,
+    ) -> Result<String> {
         let mut name = gen_name(u)?;
-        while !self.claim_file_name(&mut name) {
+        while !self.claim_file_name(&mut name, kind) {
             // try again on the next iteration
         }
         Ok(name)
     }
 
-    fn claim_file_name(&mut self, name: &mut String) -> bool {
+    fn claim_file_name(&mut self, name: &mut String, kind: DefinitionKind) -> bool {
         match self.namespace.entry(name.clone()) {
-            Entry::Occupied(mut e) => match e.get() {
+            Entry::Occupied(mut e) => match e.get().0 {
                 // If this name is already claimed elsewhere in the package
                 // then that's ok as we're going to shadow it, so switch it
                 // to a file definition.
-                Definition::Package => *e.get_mut() = Definition::File,
+                DefinitionLevel::Package => *e.get_mut() = (DefinitionLevel::File, kind),
 
                 // If it's already defined in the file try to add more stuff
                 // to the name to make the next try not collide.
-                Definition::File => {
+                DefinitionLevel::File => {
                     name.push_str("y");
                     write!(name, "{}", self.namespace.len()).unwrap();
                     return false;
@@ -1032,22 +1169,26 @@ impl File {
 
             // Not defined? Claim it.
             Entry::Vacant(v) => {
-                v.insert(Definition::File);
+                v.insert((DefinitionLevel::File, kind));
             }
         }
         true
     }
 
-    fn insert_definition(&mut self, def: FileInterface) {
-        match self.namespace.get(&def.name) {
-            Some(Definition::File) => return,
-            Some(Definition::Package) => unreachable!(),
+    fn insert_definition(&mut self, name: &str, kind: DefinitionKind) -> bool {
+        match self.namespace.get(name) {
+            // This name is already defined, so it can't be inserted.
+            Some((DefinitionLevel::File, _)) => return false,
+            Some(other) => {
+                panic!("found duplicate definition when should be package-unique: {other:?}")
+            }
             None => {}
         }
-        let prev = self.namespace.insert(def.name.clone(), Definition::Package);
-        assert!(prev.is_none());
-        let prev = self.interfaces.insert(def.name.clone(), def);
+        let prev = self
+            .namespace
+            .insert(name.to_string(), (DefinitionLevel::Package, kind));
         assert!(prev.is_none());
+        true
     }
 }
 
diff --git a/crates/wit-smith/src/lib.rs b/crates/wit-smith/src/lib.rs
index 73e6df68..b29ab4b2 100644
--- a/crates/wit-smith/src/lib.rs
+++ b/crates/wit-smith/src/lib.rs
@@ -28,6 +28,9 @@ pub fn smith(config: &Config, u: &mut Unstructured<'_>) -> Result<Vec<u8>> {
                 if e.is::<InvalidTransitiveDependency>() {
                     return Err(arbitrary::Error::IncorrectFormat);
                 }
+                if e.to_string().contains("shadows previously") {
+                    return Err(arbitrary::Error::IncorrectFormat);
+                }
                 panic!("bad wit parse: {e:?}")
             }
         };
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
index 658c2015..f5152552 100644
--- a/fuzz/Cargo.toml
+++ b/fuzz/Cargo.toml
@@ -14,7 +14,6 @@ workspace = true
 anyhow = { workspace = true }
 arbitrary = { workspace = true }
 env_logger = { workspace = true }
-libfuzzer-sys = { workspace = true }
 log = { workspace = true }
 tempfile = "3.0"
 wasm-encoder = { workspace = true }
@@ -37,8 +36,13 @@ version = '0.214.0'
 package = 'wit-component'
 version = '0.214.0'
 
+[target.'cfg(fuzzing)'.dependencies]
+libfuzzer-sys = { workspace = true }
+
+[dev-dependencies]
+rand = { workspace = true }
+
 [lib]
-test = false
 doctest = false
 
 [[bin]]
diff --git a/fuzz/fuzz_targets/run.rs b/fuzz/fuzz_targets/run.rs
index 45275329..b9e08a8b 100644
--- a/fuzz/fuzz_targets/run.rs
+++ b/fuzz/fuzz_targets/run.rs
@@ -1,9 +1,19 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
 
 use arbitrary::Unstructured;
-use libfuzzer_sys::fuzz_target;
 use std::sync::OnceLock;
 
+#[cfg(fuzzing)]
+use libfuzzer_sys::fuzz_target;
+#[cfg(not(fuzzing))]
+macro_rules! fuzz_target {
+    ($e:expr) => {
+        fn main() {
+            let _ = $e(&[]);
+        }
+    };
+}
+
 // Helper macro which takes a static list of fuzzers as input which are then
 // delegated to internally based on the fuzz target selected.
 //
diff --git a/fuzz/src/incremental_parse.rs b/fuzz/src/incremental_parse.rs
index 42fc2461..5817cf0f 100644
--- a/fuzz/src/incremental_parse.rs
+++ b/fuzz/src/incremental_parse.rs
@@ -217,3 +217,8 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
     }
     Ok(())
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}
diff --git a/fuzz/src/lib.rs b/fuzz/src/lib.rs
index ff0af0a2..6f34f68b 100644
--- a/fuzz/src/lib.rs
+++ b/fuzz/src/lib.rs
@@ -1,4 +1,4 @@
-use libfuzzer_sys::arbitrary::{Result, Unstructured};
+use arbitrary::{Result, Unstructured};
 use std::fmt::Debug;
 use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
 use wasm_smith::{Component, Config, Module};
@@ -105,3 +105,39 @@ pub fn log_wasm(wasm: &[u8], config: impl Debug) {
         drop(std::fs::remove_file(&wat_file));
     }
 }
+#[cfg(test)]
+mod test {
+    use arbitrary::{Result, Unstructured};
+    use rand::{rngs::SmallRng, RngCore, SeedableRng};
+
+    fn gen_until_pass(mut f: impl FnMut(&mut Unstructured<'_>) -> Result<bool>) -> bool {
+        let mut rng = SmallRng::seed_from_u64(0);
+        let mut buf = vec![0; 2048];
+        let n = 3000;
+        for _ in 0..n {
+            rng.fill_bytes(&mut buf);
+            let mut u = Unstructured::new(&buf);
+
+            if f(&mut u).unwrap() {
+                return true;
+            }
+        }
+        false
+    }
+
+    /// Runs `f` with random data until it returns `Ok(())` `iters` times.
+    pub fn test_n_times(
+        iters: u32,
+        mut f: impl FnMut(&mut Unstructured<'_>) -> arbitrary::Result<()>,
+    ) {
+        let mut to_test = 0..iters;
+        let ok = gen_until_pass(|b| {
+            if f(b).is_ok() {
+                Ok(to_test.next().is_none())
+            } else {
+                Ok(false)
+            }
+        });
+        assert!(ok);
+    }
+}
diff --git a/fuzz/src/mutate.rs b/fuzz/src/mutate.rs
index 88d37902..c0c295b4 100644
--- a/fuzz/src/mutate.rs
+++ b/fuzz/src/mutate.rs
@@ -329,3 +329,8 @@ mod eval {
         }
     }
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}
diff --git a/fuzz/src/no_traps.rs b/fuzz/src/no_traps.rs
index b3d7d81a..9f6f5df4 100644
--- a/fuzz/src/no_traps.rs
+++ b/fuzz/src/no_traps.rs
@@ -122,3 +122,8 @@ fn validate_module(wasm_bytes: &Vec<u8>) {
         panic!("Invalid module: {e}");
     }
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}
diff --git a/fuzz/src/print.rs b/fuzz/src/print.rs
index 1e549f32..6723d4c6 100644
--- a/fuzz/src/print.rs
+++ b/fuzz/src/print.rs
@@ -13,3 +13,8 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
     let _ = cfg.print(&data, &mut wasmprinter::PrintFmtWrite(&mut dst));
     Ok(())
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}
diff --git a/fuzz/src/reencode.rs b/fuzz/src/reencode.rs
index 7e27dbb3..692ef23f 100644
--- a/fuzz/src/reencode.rs
+++ b/fuzz/src/reencode.rs
@@ -19,3 +19,8 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
 
     Ok(())
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}
diff --git a/fuzz/src/roundtrip_wit.rs b/fuzz/src/roundtrip_wit.rs
index 6f5e3c41..b1eb5ba8 100644
--- a/fuzz/src/roundtrip_wit.rs
+++ b/fuzz/src/roundtrip_wit.rs
@@ -188,3 +188,8 @@ impl Reencode for RemoveImports<'_, '_> {
         }
     }
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}
diff --git a/fuzz/src/validate.rs b/fuzz/src/validate.rs
index ff14c187..2b87023b 100644
--- a/fuzz/src/validate.rs
+++ b/fuzz/src/validate.rs
@@ -109,3 +109,8 @@ fn validate_all(u: &mut Unstructured<'_>, mut validator: Validator, wasm: &[u8])
 
     Ok(())
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}
diff --git a/fuzz/src/validate_valid_module.rs b/fuzz/src/validate_valid_module.rs
index ff23e336..dc471673 100644
--- a/fuzz/src/validate_valid_module.rs
+++ b/fuzz/src/validate_valid_module.rs
@@ -66,3 +66,8 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
     }
     Ok(())
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}
diff --git a/fuzz/src/wit64.rs b/fuzz/src/wit64.rs
index 6060b754..cbaa7012 100644
--- a/fuzz/src/wit64.rs
+++ b/fuzz/src/wit64.rs
@@ -118,3 +118,8 @@ fn write_file(path: &str, contents: impl AsRef<[u8]>) {
         std::fs::write(path, wasmprinter::print_bytes(&contents).unwrap()).unwrap();
     }
 }
+
+#[test]
+fn smoke() {
+    super::test::test_n_times(100, run);
+}


Test patch:
diff --git a/crates/wit-component/tests/interfaces/doc-comments/foo.wit.print b/crates/wit-component/tests/interfaces/doc-comments/foo.wit.print
index 3ef196c3..7f31dbf9 100644
--- a/crates/wit-component/tests/interfaces/doc-comments/foo.wit.print
+++ b/crates/wit-component/tests/interfaces/doc-comments/foo.wit.print
@@ -60,11 +60,10 @@ interface other-comment-forms {
 
 /// world docs
 world coverage-world {
-  /// world func import docs
-  import imp: func();
-
   /// world typedef docs
   type t = u32;
+  /// world func import docs
+  import imp: func();
 
   /// world func export docs
   export exp: func();
diff --git a/crates/wit-component/tests/interfaces/resources.wat b/crates/wit-component/tests/interfaces/resources.wat
index 3d07b806..c4a8a9d3 100644
--- a/crates/wit-component/tests/interfaces/resources.wat
+++ b/crates/wit-component/tests/interfaces/resources.wat
@@ -100,6 +100,20 @@
       (type (;0;)
         (component
           (type (;0;)
+            (instance
+              (export (;0;) "a" (type (sub resource)))
+              (type (;1;) (own 0))
+              (type (;2;) (func (result 1)))
+              (export (;0;) "[constructor]a" (func (type 2)))
+              (type (;3;) (func))
+              (export (;1;) "[static]a.b" (func (type 3)))
+              (type (;4;) (borrow 0))
+              (type (;5;) (func (param "self" 4)))
+              (export (;2;) "[method]a.c" (func (type 5)))
+            )
+          )
+          (import "anon" (instance (;0;) (type 0)))
+          (type (;1;)
             (instance
               (export (;0;) "bar" (type (sub resource)))
               (export (;1;) "t" (type (eq 0)))
@@ -117,14 +131,14 @@
               (export (;3;) "a" (func (type 9)))
             )
           )
-          (import "foo:bar/foo" (instance (;0;) (type 0)))
-          (alias export 0 "bar" (type (;1;)))
-          (alias export 0 "t" (type (;2;)))
-          (type (;3;)
+          (import "foo:bar/foo" (instance (;1;) (type 1)))
+          (alias export 1 "bar" (type (;2;)))
+          (alias export 1 "t" (type (;3;)))
+          (type (;4;)
             (instance
-              (alias outer 1 1 (type (;0;)))
+              (alias outer 1 2 (type (;0;)))
               (export (;1;) "bar" (type (eq 0)))
-              (alias outer 1 2 (type (;2;)))
+              (alias outer 1 3 (type (;2;)))
               (export (;3;) "t" (type (eq 2)))
               (type (;4;) (own 1))
               (type (;5;) (func (param "x" 4) (result 4)))
@@ -134,29 +148,15 @@
               (export (;1;) "b" (func (type 7)))
             )
           )
-          (import "foo:bar/baz" (instance (;1;) (type 3)))
-          (alias export 1 "bar" (type (;4;)))
-          (import "bar" (type (;5;) (eq 4)))
-          (import "a" (type (;6;) (sub resource)))
-          (type (;7;)
-            (instance
-              (export (;0;) "a" (type (sub resource)))
-              (type (;1;) (own 0))
-              (type (;2;) (func (result 1)))
-              (export (;0;) "[constructor]a" (func (type 2)))
-              (type (;3;) (func))
-              (export (;1;) "[static]a.b" (func (type 3)))
-              (type (;4;) (borrow 0))
-              (type (;5;) (func (param "self" 4)))
-              (export (;2;) "[method]a.c" (func (type 5)))
-            )
-          )
-          (import "anon" (instance (;2;) (type 7)))
-          (type (;8;) (own 6))
+          (import "foo:bar/baz" (instance (;2;) (type 4)))
+          (alias export 2 "bar" (type (;5;)))
+          (import "bar" (type (;6;) (eq 5)))
+          (import "a" (type (;7;) (sub resource)))
+          (type (;8;) (own 7))
           (type (;9;) (func (result 8)))
           (import "[constructor]a" (func (;0;) (type 9)))
           (export (;1;) "x" (func (type 9)))
-          (type (;10;) (own 5))
+          (type (;10;) (own 6))
           (type (;11;) (func (result 10)))
           (export (;2;) "y" (func (type 11)))
         )
diff --git a/crates/wit-component/tests/interfaces/resources.wit.print b/crates/wit-component/tests/interfaces/resources.wit.print
index 6f386b6d..c52d6744 100644
--- a/crates/wit-component/tests/interfaces/resources.wit.print
+++ b/crates/wit-component/tests/interfaces/resources.wit.print
@@ -50,8 +50,6 @@ interface implicit-own-handles2 {
 }
 
 world some-world {
-  import foo;
-  import baz;
   import anon: interface {
     resource a {
       constructor();
@@ -59,6 +57,8 @@ world some-world {
       c: func();
     }
   }
+  import foo;
+  import baz;
   use baz.{bar};
 
   resource a {
diff --git a/crates/wit-component/tests/interfaces/world-top-level.wat b/crates/wit-component/tests/interfaces/world-top-level.wat
index 347066ec..4afcebfc 100644
--- a/crates/wit-component/tests/interfaces/world-top-level.wat
+++ b/crates/wit-component/tests/interfaces/world-top-level.wat
@@ -3,15 +3,15 @@
     (component
       (type (;0;)
         (component
-          (type (;0;) (func))
-          (import "foo" (func (;0;) (type 0)))
-          (type (;1;) (func (param "arg" u32)))
-          (import "bar" (func (;1;) (type 1)))
-          (type (;2;)
+          (type (;0;)
             (instance)
           )
-          (import "some-interface" (instance (;0;) (type 2)))
-          (export (;2;) "foo2" (func (type 0)))
+          (import "some-interface" (instance (;0;) (type 0)))
+          (type (;1;) (func))
+          (import "foo" (func (;0;) (type 1)))
+          (type (;2;) (func (param "arg" u32)))
+          (import "bar" (func (;1;) (type 2)))
+          (export (;2;) "foo2" (func (type 1)))
           (type (;3;) (func (result u32)))
           (export (;3;) "bar2" (func (type 3)))
           (type (;4;)
diff --git a/crates/wit-component/tests/interfaces/world-top-level.wit.print b/crates/wit-component/tests/interfaces/world-top-level.wit.print
index 5308f654..b28325ef 100644
--- a/crates/wit-component/tests/interfaces/world-top-level.wit.print
+++ b/crates/wit-component/tests/interfaces/world-top-level.wit.print
@@ -1,10 +1,10 @@
 package foo:foo;
 
 world foo {
-  import foo: func();
-  import bar: func(arg: u32);
   import some-interface: interface {
   }
+  import foo: func();
+  import bar: func(arg: u32);
 
   export foo2: func();
   export bar2: func() -> u32;
diff --git a/crates/wit-component/tests/interfaces/worlds-with-types.wit.print b/crates/wit-component/tests/interfaces/worlds-with-types.wit.print
index 147e1219..1c4d0e3d 100644
--- a/crates/wit-component/tests/interfaces/worlds-with-types.wit.print
+++ b/crates/wit-component/tests/interfaces/worlds-with-types.wit.print
@@ -5,20 +5,19 @@ interface import-me {
 }
 
 world simple {
-  import a: func(a: foo) -> bar;
-
   record foo {
     f: u8,
   }
 
   type bar = foo;
+  import a: func(a: foo) -> bar;
 
   export b: func(a: foo) -> bar;
 }
 world with-imports {
   import import-me;
-  import a: func(a: foo);
   use import-me.{foo};
+  import a: func(a: foo);
 
   export b: func(a: foo);
 }
diff --git a/crates/wit-parser/tests/ui/gated-include-use-with-stable.wit.json b/crates/wit-parser/tests/ui/gated-include-use-with-stable.wit.json
index 471d6b4c..b7f857b1 100644
--- a/crates/wit-parser/tests/ui/gated-include-use-with-stable.wit.json
+++ b/crates/wit-parser/tests/ui/gated-include-use-with-stable.wit.json
@@ -106,9 +106,6 @@
             }
           }
         },
-        "stable-resource": {
-          "type": 3
-        },
         "interface-1": {
           "interface": {
             "id": 1,
@@ -119,9 +116,6 @@
             }
           }
         },
-        "unversioned-resource": {
-          "type": 4
-        },
         "interface-0": {
           "interface": {
             "id": 0,
@@ -132,6 +126,12 @@
             }
           }
         },
+        "stable-resource": {
+          "type": 3
+        },
+        "unversioned-resource": {
+          "type": 4
+        },
         "unstable-resource": {
           "type": 5
         }
@@ -157,9 +157,6 @@
             }
           }
         },
-        "stable-resource": {
-          "type": 3
-        },
         "interface-1": {
           "interface": {
             "id": 1,
@@ -170,9 +167,6 @@
             }
           }
         },
-        "unversioned-resource": {
-          "type": 4
-        },
         "interface-0": {
           "interface": {
             "id": 0,
@@ -183,6 +177,12 @@
             }
           }
         },
+        "stable-resource": {
+          "type": 3
+        },
+        "unversioned-resource": {
+          "type": 4
+        },
         "unstable-resource": {
           "type": 5
         }
diff --git a/crates/wit-parser/tests/ui/since-and-unstable.wit.json b/crates/wit-parser/tests/ui/since-and-unstable.wit.json
index ad483746..851694ac 100644
--- a/crates/wit-parser/tests/ui/since-and-unstable.wit.json
+++ b/crates/wit-parser/tests/ui/since-and-unstable.wit.json
@@ -25,6 +25,26 @@
     {
       "name": "in-a-world",
       "imports": {
+        "y": {
+          "interface": {
+            "id": 6,
+            "stability": {
+              "stable": {
+                "since": "1.0.0"
+              }
+            }
+          }
+        },
+        "interface-4": {
+          "interface": {
+            "id": 4,
+            "stability": {
+              "stable": {
+                "since": "1.0.0"
+              }
+            }
+          }
+        },
         "t1": {
           "type": 11
         },
@@ -58,26 +78,6 @@
             }
           }
         },
-        "y": {
-          "interface": {
-            "id": 6,
-            "stability": {
-              "stable": {
-                "since": "1.0.0"
-              }
-            }
-          }
-        },
-        "interface-4": {
-          "interface": {
-            "id": 4,
-            "stability": {
-              "stable": {
-                "since": "1.0.0"
-              }
-            }
-          }
-        },
         "[constructor]t7": {
           "function": {
             "name": "[constructor]t7",
diff --git a/tests/cli/importize.wit.simple-rename.stdout b/tests/cli/importize.wit.simple-rename.stdout
index 64612e20..1514dbe8 100644
--- a/tests/cli/importize.wit.simple-rename.stdout
+++ b/tests/cli/importize.wit.simple-rename.stdout
@@ -78,11 +78,11 @@ world fail1 {
 }
 world trim-imports {
   import a;
-  import foo: func();
   import bar: interface {
   }
 
   type t = u32;
+  import foo: func();
 
   export b;
 }
diff --git a/tests/cli/importize.wit.simple-toplevel.stdout b/tests/cli/importize.wit.simple-toplevel.stdout
index 10aff4d9..47994748 100644
--- a/tests/cli/importize.wit.simple-toplevel.stdout
+++ b/tests/cli/importize.wit.simple-toplevel.stdout
@@ -75,11 +75,11 @@ world fail1 {
 }
 world trim-imports {
   import a;
-  import foo: func();
   import bar: interface {
   }
 
   type t = u32;
+  import foo: func();
 
   export b;
 }
@@ -90,8 +90,8 @@ world tricky-import {
   export f: func() -> t;
 }
 world simple-toplevel-importized {
-  import foo: func();
   import something: interface {
     foo: func();
   }
+  import foo: func();
 }
diff --git a/tests/cli/importize.wit.simple.stdout b/tests/cli/importize.wit.simple.stdout
index 1bdb5c80..7e13e853 100644
--- a/tests/cli/importize.wit.simple.stdout
+++ b/tests/cli/importize.wit.simple.stdout
@@ -78,11 +78,11 @@ world fail1 {
 }
 world trim-imports {
   import a;
-  import foo: func();
   import bar: interface {
   }
 
   type t = u32;
+  import foo: func();
 
   export b;
 }
diff --git a/tests/cli/importize.wit.toplevel-deps.stdout b/tests/cli/importize.wit.toplevel-deps.stdout
index e187bd06..f9247fc1 100644
--- a/tests/cli/importize.wit.toplevel-deps.stdout
+++ b/tests/cli/importize.wit.toplevel-deps.stdout
@@ -69,11 +69,11 @@ world fail1 {
 }
 world trim-imports {
   import a;
-  import foo: func();
   import bar: interface {
   }
 
   type t = u32;
+  import foo: func();
 
   export b;
 }
@@ -84,7 +84,6 @@ world tricky-import {
   export f: func() -> t;
 }
 world toplevel-deps-importized {
-  import bar: func() -> s;
   import something-else-dep;
   import something-else: interface {
     use something-else-dep.{t};
@@ -93,4 +92,5 @@ world toplevel-deps-importized {
   }
 
   type s = u32;
+  import bar: func() -> s;
 }
diff --git a/tests/cli/importize.wit.tricky-import.stdout b/tests/cli/importize.wit.tricky-import.stdout
index 08d2d563..c89d0acf 100644
--- a/tests/cli/importize.wit.tricky-import.stdout
+++ b/tests/cli/importize.wit.tricky-import.stdout
@@ -81,16 +81,16 @@ world fail1 {
 }
 world trim-imports {
   import a;
-  import foo: func();
   import bar: interface {
   }
 
   type t = u32;
+  import foo: func();
 
   export b;
 }
 world tricky-import-importized {
   import with-dep;
-  import f: func() -> t;
   use with-dep.{t};
+  import f: func() -> t;
 }
diff --git a/tests/cli/importize.wit.with-deps.stdout b/tests/cli/importize.wit.with-deps.stdout
index 9b567ad3..97bef88d 100644
--- a/tests/cli/importize.wit.with-deps.stdout
+++ b/tests/cli/importize.wit.with-deps.stdout
@@ -75,11 +75,11 @@ world fail1 {
 }
 world trim-imports {
   import a;
-  import foo: func();
   import bar: interface {
   }
 
   type t = u32;
+  import foo: func();
 
   export b;
 }
diff --git a/tests/cli/wit-stability-in-binary-format.wit.stdout b/tests/cli/wit-stability-in-binary-format.wit.stdout
index 45db6e8b..54a0a939 100644
--- a/tests/cli/wit-stability-in-binary-format.wit.stdout
+++ b/tests/cli/wit-stability-in-binary-format.wit.stdout
@@ -25,13 +25,13 @@ world w {
   @since(version = 1.0.0)
   import foo;
   @since(version = 1.0.0)
-  import f: func();
-  @since(version = 1.0.0)
   import a: interface {
   }
 
   @since(version = 1.0.0)
   type t = u32;
+  @since(version = 1.0.0)
+  import f: func();
 
   @since(version = 1.0.0)
   export f: func();
diff --git a/tests/cli/wit-with-features.wit.stdout b/tests/cli/wit-with-features.wit.stdout
index b402b6aa..f188b45e 100644
--- a/tests/cli/wit-with-features.wit.stdout
+++ b/tests/cli/wit-with-features.wit.stdout
@@ -39,14 +39,14 @@ interface another-interface {
 world the-world {
   @unstable(feature = foo)
   import foo;
-  @unstable(feature = foo)
-  import x: func();
 
   @unstable(feature = foo)
   resource thing {
     @unstable(feature = foo)
     constructor();
   }
+  @unstable(feature = foo)
+  import x: func();
 
   @unstable(feature = foo)
   export y: func();
diff --git a/tests/cli/world-merging-add-imports.wit.stdout b/tests/cli/world-merging-add-imports.wit.stdout
index 6f0064d4..80d325e6 100644
--- a/tests/cli/world-merging-add-imports.wit.stdout
+++ b/tests/cli/world-merging-add-imports.wit.stdout
@@ -1,11 +1,11 @@
 package root:root;
 
 world root {
-  import a:b/b;
   import a: interface {
   }
-  import c: func() -> t;
+  import a:b/b;
   use a:b/b.{t};
+  import c: func() -> t;
 }
 package a:b {
   interface b {
@@ -14,10 +14,10 @@ package a:b {
   world into {
   }
   world %from {
-    import b;
     import a: interface {
     }
-    import c: func() -> t;
+    import b;
     use b.{t};
+    import c: func() -> t;
   }
 }
diff --git a/tests/cli/world-merging-same-imports.wit.stdout b/tests/cli/world-merging-same-imports.wit.stdout
index 90090844..e5c366b4 100644
--- a/tests/cli/world-merging-same-imports.wit.stdout
+++ b/tests/cli/world-merging-same-imports.wit.stdout
@@ -1,28 +1,28 @@
 package root:root;
 
 world root {
-  import a:b/b;
   import a: interface {
   }
-  import c: func();
+  import a:b/b;
   use a:b/b.{t};
+  import c: func();
 }
 package a:b {
   interface b {
     type t = u32;
   }
   world into {
-    import b;
     import a: interface {
     }
-    import c: func();
+    import b;
     use b.{t};
+    import c: func();
   }
   world %from {
-    import b;
     import a: interface {
     }
-    import c: func();
+    import b;
     use b.{t};
+    import c: func();
   }
 }
diff --git a/tests/cli/world-merging.wit.stdout b/tests/cli/world-merging.wit.stdout
index abcfaefc..d18e6f53 100644
--- a/tests/cli/world-merging.wit.stdout
+++ b/tests/cli/world-merging.wit.stdout
@@ -2,8 +2,8 @@ package root:root;
 
 world root {
   import a:b/x;
-  import a: func() -> t;
   use a:b/x.{t};
+  import a: func() -> t;
 
   export y: func();
   export a:b/x;
@@ -16,8 +16,8 @@ package a:b {
   }
   world foo {
     import x;
-    import a: func() -> t;
     use x.{t};
+    import a: func() -> t;
 
     export y: func();
     export x;