diff --git a/crates/environ/src/component/translate.rs b/crates/environ/src/component/translate.rs index 678aa6306e..ab538db424 100644 --- a/crates/environ/src/component/translate.rs +++ b/crates/environ/src/component/translate.rs @@ -266,6 +266,7 @@ enum ComponentItemType { Func(TypeFuncIndex), Component(ComponentType), Instance(ComponentInstanceType), + Type(TypeDef), } #[derive(Copy, Clone, PartialEq, Eq)] @@ -621,6 +622,9 @@ impl<'a, 'data> Translator<'a, 'data> { self.result .initializers .push(LocalInitializer::Export(item)); + if let ComponentItem::Type(ty) = item { + self.types.push_component_typedef(ty); + } } } @@ -775,7 +779,8 @@ impl<'a, 'data> Translator<'a, 'data> { ComponentItem::ComponentInstance(i) => Some(ComponentItemType::Instance( self.result.component_instances[i], )), - ComponentItem::Module(_) | ComponentItem::Type(_) => None, + ComponentItem::Type(ty) => Some(ComponentItemType::Type(ty)), + ComponentItem::Module(_) => None, }; map.insert(export.name, idx); if let Some(ty) = ty { @@ -848,6 +853,9 @@ impl<'a, 'data> Translator<'a, 'data> { ComponentInstanceType::Index(ty) => { let (_url, ty) = &self.types[ty].exports[name]; self.result.push_typedef(*ty); + if let TypeDef::Interface(_) = ty { + self.types.push_component_typedef(*ty); + } } // An imported component was instantiated so the type of the aliased @@ -856,6 +864,9 @@ impl<'a, 'data> Translator<'a, 'data> { ComponentInstanceType::InstantiatedIndex(ty) => { let (_, ty) = self.types[ty].exports[name]; self.result.push_typedef(ty); + if let TypeDef::Interface(_) = ty { + self.types.push_component_typedef(ty); + } } // A static nested component was instantiated which means that the @@ -902,6 +913,9 @@ impl<'a, 'data> Translator<'a, 'data> { ComponentItemType::Instance(ty) => { self.result.component_instances.push(ty); } + ComponentItemType::Type(ty) => { + self.types.push_component_typedef(ty); + } } } } diff --git a/crates/environ/src/component/translate/inline.rs b/crates/environ/src/component/translate/inline.rs index 352f9883d1..9d63bb4bef 100644 --- a/crates/environ/src/component/translate/inline.rs +++ b/crates/environ/src/component/translate/inline.rs @@ -683,9 +683,10 @@ impl<'a> Inliner<'a> { TypeDef::Component(_) => { unimplemented!("aliasing component export of component import") } - TypeDef::Interface(_) => { - unimplemented!("aliasing type export of component import") - } + + // This is handled during the initial translation + // pass and doesn't need further handling here. + TypeDef::Interface(_) => {} // not possible with valid components TypeDef::CoreFunc(_) => unreachable!(), diff --git a/crates/environ/src/component/types.rs b/crates/environ/src/component/types.rs index b690b9ccf6..4c78c2cbca 100644 --- a/crates/environ/src/component/types.rs +++ b/crates/environ/src/component/types.rs @@ -335,6 +335,7 @@ pub struct ComponentTypesBuilder { struct TypeScope { core: PrimaryMap, component: PrimaryMap, + instances: PrimaryMap, } macro_rules! intern_and_fill_flat_types { @@ -554,13 +555,13 @@ impl ComponentTypesBuilder { ComponentTypeDeclaration::CoreType(ty) => self.type_declaration_core_type(ty)?, ComponentTypeDeclaration::Alias(alias) => self.type_declaration_alias(alias)?, ComponentTypeDeclaration::Export { name, url, ty } => { - let ty = self.component_type_ref(ty); + let ty = self.type_declaration_define(ty); result .exports .insert(name.to_string(), (url.to_string(), ty)); } ComponentTypeDeclaration::Import(import) => { - let ty = self.component_type_ref(&import.ty); + let ty = self.type_declaration_define(&import.ty); result .imports .insert(import.name.to_string(), (import.url.to_string(), ty)); @@ -586,7 +587,7 @@ impl ComponentTypesBuilder { InstanceTypeDeclaration::CoreType(ty) => self.type_declaration_core_type(ty)?, InstanceTypeDeclaration::Alias(alias) => self.type_declaration_alias(alias)?, InstanceTypeDeclaration::Export { name, url, ty } => { - let ty = self.component_type_ref(ty); + let ty = self.type_declaration_define(ty); result .exports .insert(name.to_string(), (url.to_string(), ty)); @@ -629,11 +630,49 @@ impl ComponentTypesBuilder { let ty = self.component_outer_type(*count, ComponentTypeIndex::from_u32(*index)); self.push_component_typedef(ty); } + ComponentAlias::InstanceExport { + kind: _, + instance_index, + name, + } => { + let ty = self.type_scopes.last().unwrap().instances + [ComponentInstanceIndex::from_u32(*instance_index)]; + let (_, ty) = self.component_types[ty].exports[*name]; + self.push_component_typedef(ty); + } a => unreachable!("invalid alias {a:?}"), } Ok(()) } + fn type_declaration_define(&mut self, ty: &wasmparser::ComponentTypeRef) -> TypeDef { + let ty = self.component_type_ref(ty); + let scope = self.type_scopes.last_mut().unwrap(); + match ty { + // If an import or an export within a component or instance type + // references an interface type itself then that creates a new type + // which is effectively an alias, so push the type information here. + TypeDef::Interface(_) => { + self.push_component_typedef(ty); + } + + // When an import or an export references a component instance then + // that creates a "pseudo-instance" which type information is + // maintained about. This is later used during the `InstanceExport` + // alias within a type declaration. + TypeDef::ComponentInstance(ty) => { + scope.instances.push(ty); + } + + // All other valid types are ignored since we don't need to maintain + // metadata about them here as index spaces are modified that we're + // not interested in. + _ => {} + } + + ty + } + fn func_type(&mut self, ty: &wasmparser::ComponentFuncType<'_>) -> TypeFuncIndex { let ty = TypeFunc { params: ty diff --git a/tests/misc_testsuite/component-model/types.wast b/tests/misc_testsuite/component-model/types.wast index 2cd334a625..c4c93a8037 100644 --- a/tests/misc_testsuite/component-model/types.wast +++ b/tests/misc_testsuite/component-model/types.wast @@ -246,3 +246,77 @@ (type $t101 (list $t100)) ) "type nesting is too deep") + +(component + (type (instance + (export $x "x" (instance + (type $t u32) + (export "y" (type (eq $t))) + )) + (alias export $x "y" (type $t)) + (export "my-y" (type (eq $t))) + )) + + (type (component + (import "x" (instance $x + (type $t u32) + (export "y" (type (eq $t))) + )) + (alias export $x "y" (type $t)) + (export "my-y" (type (eq $t))) + )) +) + +(component + (type $t u32) + (export $t2 "t" (type $t)) + (type $r (record (field "x" $t2))) + (export "r" (type $r)) +) + +(component + (component + (import "x" (instance $i + (type $i u32) + (export "i" (type (eq $i))) + )) + (alias export $i "i" (type $i)) + (export "i" (type $i)) + ) +) + +(component + (type $u u32) + (instance $i + (export "i" (type $u)) + ) + (alias export $i "i" (type $i)) + (export "i" (type $i)) +) + +(component + (component $c + (type $t u32) + (export "t" (type $t)) + ) + (instance $c (instantiate $c)) + (export "i" (type $c "t")) +) + +(component + (component $c + (import "x" (component $c + (type $t u32) + (export "t" (type (eq $t))) + )) + (instance $c (instantiate $c)) + (export "i" (type $c "t")) + ) + + (component $x + (type $t u32) + (export "t" (type $t)) + ) + + (instance $c (instantiate $c (with "x" (component $x)))) +)