Skip to content

Commit 90fd388

Browse files
authored
Flesh out more text support for GC types in components (#1813)
This commit builds on the work of #1764 to support the text format for GC types in components more than before. This notably bring support for: * `(sub ...)` types in components and module types * `(rec ...)` groups in components and module types * types can refer to themselves like with core wasm The main consequence of this work is that unlike most other `$foo` identifiers in the component model the identifiers found in types will not automatically inject outer aliases to refer to outer types. For example this will not parse: (component $C (type $t (struct)) (component (type (array (ref $t))) ) ) The reason for this is that automatic injection of an outer alias requires that types are resolved and then their names are registered. The resolution process queues up aliases to inject which are accounted for during registration when indices are assigned. Here though because types can refer to themselves (or future types in `rec` groups) the registration process has to happen first before resolution. This means that if resolution were to inject more type indices then that would mess up the indexes already assigned. This is hopefully relatively minor in terms of how often this'll bite someone. For now various changes have been made to the name resolution pass of components to handle this and some tests have been added too for both positive and negative situations.
1 parent 3e54745 commit 90fd388

File tree

17 files changed

+438
-175
lines changed

17 files changed

+438
-175
lines changed

crates/wast/src/component/binary.rs

Lines changed: 17 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use wasm_encoder::{
77
ComponentDefinedTypeEncoder, ComponentExportSection, ComponentImportSection,
88
ComponentInstanceSection, ComponentNameSection, ComponentSection, ComponentSectionId,
99
ComponentStartSection, ComponentTypeEncoder, ComponentTypeSection, CoreTypeSection,
10-
InstanceSection, NameMap, NestedComponentSection, RawSection, SubType,
10+
InstanceSection, NameMap, NestedComponentSection, RawSection,
1111
};
1212

1313
pub fn encode(component: &Component<'_>, options: &EncodeOptions) -> Vec<u8> {
@@ -33,6 +33,7 @@ fn encode_fields(
3333
ComponentField::CoreModule(m) => e.encode_core_module(m, options),
3434
ComponentField::CoreInstance(i) => e.encode_core_instance(i),
3535
ComponentField::CoreType(t) => e.encode_core_type(t),
36+
ComponentField::CoreRec(t) => e.encode_core_rec(t),
3637
ComponentField::Component(c) => e.encode_component(c, options),
3738
ComponentField::Instance(i) => e.encode_instance(i),
3839
ComponentField::Alias(a) => e.encode_alias(a),
@@ -58,12 +59,7 @@ fn encode_fields(
5859
fn encode_core_type(encoder: ComponentCoreTypeEncoder, ty: &CoreTypeDef) {
5960
match ty {
6061
CoreTypeDef::Def(def) => {
61-
let sub_type = SubType {
62-
is_final: true,
63-
supertype_idx: None,
64-
composite_type: def.to_composite_type(),
65-
};
66-
encoder.core().subtype(&sub_type);
62+
encoder.core().subtype(&def.to_subtype());
6763
}
6864
CoreTypeDef::Module(t) => {
6965
encoder.module(&t.into());
@@ -232,6 +228,17 @@ impl<'a> Encoder<'a> {
232228
self.flush(Some(self.core_types.id()));
233229
}
234230

231+
fn encode_core_rec(&mut self, ty: &core::Rec<'a>) {
232+
for ty in ty.types.iter() {
233+
self.core_type_names.push(get_name(&ty.id, &ty.name));
234+
}
235+
self.core_types
236+
.ty()
237+
.core()
238+
.rec(ty.types.iter().map(|t| t.to_subtype()));
239+
self.flush(Some(self.core_types.id()));
240+
}
241+
235242
fn encode_component(&mut self, component: &NestedComponent<'a>, options: &EncodeOptions) {
236243
self.component_names
237244
.push(get_name(&component.id, &component.name));
@@ -555,66 +562,6 @@ impl Custom<'_> {
555562
}
556563
}
557564

558-
// TODO: move these core conversion functions to the core module
559-
// once we update core encoding to use wasm-encoder.
560-
impl From<core::ValType<'_>> for wasm_encoder::ValType {
561-
fn from(ty: core::ValType) -> Self {
562-
match ty {
563-
core::ValType::I32 => Self::I32,
564-
core::ValType::I64 => Self::I64,
565-
core::ValType::F32 => Self::F32,
566-
core::ValType::F64 => Self::F64,
567-
core::ValType::V128 => Self::V128,
568-
core::ValType::Ref(r) => Self::Ref(r.into()),
569-
}
570-
}
571-
}
572-
573-
impl From<core::RefType<'_>> for wasm_encoder::RefType {
574-
fn from(r: core::RefType<'_>) -> Self {
575-
wasm_encoder::RefType {
576-
nullable: r.nullable,
577-
heap_type: r.heap.into(),
578-
}
579-
}
580-
}
581-
582-
impl From<core::HeapType<'_>> for wasm_encoder::HeapType {
583-
fn from(r: core::HeapType<'_>) -> Self {
584-
use wasm_encoder::AbstractHeapType::*;
585-
match r {
586-
core::HeapType::Abstract { shared, ty } => {
587-
let ty = match ty {
588-
core::AbstractHeapType::Func => Func,
589-
core::AbstractHeapType::Extern => Extern,
590-
core::AbstractHeapType::Exn => Exn,
591-
core::AbstractHeapType::NoExn => NoExn,
592-
core::AbstractHeapType::Any => Any,
593-
core::AbstractHeapType::Eq => Eq,
594-
core::AbstractHeapType::Struct => Struct,
595-
core::AbstractHeapType::Array => Array,
596-
core::AbstractHeapType::NoFunc => NoFunc,
597-
core::AbstractHeapType::NoExtern => NoExtern,
598-
core::AbstractHeapType::None => None,
599-
core::AbstractHeapType::I31 => I31,
600-
};
601-
Self::Abstract { shared, ty }
602-
}
603-
core::HeapType::Concrete(Index::Num(i, _)) => Self::Concrete(i),
604-
core::HeapType::Concrete(_) => panic!("unresolved index"),
605-
}
606-
}
607-
}
608-
609-
impl<T: std::fmt::Debug> From<&core::TypeUse<'_, T>> for u32 {
610-
fn from(u: &core::TypeUse<'_, T>) -> Self {
611-
match &u.index {
612-
Some(i) => (*i).into(),
613-
None => unreachable!("unresolved type use in encoding: {:?}", u),
614-
}
615-
}
616-
}
617-
618565
impl From<&CoreInstantiationArgKind<'_>> for wasm_encoder::ModuleArg {
619566
fn from(kind: &CoreInstantiationArgKind) -> Self {
620567
match kind {
@@ -807,6 +754,9 @@ impl From<&ModuleType<'_>> for wasm_encoder::ModuleType {
807754
ModuleTypeDecl::Type(t) => {
808755
encoded.ty().subtype(&t.to_subtype());
809756
}
757+
ModuleTypeDecl::Rec(rec) => {
758+
encoded.ty().rec(rec.types.iter().map(|t| t.to_subtype()));
759+
}
810760
ModuleTypeDecl::Alias(a) => match &a.target {
811761
AliasTarget::Outer {
812762
outer,

crates/wast/src/component/component.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::annotation;
22
use crate::component::*;
3-
use crate::core::Producers;
3+
use crate::core::{self, Producers};
44
use crate::kw;
55
use crate::parser::{Parse, Parser, Result};
66
use crate::token::Index;
@@ -146,6 +146,7 @@ pub enum ComponentField<'a> {
146146
CoreModule(CoreModule<'a>),
147147
CoreInstance(CoreInstance<'a>),
148148
CoreType(CoreType<'a>),
149+
CoreRec(core::Rec<'a>),
149150
Component(NestedComponent<'a>),
150151
Instance(Instance<'a>),
151152
Alias(Alias<'a>),
@@ -185,6 +186,10 @@ impl<'a> Parse<'a> for ComponentField<'a> {
185186
if parser.peek2::<kw::func>()? {
186187
return Ok(Self::CoreFunc(parser.parse()?));
187188
}
189+
if parser.peek2::<kw::rec>()? {
190+
parser.parse::<kw::core>()?;
191+
return Ok(Self::CoreRec(parser.parse()?));
192+
}
188193
} else {
189194
if parser.peek::<kw::component>()? {
190195
return Ok(Self::Component(parser.parse()?));

crates/wast/src/component/expand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ impl<'a> Expander<'a> {
105105
self.expand_core_type(t);
106106
None
107107
}
108+
ComponentField::CoreRec(_) => None,
108109
ComponentField::Component(c) => self.expand_nested_component(c),
109110
ComponentField::Instance(i) => self.expand_instance(i),
110111
ComponentField::Type(t) => {
@@ -452,6 +453,7 @@ impl<'a> Expander<'a> {
452453
core::InnerTypeKind::Struct(_) => {}
453454
core::InnerTypeKind::Array(_) => {}
454455
},
456+
ModuleTypeDecl::Rec(_) => {}
455457
ModuleTypeDecl::Alias(_) => {}
456458
ModuleTypeDecl::Import(ty) => {
457459
expand_sig(&mut ty.item, &mut to_prepend, &mut func_type_to_idx);
@@ -497,8 +499,6 @@ impl<'a> Expander<'a> {
497499
// `shared` function must use an explicit type index,
498500
// e.g., `(func (type $ft))`.
499501
def: key.to_def(item.span, /* shared = */ false),
500-
parent: None,
501-
final_type: None,
502502
}));
503503
let idx = Index::Id(id);
504504
t.index = Some(idx);

0 commit comments

Comments
 (0)