Repository: bytecodealliance/wasm-tools
Pull request #1255 (2023-10-17 21:05:30)

Enable omitting versions in world selection
Similar to how if a name isn't provided and a package only has one world, if a name is provided and it looks like an "id" and there's only one package with that name/namespace combo then the package version can be omitted.


Patch:
diff --git a/crates/wit-component/src/decoding.rs b/crates/wit-component/src/decoding.rs
index 8fc5ca21..a998104a 100644
--- a/crates/wit-component/src/decoding.rs
+++ b/crates/wit-component/src/decoding.rs
@@ -27,6 +27,12 @@ enum Extern<'a> {
     Export(ComponentExport<'a>),
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum WitEncodingVersion {
+    V1,
+    V2,
+}
+
 impl<'a> ComponentInfo<'a> {
     /// Creates a new component info by parsing the given WebAssembly component bytes.
     fn new(bytes: &'a [u8]) -> Result<Self> {
@@ -79,27 +85,43 @@ impl<'a> ComponentInfo<'a> {
         })
     }
 
-    fn is_wit_package(&self) -> bool {
+    fn is_wit_package(&self) -> Option<WitEncodingVersion> {
         // all wit package exports must be component types, and there must be at
         // least one
-        !self.externs.is_empty()
-            && self.externs.iter().all(|(_, item)| {
-                let export = match item {
-                    Extern::Export(e) => e,
-                    _ => return false,
-                };
-                match export.kind {
-                    ComponentExternalKind::Type => matches!(
-                        &self.types[self.types.component_type_at(export.index)],
-                        types::Type::Component(_)
-                    ),
-                    _ => false,
-                }
-            })
+        if self.externs.is_empty() {
+            return None;
+        }
+
+        if !self.externs.iter().all(|(_, item)| {
+            let export = match item {
+                Extern::Export(e) => e,
+                _ => return false,
+            };
+            match export.kind {
+                ComponentExternalKind::Type => matches!(
+                    &self.types[self.types.component_type_at(export.index)],
+                    types::Type::Component(_)
+                ),
+                _ => false,
+            }
+        }) {
+            return None;
+        }
+
+        // The distinction between v1 and v2 encoding formats is the structure of the export
+        // strings for each component. The v1 format uses "<namespace>:<package>/wit" as the name
+        // for the top-level exports, while the v2 format uses the unqualified name of the encoded
+        // entity.
+        match KebabName::new(self.externs[0].0, 0).ok()?.kind() {
+            KebabNameKind::Id { interface, .. } if interface.as_str() == "wit" => {
+                Some(WitEncodingVersion::V1)
+            }
+            KebabNameKind::Normal(_) => Some(WitEncodingVersion::V2),
+            _ => None,
+        }
     }
 
-    fn decode_wit_package(&self) -> Result<(Resolve, PackageId)> {
-        assert!(self.is_wit_package());
+    fn decode_wit_v1_package(&self) -> Result<(Resolve, PackageId)> {
         let resolve = Resolve::default();
         let mut decoder = WitPackageDecoder {
             resolve,
@@ -125,7 +147,7 @@ impl<'a> ComponentInfo<'a> {
             let name = KebabName::new(*name, 0).unwrap();
             pkg = Some(
                 decoder
-                    .decode_package(&name, ty)
+                    .decode_v1_package(&name, ty)
                     .with_context(|| format!("failed to decode document `{name}`"))?,
             );
         }
@@ -138,8 +160,102 @@ impl<'a> ComponentInfo<'a> {
         Ok((resolve, package))
     }
 
+    fn decode_wit_v2_package(&self) -> Result<(Resolve, PackageId)> {
+        let resolve = Resolve::default();
+        let mut decoder = WitPackageDecoder {
+            resolve,
+            info: self,
+            type_map: HashMap::new(),
+            foreign_packages: Default::default(),
+            iface_to_package_index: Default::default(),
+            named_interfaces: Default::default(),
+            resources: Default::default(),
+        };
+
+        let mut pkg_name = None;
+
+        let mut interfaces = IndexMap::new();
+        let mut worlds = IndexMap::new();
+        let mut fields = PackageFields {
+            interfaces: &mut interfaces,
+            worlds: &mut worlds,
+        };
+
+        for (_, item) in self.externs.iter() {
+            let export = match item {
+                Extern::Export(e) => e,
+                _ => unreachable!(),
+            };
+
+            let index = export.index;
+            let id = self.types.component_type_at(index);
+            let component = self.types[id].unwrap_component();
+
+            // The single export of this component will determine if it's a world or an interface:
+            // worlds export a component, while interfaces export an instance.
+            if component.exports.len() != 1 {
+                bail!(
+                    "Expected a single export, but found {} instead",
+                    component.exports.len()
+                );
+            }
+
+            let name = component.exports.keys().nth(0).unwrap();
+
+            let exported = match component.exports[name] {
+                types::ComponentEntityType::Component(ty) => &self.types[ty],
+                types::ComponentEntityType::Instance(ty) => &self.types[ty],
+                _ => unreachable!(),
+            };
+
+            let name = match exported {
+                types::Type::Component(ty) => {
+                    let package_name = decoder.decode_world(name.as_str(), ty, &mut fields)?;
+                    package_name
+                }
+                types::Type::ComponentInstance(ty) => {
+                    let package_name = decoder.decode_interface(
+                        name.as_str(),
+                        &component.imports,
+                        ty,
+                        &mut fields,
+                    )?;
+                    package_name
+                }
+                _ => panic!(),
+            };
+
+            if let Some(pkg_name) = pkg_name.as_ref() {
+                // TODO: when we have fully switched to the v2 format, we should switch to parsing
+                // multiple wit documents instead of bailing.
+                if pkg_name != &name {
+                    bail!("item defined with mismatched package name")
+                }
+            } else {
+                pkg_name.replace(name);
+            }
+        }
+
+        let pkg = if let Some(name) = pkg_name {
+            Package {
+                name,
+                docs: Docs::default(),
+                interfaces,
+                worlds,
+            }
+        } else {
+            bail!("no exported component type found");
+        };
+
+        let (mut resolve, package) = decoder.finish(pkg);
+        if let Some(package_docs) = &self.package_docs {
+            package_docs.inject(&mut resolve, package)?;
+        }
+        Ok((resolve, package))
+    }
+
     fn decode_component(&self) -> Result<(Resolve, WorldId)> {
-        assert!(!self.is_wit_package());
+        assert!(self.is_wit_package().is_none());
         let mut resolve = Resolve::default();
         // Note that this name is arbitrarily chosen. We may one day perhaps
         // want to encode this in the component binary format itself, but for
@@ -177,13 +293,18 @@ impl<'a> ComponentInfo<'a> {
             interfaces: Default::default(),
         };
 
+        let mut fields = PackageFields {
+            worlds: &mut package.worlds,
+            interfaces: &mut package.interfaces,
+        };
+
         for (_name, item) in self.externs.iter() {
             match item {
                 Extern::Import(import) => {
-                    decoder.decode_component_import(import, world, &mut package)?
+                    decoder.decode_component_import(import, world, &mut fields)?
                 }
                 Extern::Export(export) => {
-                    decoder.decode_component_export(export, world, &mut package)?
+                    decoder.decode_component_export(export, world, &mut fields)?
                 }
             }
         }
@@ -234,10 +355,19 @@ impl DecodedWasm {
 pub fn decode(bytes: &[u8]) -> Result<DecodedWasm> {
     let info = ComponentInfo::new(bytes)?;
 
-    if info.is_wit_package() {
-        log::debug!("decoding a WIT package encoded as wasm");
-        let (resolve, pkg) = info.decode_wit_package()?;
-        Ok(DecodedWasm::WitPackage(resolve, pkg))
+    if let Some(version) = info.is_wit_package() {
+        match version {
+            WitEncodingVersion::V1 => {
+                log::debug!("decoding a v1 WIT package encoded as wasm");
+                let (resolve, pkg) = info.decode_wit_v1_package()?;
+                Ok(DecodedWasm::WitPackage(resolve, pkg))
+            }
+            WitEncodingVersion::V2 => {
+                log::debug!("decoding a v2 WIT package encoded as wasm");
+                let (resolve, pkg) = info.decode_wit_v2_package()?;
+                Ok(DecodedWasm::WitPackage(resolve, pkg))
+            }
+        }
     } else {
         log::debug!("inferring the WIT of a concrete component");
         let (resolve, world) = info.decode_component()?;
@@ -245,6 +375,11 @@ pub fn decode(bytes: &[u8]) -> Result<DecodedWasm> {
     }
 }
 
+struct PackageFields<'a> {
+    interfaces: &'a mut IndexMap<String, InterfaceId>,
+    worlds: &'a mut IndexMap<String, WorldId>,
+}
+
 struct WitPackageDecoder<'a> {
     resolve: Resolve,
     info: &'a ComponentInfo<'a>,
@@ -266,7 +401,11 @@ struct WitPackageDecoder<'a> {
 }
 
 impl WitPackageDecoder<'_> {
-    fn decode_package(&mut self, name: &KebabName, ty: &types::ComponentType) -> Result<Package> {
+    fn decode_v1_package(
+        &mut self,
+        name: &KebabName,
+        ty: &types::ComponentType,
+    ) -> Result<Package> {
         // Process all imports for this package first, where imports are
         // importing from remote packages.
         for (name, ty) in ty.imports.iter() {
@@ -302,16 +441,21 @@ impl WitPackageDecoder<'_> {
             worlds: Default::default(),
         };
 
+        let mut fields = PackageFields {
+            interfaces: &mut package.interfaces,
+            worlds: &mut package.worlds,
+        };
+
         for (name, ty) in ty.exports.iter() {
             match ty {
                 types::ComponentEntityType::Instance(idx) => {
                     let ty = self.info.types[*idx].unwrap_component_instance();
-                    self.register_interface(name.as_str(), ty, &mut package)
+                    self.register_interface(name.as_str(), ty, &mut fields)
                         .with_context(|| format!("failed to process export `{name}`"))?;
                 }
                 types::ComponentEntityType::Component(idx) => {
                     let ty = self.info.types[*idx].unwrap_component();
-                    self.register_world(name.as_str(), ty, &mut package)
+                    self.register_world(name.as_str(), ty, &mut fields)
                         .with_context(|| format!("failed to process export `{name}`"))?;
                 }
                 _ => bail!("component export `{name}` is not an instance or component"),
@@ -320,11 +464,81 @@ impl WitPackageDecoder<'_> {
         Ok(package)
     }
 
-    fn decode_component_import(
+    fn decode_interface<'a>(
+        &mut self,
+        name: &str,
+        imports: &IndexMap<String, types::ComponentEntityType>,
+        ty: &types::ComponentInstanceType,
+        fields: &mut PackageFields<'a>,
+    ) -> Result<PackageName> {
+        let kebab_name = self
+            .extract_kebab_name(name)
+            .context("expected world name to have an ID form")?;
+
+        let package = match kebab_name.kind() {
+            KebabNameKind::Id {
+                namespace,
+                package,
+                version,
+                ..
+            } => PackageName {
+                namespace: namespace.to_string(),
+                name: package.to_string(),
+                version,
+            },
+            _ => bail!("expected world name to be fully qualified"),
+        };
+
+        for (name, ty) in imports.iter() {
+            let ty = match ty {
+                types::ComponentEntityType::Instance(idx) => {
+                    self.info.types[*idx].unwrap_component_instance()
+                }
+                _ => bail!("import `{name}` is not an instance"),
+            };
+            self.register_import(name, ty)
+                .with_context(|| format!("failed to process import `{name}`"))?;
+        }
+
+        let _ = self.register_interface(name, ty, fields)?;
+
+        Ok(package)
+    }
+
+    fn decode_world<'a>(
+        &mut self,
+        name: &str,
+        ty: &types::ComponentType,
+        fields: &mut PackageFields<'a>,
+    ) -> Result<PackageName> {
+        let kebab_name = self
+            .extract_kebab_name(name)
+            .context("expected world name to have an ID form")?;
+
+        let package = match kebab_name.kind() {
+            KebabNameKind::Id {
+                namespace,
+                package,
+                version,
+                ..
+            } => PackageName {
+                namespace: namespace.to_string(),
+                name: package.to_string(),
+                version,
+            },
+            _ => bail!("expected world name to be fully qualified"),
+        };
+
+        let _ = self.register_world(name, ty, fields)?;
+
+        Ok(package)
+    }
+
+    fn decode_component_import<'a>(
         &mut self,
         import: &ComponentImport<'_>,
         world: WorldId,
-        package: &mut Package,
+        package: &mut PackageFields<'a>,
     ) -> Result<()> {
         let name = import.name.as_str();
         log::debug!("decoding component import `{name}`");
@@ -369,11 +583,11 @@ impl WitPackageDecoder<'_> {
         Ok(())
     }
 
-    fn decode_component_export(
+    fn decode_component_export<'a>(
         &mut self,
         export: &ComponentExport<'_>,
         world: WorldId,
-        package: &mut Package,
+        package: &mut PackageFields<'a>,
     ) -> Result<()> {
         let name = export.name.as_str();
         log::debug!("decoding component export `{name}`");
@@ -618,11 +832,11 @@ impl WitPackageDecoder<'_> {
     ///
     /// The `package` is where to insert the final interface if `name` is an ID
     /// meaning it's registered as a named standalone item within the package.
-    fn register_interface(
+    fn register_interface<'a>(
         &mut self,
         name: &str,
         ty: &types::ComponentInstanceType,
-        package: &mut Package,
+        package: &mut PackageFields<'a>,
     ) -> Result<(WorldKey, InterfaceId)> {
         // If this interface's name is already known then that means this is an
         // interface that's both imported and exported.  Use `register_import`
@@ -690,16 +904,21 @@ impl WitPackageDecoder<'_> {
         Ok((key, id))
     }
 
-    fn extract_interface_name_from_kebab_name(&self, name: &str) -> Result<Option<String>> {
+    fn extract_kebab_name(&self, name: &str) -> Result<KebabName> {
         let import_name = if name.contains('/') {
             ComponentExternName::Interface(name)
         } else {
             ComponentExternName::Kebab(name)
         };
-        let kebab_name = KebabName::new(import_name, 0);
-        match kebab_name.as_ref().map(|k| k.kind()) {
-            Ok(KebabNameKind::Id { interface, .. }) => Ok(Some(interface.to_string())),
-            Ok(KebabNameKind::Normal(_name)) => Ok(None),
+        KebabName::new(import_name, 0)
+            .with_context(|| format!("cannot extract item name from: {name}"))
+    }
+
+    fn extract_interface_name_from_kebab_name(&self, name: &str) -> Result<Option<String>> {
+        let kebab_name = self.extract_kebab_name(name)?;
+        match kebab_name.kind() {
+            KebabNameKind::Id { interface, .. } => Ok(Some(interface.to_string())),
+            KebabNameKind::Normal(_name) => Ok(None),
             _ => bail!("cannot extract item name from: {name}"),
         }
     }
@@ -757,11 +976,11 @@ impl WitPackageDecoder<'_> {
         Ok(ty)
     }
 
-    fn register_world(
+    fn register_world<'a>(
         &mut self,
         name: &str,
         ty: &types::ComponentType,
-        package: &mut Package,
+        package: &mut PackageFields<'a>,
     ) -> Result<WorldId> {
         let name = self
             .extract_interface_name_from_kebab_name(name)?
diff --git a/crates/wit-component/src/encoding/wit/mod.rs b/crates/wit-component/src/encoding/wit/mod.rs
new file mode 100644
index 00000000..72e82baf
--- /dev/null
+++ b/crates/wit-component/src/encoding/wit/mod.rs
@@ -0,0 +1,68 @@
+use anyhow::Result;
+use wasm_encoder::{ComponentBuilder, ComponentType};
+use wit_parser::{PackageId, Resolve, WorldId};
+
+mod v1;
+mod v2;
+
+const ENCODE_V2_BY_DEFAULT: bool = false;
+
+fn use_v2_encoding() -> bool {
+    match std::env::var("WIT_COMPONENT_ENCODING_V2") {
+        Ok(s) => s == "1",
+        Err(_) => ENCODE_V2_BY_DEFAULT,
+    }
+}
+
+/// Encodes the given `package` within `resolve` to a binary WebAssembly
+/// representation.
+///
+/// This function is the root of the implementation of serializing a WIT package
+/// into a WebAssembly representation. The wasm representation serves two
+/// purposes:
+///
+/// * One is to be a binary encoding of a WIT document which is ideally more
+///   stable than the WIT textual format itself.
+/// * Another is to provide a clear mapping of all WIT features into the
+///   component model through use of its binary representation.
+///
+/// The `resolve` provided is a set of packages and types and such and the
+/// `package` argument is an ID within the world provided. The documents within
+/// `package` will all be encoded into the binary returned.
+///
+/// The binary returned can be [`decode`d](crate::decode) to recover the WIT
+/// package provided.
+pub fn encode(use_v2: Option<bool>, resolve: &Resolve, package: PackageId) -> Result<Vec<u8>> {
+    if use_v2.unwrap_or_else(use_v2_encoding) {
+        v2::encode(resolve, package)
+    } else {
+        v1::encode(resolve, package)
+    }
+}
+
+/// Exactly like `encode`, except gives an unfinished `ComponentBuilder` in case you need
+/// to append anything else before finishing.
+pub fn encode_component(
+    use_v2: Option<bool>,
+    resolve: &Resolve,
+    package: PackageId,
+) -> Result<ComponentBuilder> {
+    if use_v2.unwrap_or_else(use_v2_encoding) {
+        v2::encode_component(resolve, package)
+    } else {
+        v1::encode_component(resolve, package)
+    }
+}
+
+/// Encodes a `world` as a component type.
+pub fn encode_world(
+    use_v2: Option<bool>,
+    resolve: &Resolve,
+    world_id: WorldId,
+) -> Result<ComponentType> {
+    if use_v2.unwrap_or_else(use_v2_encoding) {
+        v2::encode_world(resolve, world_id)
+    } else {
+        v1::encode_world(resolve, world_id)
+    }
+}
diff --git a/crates/wit-component/src/encoding/wit.rs b/crates/wit-component/src/encoding/wit/v1.rs
similarity index 99%
rename from crates/wit-component/src/encoding/wit.rs
rename to crates/wit-component/src/encoding/wit/v1.rs
index 0c90dcc0..e83b91b0 100644
--- a/crates/wit-component/src/encoding/wit.rs
+++ b/crates/wit-component/src/encoding/wit/v1.rs
@@ -1,4 +1,7 @@
-use crate::encoding::types::{FunctionKey, ValtypeEncoder};
+use crate::encoding::{
+    docs::PackageDocs,
+    types::{FunctionKey, ValtypeEncoder},
+};
 use anyhow::Result;
 use indexmap::IndexSet;
 use std::collections::HashMap;
@@ -6,8 +9,6 @@ use std::mem;
 use wasm_encoder::*;
 use wit_parser::*;
 
-use super::docs::PackageDocs;
-
 /// Encodes the given `package` within `resolve` to a binary WebAssembly
 /// representation.
 ///
diff --git a/crates/wit-component/src/encoding/wit/v2.rs b/crates/wit-component/src/encoding/wit/v2.rs
new file mode 100644
index 00000000..2a3a2d78
--- /dev/null
+++ b/crates/wit-component/src/encoding/wit/v2.rs
@@ -0,0 +1,417 @@
+use crate::encoding::{
+    docs::PackageDocs,
+    types::{FunctionKey, ValtypeEncoder},
+};
+use anyhow::Result;
+use indexmap::IndexSet;
+use std::collections::HashMap;
+use std::mem;
+use wasm_encoder::*;
+use wit_parser::*;
+
+/// Encodes the given `package` within `resolve` to a binary WebAssembly
+/// representation.
+///
+/// This function is the root of the implementation of serializing a WIT package
+/// into a WebAssembly representation. The wasm representation serves two
+/// purposes:
+///
+/// * One is to be a binary encoding of a WIT document which is ideally more
+///   stable than the WIT textual format itself.
+/// * Another is to provide a clear mapping of all WIT features into the
+///   component model through use of its binary representation.
+///
+/// The `resolve` provided is a set of packages and types and such and the
+/// `package` argument is an ID within the world provided. The documents within
+/// `package` will all be encoded into the binary returned.
+///
+/// The binary returned can be [`decode`d](crate::decode) to recover the WIT
+/// package provided.
+pub fn encode(resolve: &Resolve, package: PackageId) -> Result<Vec<u8>> {
+    let mut component = encode_component(resolve, package)?;
+    component.raw_custom_section(&crate::base_producers().raw_custom_section());
+    Ok(component.finish())
+}
+
+/// Exactly like `encode`, except gives an unfinished `ComponentBuilder` in case you need
+/// to append anything else before finishing.
+pub fn encode_component(resolve: &Resolve, package: PackageId) -> Result<ComponentBuilder> {
+    let mut encoder = Encoder {
+        component: ComponentBuilder::default(),
+        resolve,
+        package,
+    };
+    encoder.run()?;
+
+    let package_docs = PackageDocs::extract(resolve, package);
+    encoder
+        .component
+        .raw_custom_section(&package_docs.raw_custom_section()?);
+
+    Ok(encoder.component)
+}
+
+struct Encoder<'a> {
+    component: ComponentBuilder,
+    resolve: &'a Resolve,
+    package: PackageId,
+}
+
+impl Encoder<'_> {
+    fn run(&mut self) -> Result<()> {
+        // Build a set of interfaces reachable from this document, including the
+        // interfaces in the document itself. This is used to import instances
+        // into the component type we're encoding. Note that entire interfaces
+        // are imported with all their types as opposed to just the needed types
+        // in an interface for this document. That's done to assist with the
+        // decoding process where everyone's view of a foreign document agrees
+        // notably on the order that types are defined in to assist with
+        // roundtripping.
+        for (name, &id) in self.resolve.packages[self.package].interfaces.iter() {
+            let component_ty = self.encode_interface(id)?;
+            let ty = self.component.type_component(&component_ty);
+            self.component
+                .export(name.as_ref(), ComponentExportKind::Type, ty, None);
+        }
+
+        for (name, &world) in self.resolve.packages[self.package].worlds.iter() {
+            let component_ty = encode_world(self.resolve, world)?;
+            let ty = self.component.type_component(&component_ty);
+            self.component
+                .export(name.as_ref(), ComponentExportKind::Type, ty, None);
+        }
+
+        Ok(())
+    }
+
+    fn encode_interface(&mut self, id: InterfaceId) -> Result<ComponentType> {
+        // Build a set of interfaces reachable from this document, including the
+        // interfaces in the document itself. This is used to import instances
+        // into the component type we're encoding. Note that entire interfaces
+        // are imported with all their types as opposed to just the needed types
+        // in an interface for this document. That's done to assist with the
+        // decoding process where everyone's view of a foreign document agrees
+        // notably on the order that types are defined in to assist with
+        // roundtripping.
+        let mut interfaces = IndexSet::new();
+        self.add_live_interfaces(&mut interfaces, id);
+
+        // Seed the set of used names with all exported interfaces to ensure
+        // that imported interfaces choose different names as the import names
+        // aren't used during decoding.
+        let mut used_names = IndexSet::new();
+        for id in interfaces.iter() {
+            let iface = &self.resolve.interfaces[*id];
+            if iface.package == Some(self.package) {
+                let first = used_names.insert(iface.name.as_ref().unwrap().clone());
+                assert!(first);
+            }
+        }
+
+        let mut encoder = InterfaceEncoder::new(self.resolve);
+        for interface in interfaces {
+            encoder.interface = Some(interface);
+            let iface = &self.resolve.interfaces[interface];
+            let name = self.resolve.id_of(interface).unwrap();
+            if interface == id {
+                let idx = encoder.encode_instance(interface)?;
+                log::trace!("exporting self as {idx}");
+                encoder.outer.export(&name, ComponentTypeRef::Instance(idx));
+            } else {
+                encoder.push_instance();
+                for (_, id) in iface.types.iter() {
+                    encoder.encode_valtype(self.resolve, &Type::Id(*id))?;
+                }
+                let instance = encoder.pop_instance();
+                let idx = encoder.outer.type_count();
+                encoder.outer.ty().instance(&instance);
+                encoder.import_map.insert(interface, encoder.instances);
+                encoder.instances += 1;
+                encoder.outer.import(&name, ComponentTypeRef::Instance(idx));
+            }
+        }
+
+        encoder.interface = None;
+
+        Ok(encoder.outer)
+    }
+
+    /// Recursively add all live interfaces reachable from `id` into the
+    /// `interfaces` set, and then add `id` to the set.
+    fn add_live_interfaces(&self, interfaces: &mut IndexSet<InterfaceId>, id: InterfaceId) {
+        if interfaces.contains(&id) {
+            return;
+        }
+        for id in self.resolve.interface_direct_deps(id) {
+            self.add_live_interfaces(interfaces, id);
+        }
+        assert!(interfaces.insert(id));
+    }
+}
+
+struct InterfaceEncoder<'a> {
+    resolve: &'a Resolve,
+    outer: ComponentType,
+    ty: Option<InstanceType>,
+    func_type_map: HashMap<FunctionKey<'a>, u32>,
+    type_map: HashMap<TypeId, u32>,
+    saved_types: Option<(HashMap<TypeId, u32>, HashMap<FunctionKey<'a>, u32>)>,
+    import_map: HashMap<InterfaceId, u32>,
+    outer_type_map: HashMap<TypeId, u32>,
+    instances: u32,
+    import_types: bool,
+    interface: Option<InterfaceId>,
+}
+
+impl InterfaceEncoder<'_> {
+    fn new(resolve: &Resolve) -> InterfaceEncoder<'_> {
+        InterfaceEncoder {
+            resolve,
+            outer: ComponentType::new(),
+            ty: None,
+            type_map: Default::default(),
+            func_type_map: Default::default(),
+            import_map: Default::default(),
+            outer_type_map: Default::default(),
+            instances: 0,
+            saved_types: None,
+            import_types: false,
+            interface: None,
+        }
+    }
+
+    fn encode_instance(&mut self, interface: InterfaceId) -> Result<u32> {
+        self.push_instance();
+        let iface = &self.resolve.interfaces[interface];
+        let mut type_order = IndexSet::new();
+        for (_, id) in iface.types.iter() {
+            self.encode_valtype(self.resolve, &Type::Id(*id))?;
+            type_order.insert(*id);
+        }
+
+        // Sort functions based on whether or not they're associated with
+        // resources.
+        //
+        // This is done here to ensure that when a WIT package is printed as WIT
+        // then decoded, or if it's printed as Wasm then decoded, the final
+        // result is the same. When printing via WIT resource methods are
+        // attached to the resource types themselves meaning that they'll appear
+        // intermingled with the rest of the types, namely first before all
+        // other functions. The purpose of this sort is to perform a stable sort
+        // over all functions by shuffling the resource-related functions first,
+        // in order of when their associated resource was encoded, and putting
+        // freestanding functions last.
+        //
+        // Note that this is not actually required for correctness, it's
+        // basically here to make fuzzing happy.
+        let mut funcs = iface.functions.iter().collect::<Vec<_>>();
+        funcs.sort_by_key(|(_name, func)| match func.kind {
+            FunctionKind::Freestanding => type_order.len(),
+            FunctionKind::Method(id) | FunctionKind::Constructor(id) | FunctionKind::Static(id) => {
+                type_order.get_index_of(&id).unwrap()
+            }
+        });
+
+        for (name, func) in funcs {
+            let ty = self.encode_func_type(self.resolve, func)?;
+            self.ty
+                .as_mut()
+                .unwrap()
+                .export(name, ComponentTypeRef::Func(ty));
+        }
+        let instance = self.pop_instance();
+        let idx = self.outer.type_count();
+        self.outer.ty().instance(&instance);
+        self.import_map.insert(interface, self.instances);
+        self.instances += 1;
+        Ok(idx)
+    }
+
+    fn push_instance(&mut self) {
+        assert!(self.ty.is_none());
+        assert!(self.saved_types.is_none());
+        self.saved_types = Some((
+            mem::take(&mut self.type_map),
+            mem::take(&mut self.func_type_map),
+        ));
+        self.ty = Some(InstanceType::default());
+    }
+
+    fn pop_instance(&mut self) -> InstanceType {
+        let (types, funcs) = self.saved_types.take().unwrap();
+        self.type_map = types;
+        self.func_type_map = funcs;
+        mem::take(&mut self.ty).unwrap()
+    }
+}
+
+impl<'a> ValtypeEncoder<'a> for InterfaceEncoder<'a> {
+    fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
+        match &mut self.ty {
+            Some(ty) => (ty.type_count(), ty.ty().defined_type()),
+            None => (self.outer.type_count(), self.outer.ty().defined_type()),
+        }
+    }
+    fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
+        match &mut self.ty {
+            Some(ty) => (ty.type_count(), ty.ty().function()),
+            None => (self.outer.type_count(), self.outer.ty().function()),
+        }
+    }
+    fn export_type(&mut self, index: u32, name: &'a str) -> Option<u32> {
+        match &mut self.ty {
+            Some(ty) => {
+                assert!(!self.import_types);
+                let ret = ty.type_count();
+                ty.export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
+                Some(ret)
+            }
+            None => {
+                let ret = self.outer.type_count();
+                if self.import_types {
+                    self.outer
+                        .import(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
+                } else {
+                    self.outer
+                        .export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
+                }
+                Some(ret)
+            }
+        }
+    }
+    fn export_resource(&mut self, name: &'a str) -> u32 {
+        let type_ref = ComponentTypeRef::Type(TypeBounds::SubResource);
+        match &mut self.ty {
+            Some(ty) => {
+                assert!(!self.import_types);
+                ty.export(name, type_ref);
+                ty.type_count() - 1
+            }
+            None => {
+                if self.import_types {
+                    self.outer.import(name, type_ref);
+                } else {
+                    self.outer.export(name, type_ref);
+                }
+                self.outer.type_count() - 1
+            }
+        }
+    }
+    fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
+        &mut self.type_map
+    }
+    fn interface(&self) -> Option<InterfaceId> {
+        self.interface
+    }
+    fn import_type(&mut self, owner: InterfaceId, id: TypeId) -> u32 {
+        let ty = &self.resolve.types[id];
+        let instance = self.import_map[&owner];
+        let outer_idx = *self.outer_type_map.entry(id).or_insert_with(|| {
+            let ret = self.outer.type_count();
+            self.outer.alias(Alias::InstanceExport {
+                instance,
+                name: ty.name.as_ref().unwrap(),
+                kind: ComponentExportKind::Type,
+            });
+            ret
+        });
+        match &mut self.ty {
+            Some(ty) => {
+                let ret = ty.type_count();
+                ty.alias(Alias::Outer {
+                    count: 1,
+                    index: outer_idx,
+                    kind: ComponentOuterAliasKind::Type,
+                });
+                ret
+            }
+            None => outer_idx,
+        }
+    }
+    fn func_type_map(&mut self) -> &mut HashMap<FunctionKey<'a>, u32> {
+        &mut self.func_type_map
+    }
+}
+
+/// Encodes a `world` as a component type.
+pub fn encode_world(resolve: &Resolve, world_id: WorldId) -> Result<ComponentType> {
+    let mut encoder = InterfaceEncoder::new(resolve);
+    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 => 0,
+            _ => 1,
+        },
+        _ => 0,
+    });
+
+    // Encode the imports
+    for (name, import) in imports {
+        let name = resolve.name_world_key(name);
+        log::trace!("encoding import {name}");
+        let ty = match import {
+            WorldItem::Interface(i) => {
+                encoder.interface = Some(*i);
+                let idx = encoder.encode_instance(*i)?;
+                ComponentTypeRef::Instance(idx)
+            }
+            WorldItem::Function(f) => {
+                encoder.interface = None;
+                let idx = encoder.encode_func_type(resolve, f)?;
+                ComponentTypeRef::Func(idx)
+            }
+            WorldItem::Type(t) => {
+                encoder.interface = None;
+                encoder.import_types = true;
+                encoder.encode_valtype(resolve, &Type::Id(*t))?;
+                encoder.import_types = false;
+                continue;
+            }
+        };
+        encoder.outer.import(&name, ty);
+    }
+    // Encode the exports
+    for (name, export) in world.exports.iter() {
+        let name = resolve.name_world_key(name);
+        let ty = match export {
+            WorldItem::Interface(i) => {
+                encoder.interface = Some(*i);
+                let idx = encoder.encode_instance(*i)?;
+                ComponentTypeRef::Instance(idx)
+            }
+            WorldItem::Function(f) => {
+                encoder.interface = None;
+                let idx = encoder.encode_func_type(resolve, f)?;
+                ComponentTypeRef::Func(idx)
+            }
+            WorldItem::Type(_) => unreachable!(),
+        };
+        encoder.outer.export(&name, ty);
+    }
+
+    let mut component = ComponentType::new();
+    component.ty().component(&encoder.outer);
+
+    let name = match world.package {
+        Some(id) => resolve.packages[id].name.interface_id(&world.name),
+        None => world.name.clone(),
+    };
+    component.export(&name, ComponentTypeRef::Component(0));
+    Ok(component)
+}
diff --git a/crates/wit-component/src/metadata.rs b/crates/wit-component/src/metadata.rs
index a452e5ef..bb65aed6 100644
--- a/crates/wit-component/src/metadata.rs
+++ b/crates/wit-component/src/metadata.rs
@@ -176,7 +176,8 @@ pub fn encode(
     });
     world.name.encode(&mut ret);
     // This appends a wasm binary encoded Component to the ret:
-    let mut component_builder = crate::encoding::encode_component(resolve, world.package.unwrap())?;
+    let mut component_builder =
+        crate::encoding::encode_component(None, resolve, world.package.unwrap())?;
 
     let mut producers = crate::base_producers();
     if let Some(p) = extra_producers {
diff --git a/crates/wit-component/src/targets.rs b/crates/wit-component/src/targets.rs
index cfc252f2..c33062bc 100644
--- a/crates/wit-component/src/targets.rs
+++ b/crates/wit-component/src/targets.rs
@@ -16,7 +16,7 @@ pub fn targets(resolve: &Resolve, world: WorldId, component_to_test: &[u8]) -> R
     // (2) Encode the world to a component type and embed a new component which
     // imports the encoded component type.
     let test_component_idx = {
-        let component_ty = encode_world(resolve, world)?;
+        let component_ty = encode_world(None, resolve, world)?;
         let mut component = ComponentBuilder::default();
         let component_ty_idx = component.type_component(&component_ty);
         component.import(
diff --git a/crates/wit-parser/src/resolve.rs b/crates/wit-parser/src/resolve.rs
index f98fa4d6..8fc1e3a3 100644
--- a/crates/wit-parser/src/resolve.rs
+++ b/crates/wit-parser/src/resolve.rs
@@ -570,13 +570,34 @@ impl Resolve {
             .with_context(|| format!("failed to parse world specifier `{world}`"))?;
         let (pkg, world) = match path {
             AstUsePath::Name(name) => (pkg, name),
-            AstUsePath::Package(pkg, interface) => (
-                *self
-                    .package_names
-                    .get(&pkg)
-                    .ok_or_else(|| anyhow!("unknown package `{pkg}`"))?,
-                interface,
-            ),
+            AstUsePath::Package(pkg, interface) => {
+                let pkg = match self.package_names.get(&pkg) {
+                    Some(pkg) => *pkg,
+                    None => {
+                        let mut candidates = self.package_names.iter().filter(|(name, _)| {
+                            pkg.version.is_none()
+                                && pkg.name == name.name
+                                && pkg.namespace == name.namespace
+                                && name.version.is_some()
+                        });
+                        let candidate = candidates.next();
+                        if let Some((c2, _)) = candidates.next() {
+                            let (c1, _) = candidate.unwrap();
+                            bail!(
+                                "package name `{pkg}` is available at both \
+                                 versions {} and {} but which is not specified",
+                                c1.version.as_ref().unwrap(),
+                                c2.version.as_ref().unwrap(),
+                            );
+                        }
+                        match candidate {
+                            Some((_, id)) => *id,
+                            None => bail!("unknown package `{pkg}`"),
+                        }
+                    }
+                };
+                (pkg, interface)
+            }
         };
         let pkg = &self.packages[pkg];
         pkg.worlds
@@ -1781,3 +1802,66 @@ impl<'a> MergeMap<'a> {
         Ok(())
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::{PackageId, Resolve};
+
+    #[test]
+    fn select_world() {
+        let mut resolve = Resolve::default();
+        parse_into(
+            &mut resolve,
+            r#"
+                package foo:bar@0.1.0
+
+                world foo {}
+            "#,
+        );
+        parse_into(
+            &mut resolve,
+            r#"
+                package foo:baz@0.1.0
+
+                world foo {}
+            "#,
+        );
+        parse_into(
+            &mut resolve,
+            r#"
+                package foo:baz@0.2.0
+
+                world foo {}
+            "#,
+        );
+
+        let dummy = parse_into(
+            &mut resolve,
+            r#"
+                package foo:dummy
+
+                world foo {}
+            "#,
+        );
+
+        assert!(resolve.select_world(dummy, None).is_ok());
+        assert!(resolve.select_world(dummy, Some("xx")).is_err());
+        assert!(resolve.select_world(dummy, Some("")).is_err());
+        assert!(resolve.select_world(dummy, Some("foo:bar/foo")).is_ok());
+        assert!(resolve
+            .select_world(dummy, Some("foo:bar/foo@0.1.0"))
+            .is_ok());
+        assert!(resolve.select_world(dummy, Some("foo:baz/foo")).is_err());
+        assert!(resolve
+            .select_world(dummy, Some("foo:baz/foo@0.1.0"))
+            .is_ok());
+        assert!(resolve
+            .select_world(dummy, Some("foo:baz/foo@0.2.0"))
+            .is_ok());
+    }
+
+    fn parse_into(resolve: &mut Resolve, wit: &str) -> PackageId {
+        let pkg = crate::UnresolvedPackage::parse("input.wit".as_ref(), wit).unwrap();
+        resolve.push(pkg).unwrap()
+    }
+}
diff --git a/crates/wit-smith/src/config.rs b/crates/wit-smith/src/config.rs
index ea837c5c..948fbb73 100644
--- a/crates/wit-smith/src/config.rs
+++ b/crates/wit-smith/src/config.rs
@@ -44,7 +44,7 @@ impl Arbitrary<'_> for Config {
             max_type_size: u.int_in_range(0..=1000)?,
             max_interface_items: u.int_in_range(0..=20)?,
             max_world_items: u.int_in_range(0..=10)?,
-            max_pkg_items: u.int_in_range(0..=10)?,
+            max_pkg_items: u.int_in_range(1..=10)?,
             max_type_parts: u.int_in_range(1..=10)?,
             max_resource_items: u.int_in_range(0..=10)?,
         })
diff --git a/crates/wit-smith/src/generate.rs b/crates/wit-smith/src/generate.rs
index 66d8a7b9..aaa64783 100644
--- a/crates/wit-smith/src/generate.rs
+++ b/crates/wit-smith/src/generate.rs
@@ -58,7 +58,7 @@ impl Generator {
     pub fn gen(&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() || u.arbitrary()?) {
+        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));
@@ -89,7 +89,7 @@ impl Generator {
             sources: SourceMap::new(),
         };
 
-        #[derive(Arbitrary)]
+        #[derive(Arbitrary, Clone)]
         enum Generate {
             Interface,
             Use,
@@ -98,11 +98,12 @@ impl Generator {
         }
 
         let mut items = 0;
+        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 && !u.is_empty() {
+        while items < self.config.max_pkg_items {
             items += 1;
             let max = if files.len() < self.config.max_files_per_package {
                 files.len() + 1
@@ -125,12 +126,23 @@ impl Generator {
                     files.last_mut().unwrap()
                 }
             };
-            match u.arbitrary()? {
+
+            // Only generate Use/Done if we've already generated a world or interface. This ensures
+            // that we never generate empty packages, which aren't representable.
+            let gen = if empty {
+                u.choose(&[Generate::World, Generate::Interface])?.clone()
+            } else {
+                u.arbitrary()?
+            };
+
+            match gen {
                 Generate::World => {
                     let name = file.gen_unique_package_name(u, &mut package_names)?;
                     log::debug!("new world `{name}` in {i}");
                     let world = self.gen_world(u, &name, file)?;
                     file.items.push(world);
+
+                    empty = false;
                 }
                 Generate::Interface => {
                     let name = file.gen_unique_package_name(u, &mut package_names)?;
@@ -166,6 +178,8 @@ impl Generator {
                     for file in files.iter_mut() {
                         file.insert_definition(interface.clone());
                     }
+
+                    empty = false;
                 }
                 Generate::Use => {
                     let mut piece = String::new();
diff --git a/crates/wit-smith/src/lib.rs b/crates/wit-smith/src/lib.rs
index bbd5e863..36410ada 100644
--- a/crates/wit-smith/src/lib.rs
+++ b/crates/wit-smith/src/lib.rs
@@ -38,5 +38,5 @@ pub fn smith(config: &Config, u: &mut Unstructured<'_>) -> Result<Vec<u8>> {
     }
     let pkg = last.unwrap();
 
-    Ok(wit_component::encode(&resolve, pkg).expect("failed to encode WIT document"))
+    Ok(wit_component::encode(Some(true), &resolve, pkg).expect("failed to encode WIT document"))
 }
diff --git a/fuzz/src/roundtrip_wit.rs b/fuzz/src/roundtrip_wit.rs
index 9a6c74c2..04f29249 100644
--- a/fuzz/src/roundtrip_wit.rs
+++ b/fuzz/src/roundtrip_wit.rs
@@ -15,6 +15,7 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
         DecodedWasm::WitPackage(resolve, pkg) => (resolve, pkg),
         DecodedWasm::Component(..) => unreachable!(),
     };
+
     roundtrip_through_printing("doc1", &resolve, &wasm);
 
     let (resolve2, pkg2) = match wit_component::decode(&wasm).unwrap() {
@@ -22,7 +23,8 @@ pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
         DecodedWasm::Component(..) => unreachable!(),
     };
 
-    let wasm2 = wit_component::encode(&resolve2, pkg2).expect("failed to encode WIT document");
+    let wasm2 =
+        wit_component::encode(Some(true), &resolve2, pkg2).expect("failed to encode WIT document");
     write_file("doc2.wasm", &wasm2);
     roundtrip_through_printing("doc2", &resolve2, &wasm2);
 
@@ -80,7 +82,7 @@ fn roundtrip_through_printing(file: &str, resolve: &Resolve, wasm: &[u8]) {
 
     // Finally encode the `new_resolve` which should be the exact same as
     // before.
-    let wasm2 = wit_component::encode(&new_resolve, last.unwrap()).unwrap();
+    let wasm2 = wit_component::encode(Some(true), &new_resolve, last.unwrap()).unwrap();
     write_file(&format!("{file}-reencoded.wasm"), &wasm2);
     if wasm != wasm2 {
         panic!("failed to roundtrip through text printing");
diff --git a/src/bin/wasm-tools/component.rs b/src/bin/wasm-tools/component.rs
index 0ba7aa3b..f680fb35 100644
--- a/src/bin/wasm-tools/component.rs
+++ b/src/bin/wasm-tools/component.rs
@@ -507,7 +507,7 @@ impl WitOpts {
         assert!(self.wasm || self.wat);
         assert!(self.out_dir.is_none());
 
-        let bytes = wit_component::encode(decoded.resolve(), decoded.package())?;
+        let bytes = wit_component::encode(None, decoded.resolve(), decoded.package())?;
         if !self.skip_validation {
             wasmparser::Validator::new_with_features(wasmparser::WasmFeatures {
                 component_model: true,


Test patch:
diff --git a/crates/wit-component/tests/components/error-link-duplicate-initializers/error.txt b/crates/wit-component/tests/components/error-link-duplicate-initializers/error.txt
index 86de6c15..ecf9edd3 100644
--- a/crates/wit-component/tests/components/error-link-duplicate-initializers/error.txt
+++ b/crates/wit-component/tests/components/error-link-duplicate-initializers/error.txt
@@ -1,1 +1,1 @@
-library foo exports both `__wasm_call_ctors` and `_initialize`; expected at most one of the two
+library foo exports both `__wasm_call_ctors` and `_initialize`; expected at most one of the two
\ No newline at end of file
diff --git a/crates/wit-component/tests/interfaces.rs b/crates/wit-component/tests/interfaces.rs
index 9327d60a..0fec470c 100644
--- a/crates/wit-component/tests/interfaces.rs
+++ b/crates/wit-component/tests/interfaces.rs
@@ -55,7 +55,7 @@ fn run_test(path: &Path, is_dir: bool) -> Result<()> {
     // First convert the WIT package to a binary WebAssembly output, then
     // convert that binary wasm to textual wasm, then assert it matches the
     // expectation.
-    let wasm = wit_component::encode(&resolve, package)?;
+    let wasm = wit_component::encode(Some(true), &resolve, package)?;
     let wat = wasmprinter::print_bytes(&wasm)?;
     assert_output(&path.with_extension("wat"), &wat)?;
     wasmparser::Validator::new_with_features(features)
@@ -71,7 +71,7 @@ fn run_test(path: &Path, is_dir: bool) -> Result<()> {
 
     // Finally convert the decoded package to wasm again and make sure it
     // matches the prior wasm.
-    let wasm2 = wit_component::encode(resolve, decoded.package())?;
+    let wasm2 = wit_component::encode(Some(true), resolve, decoded.package())?;
     if wasm != wasm2 {
         let wat2 = wasmprinter::print_bytes(&wasm)?;
         assert_eq!(wat, wat2, "document did not roundtrip correctly");
diff --git a/crates/wit-component/tests/interfaces/console.wat b/crates/wit-component/tests/interfaces/console.wat
index 6aa6caf4..8825a84c 100644
--- a/crates/wit-component/tests/interfaces/console.wat
+++ b/crates/wit-component/tests/interfaces/console.wat
@@ -10,7 +10,7 @@
       (export (;0;) (interface "foo:console/console") (instance (type 0)))
     )
   )
-  (export (;1;) (interface "foo:console/wit") (type 0))
+  (export (;1;) "console" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/diamond-disambiguate.wat b/crates/wit-component/tests/interfaces/diamond-disambiguate.wat
index c7e87181..f1744b29 100644
--- a/crates/wit-component/tests/interfaces/diamond-disambiguate.wat
+++ b/crates/wit-component/tests/interfaces/diamond-disambiguate.wat
@@ -8,14 +8,24 @@
         )
       )
       (export (;0;) (interface "foo:foo/shared1") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "shared1" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (instance
           (type (;0;) u8)
           (export (;1;) "t2" (type (eq 0)))
         )
       )
-      (export (;1;) (interface "foo:foo/shared2") (instance (type 1)))
-      (type (;2;)
+      (export (;0;) (interface "foo:foo/shared2") (instance (type 0)))
+    )
+  )
+  (export (;3;) "shared2" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -49,10 +59,10 @@
           (import "bar" (instance (;3;) (type 5)))
         )
       )
-      (export (;0;) (interface "foo:foo/w1") (component (type 2)))
+      (export (;0;) (interface "foo:foo/w1") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "w1" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/diamond.wat b/crates/wit-component/tests/interfaces/diamond.wat
index ec379188..ea0da3aa 100644
--- a/crates/wit-component/tests/interfaces/diamond.wat
+++ b/crates/wit-component/tests/interfaces/diamond.wat
@@ -8,7 +8,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/shared-items") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "shared-items" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -34,8 +39,13 @@
           (import "bar" (instance (;2;) (type 3)))
         )
       )
-      (export (;0;) (interface "foo:foo/w1") (component (type 1)))
-      (type (;2;)
+      (export (;0;) (interface "foo:foo/w1") (component (type 0)))
+    )
+  )
+  (export (;3;) "w1" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -61,8 +71,13 @@
           (export (;2;) "bar" (instance (type 3)))
         )
       )
-      (export (;1;) (interface "foo:foo/w2") (component (type 2)))
-      (type (;3;)
+      (export (;0;) (interface "foo:foo/w2") (component (type 0)))
+    )
+  )
+  (export (;5;) "w2" (type 4))
+  (type (;6;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -81,10 +96,10 @@
           (export (;1;) "bar" (instance (type 2)))
         )
       )
-      (export (;2;) (interface "foo:foo/w3") (component (type 3)))
+      (export (;0;) (interface "foo:foo/w3") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;7;) "w3" (type 6))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/doc-comments.wat b/crates/wit-component/tests/interfaces/doc-comments.wat
index 7f3cd033..16dfb3ae 100644
--- a/crates/wit-component/tests/interfaces/doc-comments.wat
+++ b/crates/wit-component/tests/interfaces/doc-comments.wat
@@ -26,15 +26,25 @@
         )
       )
       (export (;0;) (interface "foo:foo/coverage-iface") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "coverage-iface" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (instance
           (type (;0;) (func))
           (export (;0;) "multiple-lines-split" (func (type 0)))
           (export (;1;) "mixed-forms" (func (type 0)))
         )
       )
-      (export (;1;) (interface "foo:foo/other-comment-forms") (instance (type 1)))
-      (type (;2;)
+      (export (;0;) (interface "foo:foo/other-comment-forms") (instance (type 0)))
+    )
+  )
+  (export (;3;) "other-comment-forms" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (component
           (type (;0;) u32)
           (import "t" (type (;1;) (eq 0)))
@@ -52,10 +62,10 @@
           (export (;0;) "i" (instance (type 3)))
         )
       )
-      (export (;0;) (interface "foo:foo/coverage-world") (component (type 2)))
+      (export (;0;) (interface "foo:foo/coverage-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "coverage-world" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/empty.wat b/crates/wit-component/tests/interfaces/empty.wat
index 02906cca..efea26d3 100644
--- a/crates/wit-component/tests/interfaces/empty.wat
+++ b/crates/wit-component/tests/interfaces/empty.wat
@@ -5,7 +5,12 @@
         (instance)
       )
       (export (;0;) (interface "foo:empty/empty") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "empty" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance)
@@ -25,14 +30,19 @@
           (export (;3;) "empty2" (instance (type 3)))
         )
       )
-      (export (;0;) (interface "foo:empty/empty-world") (component (type 1)))
-      (type (;2;)
+      (export (;0;) (interface "foo:empty/empty-world") (component (type 0)))
+    )
+  )
+  (export (;3;) "empty-world" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (component)
       )
-      (export (;1;) (interface "foo:empty/actually-empty-world") (component (type 2)))
+      (export (;0;) (interface "foo:empty/actually-empty-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:empty/wit") (type 0))
+  (export (;5;) "actually-empty-world" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/export-other-packages-interface.wat b/crates/wit-component/tests/interfaces/export-other-packages-interface.wat
index e9569e89..49329a39 100644
--- a/crates/wit-component/tests/interfaces/export-other-packages-interface.wat
+++ b/crates/wit-component/tests/interfaces/export-other-packages-interface.wat
@@ -15,7 +15,7 @@
       (export (;0;) (interface "foo:foo/foo") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;1;) "foo" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/exports.wat b/crates/wit-component/tests/interfaces/exports.wat
index 3f2bd040..99da09b4 100644
--- a/crates/wit-component/tests/interfaces/exports.wat
+++ b/crates/wit-component/tests/interfaces/exports.wat
@@ -10,7 +10,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -23,10 +28,10 @@
           (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
         )
       )
-      (export (;0;) (interface "foo:foo/export-foo") (component (type 1)))
+      (export (;0;) (interface "foo:foo/export-foo") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "export-foo" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/flags.wat b/crates/wit-component/tests/interfaces/flags.wat
index 1c07f490..b39eee54 100644
--- a/crates/wit-component/tests/interfaces/flags.wat
+++ b/crates/wit-component/tests/interfaces/flags.wat
@@ -34,7 +34,12 @@
         )
       )
       (export (;0;) (interface "foo:flags/imports") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "imports" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -71,10 +76,10 @@
           (import (interface "foo:flags/imports") (instance (;0;) (type 0)))
         )
       )
-      (export (;0;) (interface "foo:flags/flags-world") (component (type 1)))
+      (export (;0;) (interface "foo:flags/flags-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:flags/wit") (type 0))
+  (export (;3;) "flags-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/floats.wat b/crates/wit-component/tests/interfaces/floats.wat
index e974ebe8..fa163945 100644
--- a/crates/wit-component/tests/interfaces/floats.wat
+++ b/crates/wit-component/tests/interfaces/floats.wat
@@ -14,7 +14,12 @@
         )
       )
       (export (;0;) (interface "foo:floats/floats") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "floats" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -31,10 +36,10 @@
           (import (interface "foo:floats/floats") (instance (;0;) (type 0)))
         )
       )
-      (export (;0;) (interface "foo:floats/floats-world") (component (type 1)))
+      (export (;0;) (interface "foo:floats/floats-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:floats/wit") (type 0))
+  (export (;3;) "floats-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/foreign-use-chain.wat b/crates/wit-component/tests/interfaces/foreign-use-chain.wat
index c55bb5a1..d98b07a2 100644
--- a/crates/wit-component/tests/interfaces/foreign-use-chain.wat
+++ b/crates/wit-component/tests/interfaces/foreign-use-chain.wat
@@ -23,7 +23,7 @@
       (export (;0;) (interface "foo:foo/foo") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;1;) "foo" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/import-and-export.wat b/crates/wit-component/tests/interfaces/import-and-export.wat
index 627281ee..494f72e5 100644
--- a/crates/wit-component/tests/interfaces/import-and-export.wat
+++ b/crates/wit-component/tests/interfaces/import-and-export.wat
@@ -8,14 +8,24 @@
         )
       )
       (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (instance
           (type (;0;) (func))
           (export (;0;) "bar" (func (type 0)))
         )
       )
-      (export (;1;) (interface "foo:foo/bar") (instance (type 1)))
-      (type (;2;)
+      (export (;0;) (interface "foo:foo/bar") (instance (type 0)))
+    )
+  )
+  (export (;3;) "bar" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -33,10 +43,10 @@
           (export (;1;) (interface "foo:foo/bar") (instance (type 1)))
         )
       )
-      (export (;0;) (interface "foo:foo/import-and-export") (component (type 2)))
+      (export (;0;) (interface "foo:foo/import-and-export") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "import-and-export" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/integers.wat b/crates/wit-component/tests/interfaces/integers.wat
index a4baed89..dd55f771 100644
--- a/crates/wit-component/tests/interfaces/integers.wat
+++ b/crates/wit-component/tests/interfaces/integers.wat
@@ -45,7 +45,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/integers") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "integers" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -93,10 +98,10 @@
           (import (interface "foo:foo/integers") (instance (;0;) (type 0)))
         )
       )
-      (export (;0;) (interface "foo:foo/integers-world") (component (type 1)))
+      (export (;0;) (interface "foo:foo/integers-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "integers-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/lists.wat b/crates/wit-component/tests/interfaces/lists.wat
index 21940bb2..5d19e477 100644
--- a/crates/wit-component/tests/interfaces/lists.wat
+++ b/crates/wit-component/tests/interfaces/lists.wat
@@ -96,7 +96,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/lists") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "lists" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -195,10 +200,10 @@
           (import (interface "foo:foo/lists") (instance (;0;) (type 0)))
         )
       )
-      (export (;0;) (interface "foo:foo/lists-world") (component (type 1)))
+      (export (;0;) (interface "foo:foo/lists-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "lists-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/multi-doc.wat b/crates/wit-component/tests/interfaces/multi-doc.wat
index e99ce635..fff5254c 100644
--- a/crates/wit-component/tests/interfaces/multi-doc.wat
+++ b/crates/wit-component/tests/interfaces/multi-doc.wat
@@ -8,6 +8,18 @@
         )
       )
       (export (;0;) (interface "foo:foo/b") (instance (type 0)))
+    )
+  )
+  (export (;1;) "b" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) (record (field "f" u8)))
+          (export (;1;) "the-type" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:foo/b") (instance (;0;) (type 0)))
       (alias export 0 "the-type" (type (;1;)))
       (type (;2;)
         (instance
@@ -16,23 +28,49 @@
         )
       )
       (export (;1;) (interface "foo:foo/a") (instance (type 2)))
-      (type (;3;)
+    )
+  )
+  (export (;3;) "a" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) (record (field "f" u8)))
+          (export (;1;) "the-type" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:foo/b") (instance (;0;) (type 0)))
+      (alias export 0 "the-type" (type (;1;)))
+      (type (;2;)
         (instance
           (alias outer 1 1 (type (;0;)))
           (export (;1;) "the-type" (type (eq 0)))
         )
       )
-      (export (;2;) (interface "foo:foo/b2") (instance (type 3)))
-      (type (;4;)
+      (export (;1;) (interface "foo:foo/b2") (instance (type 2)))
+    )
+  )
+  (export (;5;) "b2" (type 4))
+  (type (;6;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) (record (field "f" u8)))
+          (export (;1;) "the-type" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:foo/b") (instance (;0;) (type 0)))
+      (alias export 0 "the-type" (type (;1;)))
+      (type (;2;)
         (instance
           (alias outer 1 1 (type (;0;)))
           (export (;1;) "the-type" (type (eq 0)))
         )
       )
-      (export (;3;) (interface "foo:foo/a2") (instance (type 4)))
+      (export (;1;) (interface "foo:foo/a2") (instance (type 2)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;7;) "a2" (type 6))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/multiple-use.wat b/crates/wit-component/tests/interfaces/multiple-use.wat
index 38eff77f..adab86d9 100644
--- a/crates/wit-component/tests/interfaces/multiple-use.wat
+++ b/crates/wit-component/tests/interfaces/multiple-use.wat
@@ -10,13 +10,39 @@
         )
       )
       (export (;0;) (interface "foo:multiuse/foo") (instance (type 0)))
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u8)
+          (export (;1;) "u" (type (eq 0)))
+        )
+      )
+      (export (;0;) (interface "foo:multiuse/bar") (instance (type 0)))
+    )
+  )
+  (export (;3;) "bar" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u8)
+          (export (;1;) "t1" (type (eq 0)))
+          (type (;2;) u8)
+          (export (;3;) "t2" (type (eq 2)))
+        )
+      )
+      (import (interface "foo:multiuse/foo") (instance (;0;) (type 0)))
       (type (;1;)
         (instance
           (type (;0;) u8)
           (export (;1;) "u" (type (eq 0)))
         )
       )
-      (export (;1;) (interface "foo:multiuse/bar") (instance (type 1)))
+      (import (interface "foo:multiuse/bar") (instance (;1;) (type 1)))
       (alias export 0 "t1" (type (;2;)))
       (alias export 1 "u" (type (;3;)))
       (alias export 0 "t2" (type (;4;)))
@@ -33,7 +59,7 @@
       (export (;2;) (interface "foo:multiuse/baz") (instance (type 5)))
     )
   )
-  (export (;1;) (interface "foo:multiuse/wit") (type 0))
+  (export (;5;) "baz" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/pkg-use-chain.wat b/crates/wit-component/tests/interfaces/pkg-use-chain.wat
index 3271c3f4..4c02b18f 100644
--- a/crates/wit-component/tests/interfaces/pkg-use-chain.wat
+++ b/crates/wit-component/tests/interfaces/pkg-use-chain.wat
@@ -8,6 +8,18 @@
         )
       )
       (export (;0;) (interface "foo:chain/a") (instance (type 0)))
+    )
+  )
+  (export (;1;) "a" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u8)
+          (export (;1;) "a" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:chain/a") (instance (;0;) (type 0)))
       (alias export 0 "a" (type (;1;)))
       (type (;2;)
         (instance
@@ -18,6 +30,28 @@
         )
       )
       (export (;1;) (interface "foo:chain/def") (instance (type 2)))
+    )
+  )
+  (export (;3;) "def" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u8)
+          (export (;1;) "a" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:chain/a") (instance (;0;) (type 0)))
+      (alias export 0 "a" (type (;1;)))
+      (type (;2;)
+        (instance
+          (alias outer 1 1 (type (;0;)))
+          (export (;1;) "a" (type (eq 0)))
+          (type (;2;) (enum "other"))
+          (export (;3;) "name" (type (eq 2)))
+        )
+      )
+      (import (interface "foo:chain/def") (instance (;1;) (type 2)))
       (alias export 1 "name" (type (;3;)))
       (type (;4;)
         (instance
@@ -28,7 +62,7 @@
       (export (;2;) (interface "foo:chain/foo") (instance (type 4)))
     )
   )
-  (export (;1;) (interface "foo:chain/wit") (type 0))
+  (export (;5;) "foo" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/pkg-use-chain2.wat b/crates/wit-component/tests/interfaces/pkg-use-chain2.wat
index 65c10e61..cded6090 100644
--- a/crates/wit-component/tests/interfaces/pkg-use-chain2.wat
+++ b/crates/wit-component/tests/interfaces/pkg-use-chain2.wat
@@ -8,6 +8,18 @@
         )
       )
       (export (;0;) (interface "foo:foo/other") (instance (type 0)))
+    )
+  )
+  (export (;1;) "other" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) (record (field "f" u8)))
+          (export (;1;) "name" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:foo/other") (instance (;0;) (type 0)))
       (alias export 0 "name" (type (;1;)))
       (type (;2;)
         (instance
@@ -18,6 +30,28 @@
         )
       )
       (export (;1;) (interface "foo:foo/bar") (instance (type 2)))
+    )
+  )
+  (export (;3;) "bar" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) (record (field "f" u8)))
+          (export (;1;) "name" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:foo/other") (instance (;0;) (type 0)))
+      (alias export 0 "name" (type (;1;)))
+      (type (;2;)
+        (instance
+          (alias outer 1 1 (type (;0;)))
+          (export (;1;) "the-name" (type (eq 0)))
+          (type (;2;) (enum "a"))
+          (export (;3;) "name" (type (eq 2)))
+        )
+      )
+      (import (interface "foo:foo/bar") (instance (;1;) (type 2)))
       (alias export 1 "the-name" (type (;3;)))
       (type (;4;)
         (instance
@@ -28,7 +62,7 @@
       (export (;2;) (interface "foo:foo/foo") (instance (type 4)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "foo" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/preserve-dep-type-order.wat b/crates/wit-component/tests/interfaces/preserve-dep-type-order.wat
index 41d21f3a..9c3d93b7 100644
--- a/crates/wit-component/tests/interfaces/preserve-dep-type-order.wat
+++ b/crates/wit-component/tests/interfaces/preserve-dep-type-order.wat
@@ -18,7 +18,12 @@
         )
       )
       (export (;1;) (interface "foo:foo/foo") (instance (type 2)))
-      (type (;3;)
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -31,10 +36,10 @@
           (import (interface "foo:dep/foo") (instance (;0;) (type 0)))
         )
       )
-      (export (;0;) (interface "foo:foo/bar") (component (type 3)))
+      (export (;0;) (interface "foo:foo/bar") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "bar" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/preserve-foreign-reexport.wat b/crates/wit-component/tests/interfaces/preserve-foreign-reexport.wat
index e82cad59..736988e6 100644
--- a/crates/wit-component/tests/interfaces/preserve-foreign-reexport.wat
+++ b/crates/wit-component/tests/interfaces/preserve-foreign-reexport.wat
@@ -16,7 +16,7 @@
       (export (;0;) (interface "foo:foo/foo") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;1;) "foo" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/print-keyword.wat b/crates/wit-component/tests/interfaces/print-keyword.wat
index 742b8644..5619770f 100644
--- a/crates/wit-component/tests/interfaces/print-keyword.wat
+++ b/crates/wit-component/tests/interfaces/print-keyword.wat
@@ -13,7 +13,7 @@
       (export (;0;) (interface "foo:foo/interface") (instance (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;1;) "interface" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/records.wat b/crates/wit-component/tests/interfaces/records.wat
index c5d7d31e..3f76796c 100644
--- a/crates/wit-component/tests/interfaces/records.wat
+++ b/crates/wit-component/tests/interfaces/records.wat
@@ -41,7 +41,12 @@
         )
       )
       (export (;0;) (interface "foo:records/records") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "records" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -125,10 +130,10 @@
           (export (;1;) (interface "foo:records/records") (instance (type 1)))
         )
       )
-      (export (;0;) (interface "foo:records/records-world") (component (type 1)))
+      (export (;0;) (interface "foo:records/records-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:records/wit") (type 0))
+  (export (;3;) "records-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/reference-out-of-order.wat b/crates/wit-component/tests/interfaces/reference-out-of-order.wat
index 81f9af8f..13573eae 100644
--- a/crates/wit-component/tests/interfaces/reference-out-of-order.wat
+++ b/crates/wit-component/tests/interfaces/reference-out-of-order.wat
@@ -22,7 +22,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -47,10 +52,10 @@
           (import (interface "foo:foo/foo") (instance (;0;) (type 0)))
         )
       )
-      (export (;0;) (interface "foo:foo/foo-world") (component (type 1)))
+      (export (;0;) (interface "foo:foo/foo-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "foo-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/resources.wat b/crates/wit-component/tests/interfaces/resources.wat
index ccc47625..b95fa83d 100644
--- a/crates/wit-component/tests/interfaces/resources.wat
+++ b/crates/wit-component/tests/interfaces/resources.wat
@@ -20,6 +20,20 @@
         )
       )
       (export (;0;) (interface "foo:bar/foo") (instance (type 0)))
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (export (;0;) "bar" (type (sub resource)))
+          (export (;1;) "t" (type (eq 0)))
+          (type (;2;) (own 0))
+          (export (;3;) "t2" (type (eq 2)))
+        )
+      )
+      (import (interface "foo:bar/foo") (instance (;0;) (type 0)))
       (alias export 0 "bar" (type (;1;)))
       (alias export 0 "t" (type (;2;)))
       (type (;3;)
@@ -37,7 +51,12 @@
         )
       )
       (export (;1;) (interface "foo:bar/baz") (instance (type 3)))
-      (type (;4;)
+    )
+  )
+  (export (;3;) "baz" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (instance
           (export (;0;) "a" (type (sub resource)))
           (type (;1;) (own 0))
@@ -48,8 +67,13 @@
           (export (;1;) "c" (func (type 4)))
         )
       )
-      (export (;2;) (interface "foo:bar/implicit-own-handles") (instance (type 4)))
-      (type (;5;)
+      (export (;0;) (interface "foo:bar/implicit-own-handles") (instance (type 0)))
+    )
+  )
+  (export (;5;) "implicit-own-handles" (type 4))
+  (type (;6;)
+    (component
+      (type (;0;)
         (instance
           (export (;0;) "a" (type (sub resource)))
           (export (;1;) "b" (type (sub resource)))
@@ -67,8 +91,13 @@
           (export (;2;) "[static]c.a" (func (type 10)))
         )
       )
-      (export (;3;) (interface "foo:bar/implicit-own-handles2") (instance (type 5)))
-      (type (;6;)
+      (export (;0;) (interface "foo:bar/implicit-own-handles2") (instance (type 0)))
+    )
+  )
+  (export (;7;) "implicit-own-handles2" (type 6))
+  (type (;8;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -132,8 +161,13 @@
           (export (;2;) "y" (func (type 11)))
         )
       )
-      (export (;0;) (interface "foo:bar/some-world") (component (type 6)))
-      (type (;7;)
+      (export (;0;) (interface "foo:bar/some-world") (component (type 0)))
+    )
+  )
+  (export (;9;) "some-world" (type 8))
+  (type (;10;)
+    (component
+      (type (;0;)
         (component
           (import "a" (type (;0;) (sub resource)))
           (type (;1;) (own 0))
@@ -142,10 +176,10 @@
           (import "[constructor]a" (func (;0;) (type 3)))
         )
       )
-      (export (;1;) (interface "foo:bar/implicit-own-handles3") (component (type 7)))
+      (export (;0;) (interface "foo:bar/implicit-own-handles3") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:bar/wit") (type 0))
+  (export (;11;) "implicit-own-handles3" (type 10))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/simple-deps.wat b/crates/wit-component/tests/interfaces/simple-deps.wat
index 66f3bfca..d8730975 100644
--- a/crates/wit-component/tests/interfaces/simple-deps.wat
+++ b/crates/wit-component/tests/interfaces/simple-deps.wat
@@ -18,7 +18,7 @@
       (export (;1;) (interface "foo:foo/foo") (instance (type 2)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;1;) "foo" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/simple-multi.wat b/crates/wit-component/tests/interfaces/simple-multi.wat
index 2a0222d1..fabd6da4 100644
--- a/crates/wit-component/tests/interfaces/simple-multi.wat
+++ b/crates/wit-component/tests/interfaces/simple-multi.wat
@@ -5,13 +5,18 @@
         (instance)
       )
       (export (;0;) (interface "foo:foo/bar") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "bar" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (instance)
       )
-      (export (;1;) (interface "foo:foo/foo") (instance (type 1)))
+      (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "foo" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/simple-use.wat b/crates/wit-component/tests/interfaces/simple-use.wat
index caf6e5fe..f1dcfcb8 100644
--- a/crates/wit-component/tests/interfaces/simple-use.wat
+++ b/crates/wit-component/tests/interfaces/simple-use.wat
@@ -8,6 +8,18 @@
         )
       )
       (export (;0;) (interface "foo:foo/types") (instance (type 0)))
+    )
+  )
+  (export (;1;) "types" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) (enum "info" "debug"))
+          (export (;1;) "level" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:foo/types") (instance (;0;) (type 0)))
       (alias export 0 "level" (type (;1;)))
       (type (;2;)
         (instance
@@ -20,7 +32,7 @@
       (export (;1;) (interface "foo:foo/console") (instance (type 2)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "console" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/simple-world.wat b/crates/wit-component/tests/interfaces/simple-world.wat
index 1354327a..a7dd0472 100644
--- a/crates/wit-component/tests/interfaces/simple-world.wat
+++ b/crates/wit-component/tests/interfaces/simple-world.wat
@@ -8,7 +8,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/console") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "console" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -19,10 +24,10 @@
           (import (interface "foo:foo/console") (instance (;0;) (type 0)))
         )
       )
-      (export (;0;) (interface "foo:foo/the-world") (component (type 1)))
+      (export (;0;) (interface "foo:foo/the-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "the-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/single-named-result.wat b/crates/wit-component/tests/interfaces/single-named-result.wat
index 980b3361..c7398bb7 100644
--- a/crates/wit-component/tests/interfaces/single-named-result.wat
+++ b/crates/wit-component/tests/interfaces/single-named-result.wat
@@ -10,7 +10,7 @@
       (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;1;) "foo" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/type-alias.wat b/crates/wit-component/tests/interfaces/type-alias.wat
index 23c38d4b..5bb85d88 100644
--- a/crates/wit-component/tests/interfaces/type-alias.wat
+++ b/crates/wit-component/tests/interfaces/type-alias.wat
@@ -11,7 +11,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -35,10 +40,10 @@
           (export (;1;) (interface "foo:foo/foo") (instance (type 1)))
         )
       )
-      (export (;0;) (interface "foo:foo/my-world") (component (type 1)))
+      (export (;0;) (interface "foo:foo/my-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "my-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/type-alias2.wat b/crates/wit-component/tests/interfaces/type-alias2.wat
index 85d2d1f0..11306474 100644
--- a/crates/wit-component/tests/interfaces/type-alias2.wat
+++ b/crates/wit-component/tests/interfaces/type-alias2.wat
@@ -11,7 +11,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -25,10 +30,10 @@
           (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
         )
       )
-      (export (;0;) (interface "foo:foo/my-world") (component (type 1)))
+      (export (;0;) (interface "foo:foo/my-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;3;) "my-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/upstream-deps-same-name.wat b/crates/wit-component/tests/interfaces/upstream-deps-same-name.wat
index 22c03c3a..9f1cf07a 100644
--- a/crates/wit-component/tests/interfaces/upstream-deps-same-name.wat
+++ b/crates/wit-component/tests/interfaces/upstream-deps-same-name.wat
@@ -28,7 +28,7 @@
       (export (;2;) (interface "foo:foo/a") (instance (type 4)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;1;) "a" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/use-chain.wat b/crates/wit-component/tests/interfaces/use-chain.wat
index e555b67a..7c417336 100644
--- a/crates/wit-component/tests/interfaces/use-chain.wat
+++ b/crates/wit-component/tests/interfaces/use-chain.wat
@@ -10,6 +10,20 @@
         )
       )
       (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u32)
+          (export (;1;) "a" (type (eq 0)))
+          (export (;2;) "b" (type (eq 1)))
+          (export (;3;) "c" (type (eq 2)))
+        )
+      )
+      (import (interface "foo:foo/foo") (instance (;0;) (type 0)))
       (alias export 0 "c" (type (;1;)))
       (type (;2;)
         (instance
@@ -18,6 +32,28 @@
         )
       )
       (export (;1;) (interface "foo:foo/bar") (instance (type 2)))
+    )
+  )
+  (export (;3;) "bar" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u32)
+          (export (;1;) "a" (type (eq 0)))
+          (export (;2;) "b" (type (eq 1)))
+          (export (;3;) "c" (type (eq 2)))
+        )
+      )
+      (import (interface "foo:foo/foo") (instance (;0;) (type 0)))
+      (alias export 0 "c" (type (;1;)))
+      (type (;2;)
+        (instance
+          (alias outer 1 1 (type (;0;)))
+          (export (;1;) "c" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:foo/bar") (instance (;1;) (type 2)))
       (alias export 1 "c" (type (;3;)))
       (type (;4;)
         (instance
@@ -28,7 +64,7 @@
       (export (;2;) (interface "foo:foo/baz") (instance (type 4)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "baz" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/use-for-type.wat b/crates/wit-component/tests/interfaces/use-for-type.wat
index dd19b865..a6f44949 100644
--- a/crates/wit-component/tests/interfaces/use-for-type.wat
+++ b/crates/wit-component/tests/interfaces/use-for-type.wat
@@ -5,26 +5,43 @@
         (instance)
       )
       (export (;0;) (interface "foo:foo/foo") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u8)
+          (export (;1;) "t" (type (eq 0)))
+        )
+      )
+      (export (;0;) (interface "foo:foo/bar") (instance (type 0)))
+    )
+  )
+  (export (;3;) "bar" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (instance
           (type (;0;) u8)
           (export (;1;) "t" (type (eq 0)))
         )
       )
-      (export (;1;) (interface "foo:foo/bar") (instance (type 1)))
-      (alias export 1 "t" (type (;2;)))
-      (type (;3;)
+      (import (interface "foo:foo/bar") (instance (;0;) (type 0)))
+      (alias export 0 "t" (type (;1;)))
+      (type (;2;)
         (instance
-          (alias outer 1 2 (type (;0;)))
+          (alias outer 1 1 (type (;0;)))
           (export (;1;) "t" (type (eq 0)))
           (type (;2;) (record (field "a" 1)))
           (export (;3;) "bar" (type (eq 2)))
         )
       )
-      (export (;2;) (interface "foo:foo/baz") (instance (type 3)))
+      (export (;1;) (interface "foo:foo/baz") (instance (type 2)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "baz" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/variants.wat b/crates/wit-component/tests/interfaces/variants.wat
index a239f02a..2061db28 100644
--- a/crates/wit-component/tests/interfaces/variants.wat
+++ b/crates/wit-component/tests/interfaces/variants.wat
@@ -89,7 +89,12 @@
         )
       )
       (export (;0;) (interface "foo:variants/variants") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "variants" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -181,10 +186,10 @@
           (import (interface "foo:variants/variants") (instance (;0;) (type 0)))
         )
       )
-      (export (;0;) (interface "foo:variants/variants-world") (component (type 1)))
+      (export (;0;) (interface "foo:variants/variants-world") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:variants/wit") (type 0))
+  (export (;3;) "variants-world" (type 2))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/wasi-http.wat b/crates/wit-component/tests/interfaces/wasi-http.wat
index 64424876..2a9dce8e 100644
--- a/crates/wit-component/tests/interfaces/wasi-http.wat
+++ b/crates/wit-component/tests/interfaces/wasi-http.wat
@@ -139,6 +139,74 @@
         )
       )
       (export (;2;) (interface "wasi:http/types") (instance (type 5)))
+    )
+  )
+  (export (;1;) "types" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u32)
+          (export (;1;) "pollable" (type (eq 0)))
+        )
+      )
+      (import (interface "wasi:poll/poll") (instance (;0;) (type 0)))
+      (alias export 0 "pollable" (type (;1;)))
+      (type (;2;)
+        (instance
+          (alias outer 1 1 (type (;0;)))
+          (export (;1;) "pollable" (type (eq 0)))
+          (type (;2;) (record (field "f" u8)))
+          (export (;3;) "stream-error" (type (eq 2)))
+          (type (;4;) u32)
+          (export (;5;) "input-stream" (type (eq 4)))
+          (type (;6;) u32)
+          (export (;7;) "output-stream" (type (eq 6)))
+        )
+      )
+      (import (interface "wasi:io/streams") (instance (;1;) (type 2)))
+      (alias export 1 "input-stream" (type (;3;)))
+      (alias export 1 "output-stream" (type (;4;)))
+      (type (;5;)
+        (instance
+          (alias outer 1 3 (type (;0;)))
+          (export (;1;) "input-stream" (type (eq 0)))
+          (alias outer 1 4 (type (;2;)))
+          (export (;3;) "output-stream" (type (eq 2)))
+          (alias outer 1 1 (type (;4;)))
+          (export (;5;) "pollable" (type (eq 4)))
+          (type (;6;) (variant (case "get") (case "head") (case "post") (case "put") (case "delete") (case "connect") (case "options") (case "trace") (case "patch") (case "other" string)))
+          (export (;7;) "method" (type (eq 6)))
+          (type (;8;) (variant (case "HTTP") (case "HTTPS") (case "other" string)))
+          (export (;9;) "scheme" (type (eq 8)))
+          (type (;10;) (variant (case "invalid-url" string) (case "timeout-error" string) (case "protocol-error" string) (case "unexpected-error" string)))
+          (export (;11;) "error" (type (eq 10)))
+          (type (;12;) u32)
+          (export (;13;) "fields" (type (eq 12)))
+          (export (;14;) "headers" (type (eq 13)))
+          (export (;15;) "trailers" (type (eq 13)))
+          (export (;16;) "incoming-stream" (type (eq 1)))
+          (export (;17;) "outgoing-stream" (type (eq 3)))
+          (type (;18;) u32)
+          (export (;19;) "incoming-request" (type (eq 18)))
+          (type (;20;) u32)
+          (export (;21;) "outgoing-request" (type (eq 20)))
+          (type (;22;) (option u32))
+          (type (;23;) (record (field "connect-timeout-ms" 22) (field "first-byte-timeout-ms" 22) (field "between-bytes-timeout-ms" 22)))
+          (export (;24;) "request-options" (type (eq 23)))
+          (type (;25;) u32)
+          (export (;26;) "response-outparam" (type (eq 25)))
+          (type (;27;) u16)
+          (export (;28;) "status-code" (type (eq 27)))
+          (type (;29;) u32)
+          (export (;30;) "incoming-response" (type (eq 29)))
+          (type (;31;) u32)
+          (export (;32;) "outgoing-response" (type (eq 31)))
+          (type (;33;) u32)
+          (export (;34;) "future-incoming-response" (type (eq 33)))
+        )
+      )
+      (import (interface "wasi:http/types") (instance (;2;) (type 5)))
       (alias export 2 "incoming-request" (type (;6;)))
       (alias export 2 "response-outparam" (type (;7;)))
       (type (;8;)
@@ -152,24 +220,97 @@
         )
       )
       (export (;3;) (interface "wasi:http/incoming-handler") (instance (type 8)))
-      (alias export 2 "outgoing-request" (type (;9;)))
-      (alias export 2 "request-options" (type (;10;)))
-      (alias export 2 "future-incoming-response" (type (;11;)))
-      (type (;12;)
+    )
+  )
+  (export (;3;) "incoming-handler" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u32)
+          (export (;1;) "pollable" (type (eq 0)))
+        )
+      )
+      (import (interface "wasi:poll/poll") (instance (;0;) (type 0)))
+      (alias export 0 "pollable" (type (;1;)))
+      (type (;2;)
+        (instance
+          (alias outer 1 1 (type (;0;)))
+          (export (;1;) "pollable" (type (eq 0)))
+          (type (;2;) (record (field "f" u8)))
+          (export (;3;) "stream-error" (type (eq 2)))
+          (type (;4;) u32)
+          (export (;5;) "input-stream" (type (eq 4)))
+          (type (;6;) u32)
+          (export (;7;) "output-stream" (type (eq 6)))
+        )
+      )
+      (import (interface "wasi:io/streams") (instance (;1;) (type 2)))
+      (alias export 1 "input-stream" (type (;3;)))
+      (alias export 1 "output-stream" (type (;4;)))
+      (type (;5;)
+        (instance
+          (alias outer 1 3 (type (;0;)))
+          (export (;1;) "input-stream" (type (eq 0)))
+          (alias outer 1 4 (type (;2;)))
+          (export (;3;) "output-stream" (type (eq 2)))
+          (alias outer 1 1 (type (;4;)))
+          (export (;5;) "pollable" (type (eq 4)))
+          (type (;6;) (variant (case "get") (case "head") (case "post") (case "put") (case "delete") (case "connect") (case "options") (case "trace") (case "patch") (case "other" string)))
+          (export (;7;) "method" (type (eq 6)))
+          (type (;8;) (variant (case "HTTP") (case "HTTPS") (case "other" string)))
+          (export (;9;) "scheme" (type (eq 8)))
+          (type (;10;) (variant (case "invalid-url" string) (case "timeout-error" string) (case "protocol-error" string) (case "unexpected-error" string)))
+          (export (;11;) "error" (type (eq 10)))
+          (type (;12;) u32)
+          (export (;13;) "fields" (type (eq 12)))
+          (export (;14;) "headers" (type (eq 13)))
+          (export (;15;) "trailers" (type (eq 13)))
+          (export (;16;) "incoming-stream" (type (eq 1)))
+          (export (;17;) "outgoing-stream" (type (eq 3)))
+          (type (;18;) u32)
+          (export (;19;) "incoming-request" (type (eq 18)))
+          (type (;20;) u32)
+          (export (;21;) "outgoing-request" (type (eq 20)))
+          (type (;22;) (option u32))
+          (type (;23;) (record (field "connect-timeout-ms" 22) (field "first-byte-timeout-ms" 22) (field "between-bytes-timeout-ms" 22)))
+          (export (;24;) "request-options" (type (eq 23)))
+          (type (;25;) u32)
+          (export (;26;) "response-outparam" (type (eq 25)))
+          (type (;27;) u16)
+          (export (;28;) "status-code" (type (eq 27)))
+          (type (;29;) u32)
+          (export (;30;) "incoming-response" (type (eq 29)))
+          (type (;31;) u32)
+          (export (;32;) "outgoing-response" (type (eq 31)))
+          (type (;33;) u32)
+          (export (;34;) "future-incoming-response" (type (eq 33)))
+        )
+      )
+      (import (interface "wasi:http/types") (instance (;2;) (type 5)))
+      (alias export 2 "outgoing-request" (type (;6;)))
+      (alias export 2 "request-options" (type (;7;)))
+      (alias export 2 "future-incoming-response" (type (;8;)))
+      (type (;9;)
         (instance
-          (alias outer 1 9 (type (;0;)))
+          (alias outer 1 6 (type (;0;)))
           (export (;1;) "outgoing-request" (type (eq 0)))
-          (alias outer 1 10 (type (;2;)))
+          (alias outer 1 7 (type (;2;)))
           (export (;3;) "request-options" (type (eq 2)))
-          (alias outer 1 11 (type (;4;)))
+          (alias outer 1 8 (type (;4;)))
           (export (;5;) "future-incoming-response" (type (eq 4)))
           (type (;6;) (option 3))
           (type (;7;) (func (param "request" 1) (param "options" 6) (result 5)))
           (export (;0;) "handle" (func (type 7)))
         )
       )
-      (export (;4;) (interface "wasi:http/outgoing-handler") (instance (type 12)))
-      (type (;13;)
+      (export (;3;) (interface "wasi:http/outgoing-handler") (instance (type 9)))
+    )
+  )
+  (export (;5;) "outgoing-handler" (type 4))
+  (type (;6;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -400,10 +541,10 @@
           (export (;6;) (interface "wasi:http/incoming-handler") (instance (type 14)))
         )
       )
-      (export (;0;) (interface "wasi:http/proxy") (component (type 13)))
+      (export (;0;) (interface "wasi:http/proxy") (component (type 0)))
     )
   )
-  (export (;1;) (interface "wasi:http/wit") (type 0))
+  (export (;7;) "proxy" (type 6))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/world-inline-interface.wat b/crates/wit-component/tests/interfaces/world-inline-interface.wat
index 77c67eb9..bfed860d 100644
--- a/crates/wit-component/tests/interfaces/world-inline-interface.wat
+++ b/crates/wit-component/tests/interfaces/world-inline-interface.wat
@@ -16,7 +16,7 @@
       (export (;0;) (interface "foo:foo/has-inline") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;1;) "has-inline" (type 0))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/world-pkg-conflict.wat b/crates/wit-component/tests/interfaces/world-pkg-conflict.wat
index fbd7e839..c0a4611c 100644
--- a/crates/wit-component/tests/interfaces/world-pkg-conflict.wat
+++ b/crates/wit-component/tests/interfaces/world-pkg-conflict.wat
@@ -8,6 +8,18 @@
         )
       )
       (export (;0;) (interface "foo:foo/a") (instance (type 0)))
+    )
+  )
+  (export (;1;) "a" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
+        (instance
+          (type (;0;) u32)
+          (export (;1;) "t" (type (eq 0)))
+        )
+      )
+      (import (interface "foo:foo/a") (instance (;0;) (type 0)))
       (alias export 0 "t" (type (;1;)))
       (type (;2;)
         (instance
@@ -16,13 +28,18 @@
         )
       )
       (export (;1;) (interface "foo:foo/foo") (instance (type 2)))
-      (type (;3;)
+    )
+  )
+  (export (;3;) "foo" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (component)
       )
-      (export (;0;) (interface "foo:foo/c") (component (type 3)))
+      (export (;0;) (interface "foo:foo/c") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "c" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/world-top-level.wat b/crates/wit-component/tests/interfaces/world-top-level.wat
index 901850f3..1bd285cf 100644
--- a/crates/wit-component/tests/interfaces/world-top-level.wat
+++ b/crates/wit-component/tests/interfaces/world-top-level.wat
@@ -21,23 +21,33 @@
         )
       )
       (export (;0;) (interface "foo:foo/foo") (component (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "foo" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;) (func))
           (import "foo" (func (;0;) (type 0)))
         )
       )
-      (export (;1;) (interface "foo:foo/just-import") (component (type 1)))
-      (type (;2;)
+      (export (;0;) (interface "foo:foo/just-import") (component (type 0)))
+    )
+  )
+  (export (;3;) "just-import" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (component
           (type (;0;) (func))
           (export (;0;) "foo" (func (type 0)))
         )
       )
-      (export (;2;) (interface "foo:foo/just-export") (component (type 2)))
+      (export (;0;) (interface "foo:foo/just-export") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "just-export" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )
diff --git a/crates/wit-component/tests/interfaces/worlds-with-types.wat b/crates/wit-component/tests/interfaces/worlds-with-types.wat
index 4175e4f4..4a983c2b 100644
--- a/crates/wit-component/tests/interfaces/worlds-with-types.wat
+++ b/crates/wit-component/tests/interfaces/worlds-with-types.wat
@@ -8,7 +8,12 @@
         )
       )
       (export (;0;) (interface "foo:foo/import-me") (instance (type 0)))
-      (type (;1;)
+    )
+  )
+  (export (;1;) "import-me" (type 0))
+  (type (;2;)
+    (component
+      (type (;0;)
         (component
           (type (;0;) (record (field "f" u8)))
           (import "foo" (type (;1;) (eq 0)))
@@ -18,8 +23,13 @@
           (export (;1;) "b" (func (type 3)))
         )
       )
-      (export (;0;) (interface "foo:foo/simple") (component (type 1)))
-      (type (;2;)
+      (export (;0;) (interface "foo:foo/simple") (component (type 0)))
+    )
+  )
+  (export (;3;) "simple" (type 2))
+  (type (;4;)
+    (component
+      (type (;0;)
         (component
           (type (;0;)
             (instance
@@ -35,10 +45,10 @@
           (export (;1;) "b" (func (type 3)))
         )
       )
-      (export (;1;) (interface "foo:foo/with-imports") (component (type 2)))
+      (export (;0;) (interface "foo:foo/with-imports") (component (type 0)))
     )
   )
-  (export (;1;) (interface "foo:foo/wit") (type 0))
+  (export (;5;) "with-imports" (type 4))
   (@producers
     (processed-by "wit-component" "$CARGO_PKG_VERSION")
   )