Skip to content

Commit

Permalink
Improve handling of types and aliases in components (#5591)
Browse files Browse the repository at this point in the history
This commit fixes more cases from #5565 where `export` items introducing
indices wasn't handled by accident. Additionally this fixes support for
aliasing types from instances which largely wasn't working before. Most
of the fixes here are about correctly maintaining Wasmtime's view of the
type index spaces.
  • Loading branch information
alexcrichton authored Jan 19, 2023
1 parent 5fd9cb4 commit 0e92fba
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 7 deletions.
16 changes: 15 additions & 1 deletion crates/environ/src/component/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ enum ComponentItemType {
Func(TypeFuncIndex),
Component(ComponentType),
Instance(ComponentInstanceType),
Type(TypeDef),
}

#[derive(Copy, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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);
}
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions crates/environ/src/component/translate/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(),
Expand Down
45 changes: 42 additions & 3 deletions crates/environ/src/component/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ pub struct ComponentTypesBuilder {
struct TypeScope {
core: PrimaryMap<TypeIndex, TypeDef>,
component: PrimaryMap<ComponentTypeIndex, TypeDef>,
instances: PrimaryMap<ComponentInstanceIndex, TypeComponentInstanceIndex>,
}

macro_rules! intern_and_fill_flat_types {
Expand Down Expand Up @@ -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));
Expand All @@ -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));
Expand Down Expand Up @@ -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
Expand Down
74 changes: 74 additions & 0 deletions tests/misc_testsuite/component-model/types.wast
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
)

0 comments on commit 0e92fba

Please sign in to comment.