From 498cc789d1638a56d5540b1ffc7bca85d23a04b7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 May 2022 09:26:19 -0700 Subject: [PATCH 1/2] Refactor interface type representation in `wast` This commit updates the `wast` representation of interface types to match more closely what `wasmparser` does. Previously `wast` primarily used `ComponentTypeUse<'_, InterType<'_>>` for references and `InterType<'_>` for definitions. This meant, though, that references could not use primitives by-value. Additionally it also meant that the parsing for `ComponentTypeUse` actually used `IndexOrRef` to parse either `$t` or `(type $t)` but `ComponentTypeUse` is used for many other constructs where it would not be appropriate for a bare index `$t` to be parsed, for example this should not parse: (component (type $ty (module)) (import "" (module $m $ty))) This commit instead refactors all uses of `ComponentTypeUse<'_, InterType<'_>>` to instead use a new `InterTypeRef<'_>` construct. Additionally a `Primitive` was split out from the existing `InterType<'_>` and added as a variant to the `InterTypeRef<'_>` enum as well. This reflects the organization in the `wasmparser` crate and means that primitive types can be used inline instead of references and such. Closes #600 --- crates/wasmprinter/src/lib.rs | 2 - crates/wast/src/component/binary.rs | 46 ++- crates/wast/src/component/deftype.rs | 8 +- crates/wast/src/component/expand.rs | 67 ++-- crates/wast/src/component/intertype.rs | 322 ++++++++++---------- crates/wast/src/component/resolve.rs | 48 ++- crates/wast/src/component/types.rs | 12 +- tests/dump/component-inline-type.wat.dump | 13 +- tests/dump/component-instance-type.wat.dump | 19 +- 9 files changed, 272 insertions(+), 265 deletions(-) diff --git a/crates/wasmprinter/src/lib.rs b/crates/wasmprinter/src/lib.rs index d367308884..8febcf7ee3 100644 --- a/crates/wasmprinter/src/lib.rs +++ b/crates/wasmprinter/src/lib.rs @@ -2370,9 +2370,7 @@ impl Printer { match ty { InterfaceTypeRef::Primitive(ty) => self.print_primitive_type(ty), InterfaceTypeRef::Type(idx) => { - self.result.push_str("(type "); self.print_idx(&state.type_names, *idx)?; - self.result.push(')'); } } diff --git a/crates/wast/src/component/binary.rs b/crates/wast/src/component/binary.rs index e15b0363c6..590e4db734 100644 --- a/crates/wast/src/component/binary.rs +++ b/crates/wast/src/component/binary.rs @@ -376,23 +376,31 @@ impl Encode for TypeField<'_> { } } +impl Encode for Primitive { + fn encode(&self, e: &mut Vec) { + match self { + Primitive::Unit => e.push(0x7f), + Primitive::Bool => e.push(0x7e), + Primitive::S8 => e.push(0x7d), + Primitive::U8 => e.push(0x7c), + Primitive::S16 => e.push(0x7b), + Primitive::U16 => e.push(0x7a), + Primitive::S32 => e.push(0x79), + Primitive::U32 => e.push(0x78), + Primitive::S64 => e.push(0x77), + Primitive::U64 => e.push(0x76), + Primitive::Float32 => e.push(0x75), + Primitive::Float64 => e.push(0x74), + Primitive::Char => e.push(0x73), + Primitive::String => e.push(0x72), + } + } +} + impl<'a> Encode for InterType<'a> { fn encode(&self, e: &mut Vec) { match self { - InterType::Unit => e.push(0x7f), - InterType::Bool => e.push(0x7e), - InterType::S8 => e.push(0x7d), - InterType::U8 => e.push(0x7c), - InterType::S16 => e.push(0x7b), - InterType::U16 => e.push(0x7a), - InterType::S32 => e.push(0x79), - InterType::U32 => e.push(0x78), - InterType::S64 => e.push(0x77), - InterType::U64 => e.push(0x76), - InterType::Float32 => e.push(0x75), - InterType::Float64 => e.push(0x74), - InterType::Char => e.push(0x73), - InterType::String => e.push(0x72), + InterType::Primitive(p) => p.encode(e), InterType::Record(r) => r.encode(e), InterType::Variant(v) => v.encode(e), InterType::List(l) => l.encode(e), @@ -406,6 +414,16 @@ impl<'a> Encode for InterType<'a> { } } +impl<'a> Encode for InterTypeRef<'a> { + fn encode(&self, e: &mut Vec) { + match self { + InterTypeRef::Primitive(p) => p.encode(e), + InterTypeRef::Ref(i) => i.encode(e), + InterTypeRef::Inline(_) => unreachable!("should be expanded by now"), + } + } +} + impl<'a> Encode for DefType<'a> { fn encode(&self, e: &mut Vec) { match self { diff --git a/crates/wast/src/component/deftype.rs b/crates/wast/src/component/deftype.rs index 6ddab3e0a8..6024565724 100644 --- a/crates/wast/src/component/deftype.rs +++ b/crates/wast/src/component/deftype.rs @@ -101,7 +101,7 @@ pub struct ComponentFunctionType<'a> { /// name resolution and a name for the custom `name` section. pub params: Box<[ComponentFunctionParam<'a>]>, /// The result type of a function. - pub result: ComponentTypeUse<'a, InterType<'a>>, + pub result: InterTypeRef<'a>, } impl<'a> Parse<'a> for ComponentFunctionType<'a> { @@ -125,7 +125,7 @@ impl<'a> Parse<'a> for ComponentFunctionType<'a> { })? } else { // If the result is omitted, use `unit`. - ComponentTypeUse::Inline(InterType::Unit) + InterTypeRef::Primitive(Primitive::Unit) }; Ok(Self { params: params.into(), @@ -140,7 +140,7 @@ pub struct ComponentFunctionParam<'a> { /// An optionally-specified name of this parameter pub name: Option<&'a str>, /// The type of the parameter. - pub type_: ComponentTypeUse<'a, InterType<'a>>, + pub type_: InterTypeRef<'a>, } /// A type for a nested module @@ -306,7 +306,7 @@ impl<'a> From> for InstanceTypeField<'a> { #[derive(Debug, Clone)] pub struct ValueType<'a> { /// The type of the value. - pub value_type: ComponentTypeUse<'a, InterType<'a>>, + pub value_type: InterTypeRef<'a>, } impl<'a> Parse<'a> for ValueType<'a> { diff --git a/crates/wast/src/component/expand.rs b/crates/wast/src/component/expand.rs index 9b545c81be..1b2ea9ac02 100644 --- a/crates/wast/src/component/expand.rs +++ b/crates/wast/src/component/expand.rs @@ -247,9 +247,9 @@ impl<'a> Expander<'a> { fn expand_func_ty(&mut self, ty: &mut ComponentFunctionType<'a>) { for param in ty.params.iter_mut() { - self.expand_component_type_use(&mut param.type_); + self.expand_intertype_ref(&mut param.type_); } - self.expand_component_type_use(&mut ty.result); + self.expand_intertype_ref(&mut ty.result); } fn expand_module_ty(&mut self, ty: &mut ModuleType<'a>) { @@ -358,60 +358,73 @@ impl<'a> Expander<'a> { } fn expand_value_ty(&mut self, ty: &mut ValueType<'a>) { - self.expand_component_type_use(&mut ty.value_type); + self.expand_intertype_ref(&mut ty.value_type); } fn expand_intertype(&mut self, ty: &mut InterType<'a>) { match ty { - InterType::Unit - | InterType::Bool - | InterType::S8 - | InterType::U8 - | InterType::S16 - | InterType::U16 - | InterType::S32 - | InterType::U32 - | InterType::S64 - | InterType::U64 - | InterType::Float32 - | InterType::Float64 - | InterType::Char - | InterType::String - | InterType::Flags(_) - | InterType::Enum(_) => {} + InterType::Primitive(_) | InterType::Flags(_) | InterType::Enum(_) => {} InterType::Record(r) => { for field in r.fields.iter_mut() { - self.expand_component_type_use(&mut field.type_); + self.expand_intertype_ref(&mut field.type_); } } InterType::Variant(v) => { for case in v.cases.iter_mut() { - self.expand_component_type_use(&mut case.type_); + self.expand_intertype_ref(&mut case.type_); } } InterType::List(t) => { - self.expand_component_type_use(&mut t.element); + self.expand_intertype_ref(&mut t.element); } InterType::Tuple(t) => { for field in t.fields.iter_mut() { - self.expand_component_type_use(field); + self.expand_intertype_ref(field); } } InterType::Union(u) => { for arm in u.arms.iter_mut() { - self.expand_component_type_use(arm); + self.expand_intertype_ref(arm); } } InterType::Option(t) => { - self.expand_component_type_use(&mut t.element); + self.expand_intertype_ref(&mut t.element); } InterType::Expected(e) => { - self.expand_component_type_use(&mut e.ok); - self.expand_component_type_use(&mut e.err); + self.expand_intertype_ref(&mut e.ok); + self.expand_intertype_ref(&mut e.err); } } } + fn expand_intertype_ref(&mut self, ty: &mut InterTypeRef<'a>) { + let inline = match ty { + InterTypeRef::Primitive(_) | InterTypeRef::Ref(_) => return, + InterTypeRef::Inline(inline) => { + mem::replace(inline, InterType::Primitive(Primitive::Unit)) + } + }; + // If this inline type has already been defined within this context + // then reuse the previously defined type to avoid injecting too many + // types into the type index space. + if let Some(idx) = inline.key().lookup(self) { + *ty = InterTypeRef::Ref(idx); + return; + } + // And if this type isn't already defined we append it to the index + // space with a fresh and unique name. + let span = Span::from_offset(0); // FIXME: don't manufacture + let id = gensym::gen(span); + self.to_prepend.push(TypeField { + span, + id: Some(id), + name: None, + def: inline.into_def(), + }); + let idx = Index::Id(id); + *ty = InterTypeRef::Ref(idx); + } + fn expand_component_type_use( &mut self, item: &mut ComponentTypeUse<'a, T>, diff --git a/crates/wast/src/component/intertype.rs b/crates/wast/src/component/intertype.rs index b04949f2da..0798984b4f 100644 --- a/crates/wast/src/component/intertype.rs +++ b/crates/wast/src/component/intertype.rs @@ -1,12 +1,11 @@ -use crate::component::*; use crate::kw; -use crate::parser::{Cursor, Parse, Parser, Peek, Result}; +use crate::parser::{Parse, Parser, Result}; use crate::token::*; /// An interface-types type. #[allow(missing_docs)] #[derive(Debug, Clone)] -pub enum InterType<'a> { +pub enum Primitive { Unit, Bool, S8, @@ -21,129 +20,134 @@ pub enum InterType<'a> { Float64, Char, String, - Record(Record<'a>), - Variant(Variant<'a>), - List(List<'a>), - Tuple(Tuple<'a>), - Flags(Flags<'a>), - Enum(Enum<'a>), - Union(Union<'a>), - Option(OptionType<'a>), - Expected(Expected<'a>), } -impl<'a> Parse<'a> for InterType<'a> { +impl<'a> Parse<'a> for Primitive { fn parse(parser: Parser<'a>) -> Result { let mut l = parser.lookahead1(); if l.peek::() { parser.parse::()?; - Ok(InterType::Unit) + Ok(Primitive::Unit) } else if l.peek::() { parser.parse::()?; - Ok(InterType::Bool) + Ok(Primitive::Bool) } else if l.peek::() { parser.parse::()?; - Ok(InterType::S8) + Ok(Primitive::S8) } else if l.peek::() { parser.parse::()?; - Ok(InterType::U8) + Ok(Primitive::U8) } else if l.peek::() { parser.parse::()?; - Ok(InterType::S16) + Ok(Primitive::S16) } else if l.peek::() { parser.parse::()?; - Ok(InterType::U16) + Ok(Primitive::U16) } else if l.peek::() { parser.parse::()?; - Ok(InterType::S32) + Ok(Primitive::S32) } else if l.peek::() { parser.parse::()?; - Ok(InterType::U32) + Ok(Primitive::U32) } else if l.peek::() { parser.parse::()?; - Ok(InterType::S64) + Ok(Primitive::S64) } else if l.peek::() { parser.parse::()?; - Ok(InterType::U64) + Ok(Primitive::U64) } else if l.peek::() { parser.parse::()?; - Ok(InterType::Float32) + Ok(Primitive::Float32) } else if l.peek::() { parser.parse::()?; - Ok(InterType::Float64) + Ok(Primitive::Float64) } else if l.peek::() { parser.parse::()?; - Ok(InterType::Char) + Ok(Primitive::Char) } else if l.peek::() { parser.parse::()?; - Ok(InterType::String) - } else if l.peek::() { - if parser.peek2::() { - let record = parser.parse()?; - Ok(InterType::Record(record)) - } else if parser.peek2::() { - let variant = parser.parse()?; - Ok(InterType::Variant(variant)) - } else if parser.peek2::() { - let list = parser.parse()?; - Ok(InterType::List(list)) - } else if parser.peek2::() { - let tuple = parser.parse()?; - Ok(InterType::Tuple(tuple)) - } else if parser.peek2::() { - let flags = parser.parse()?; - Ok(InterType::Flags(flags)) - } else if parser.peek2::() { - let enum_ = parser.parse()?; - Ok(InterType::Enum(enum_)) - } else if parser.peek2::() { - let union = parser.parse()?; - Ok(InterType::Union(union)) - } else if parser.peek2::() { - let optional = parser.parse()?; - Ok(InterType::Option(optional)) - } else if parser.peek2::() { - let expected = parser.parse()?; - Ok(InterType::Expected(expected)) - } else { - Err(parser.error("expected derived intertype")) - } + Ok(Primitive::String) } else { Err(l.error()) } } } -impl<'a> Peek for InterType<'a> { - fn peek(cursor: Cursor<'_>) -> bool { - kw::unit::peek(cursor) - || kw::bool_::peek(cursor) - || kw::s8::peek(cursor) - || kw::u8::peek(cursor) - || kw::s16::peek(cursor) - || kw::u16::peek(cursor) - || kw::s32::peek(cursor) - || kw::u32::peek(cursor) - || kw::s64::peek(cursor) - || kw::u64::peek(cursor) - || kw::float32::peek(cursor) - || kw::float64::peek(cursor) - || kw::char::peek(cursor) - || kw::string::peek(cursor) - || (LParen::peek(cursor) - && (kw::record::peek2(cursor) - || kw::record::peek2(cursor) - || kw::variant::peek2(cursor) - || kw::list::peek2(cursor) - || kw::tuple::peek2(cursor) - || kw::flags::peek2(cursor) - || kw::enum_::peek2(cursor) - || kw::union::peek2(cursor) - || kw::option::peek2(cursor) - || kw::expected::peek2(cursor))) +/// An interface-types type. +#[allow(missing_docs)] +#[derive(Debug, Clone)] +pub enum InterType<'a> { + Primitive(Primitive), + Record(Record<'a>), + Variant(Variant<'a>), + List(List<'a>), + Tuple(Tuple<'a>), + Flags(Flags<'a>), + Enum(Enum<'a>), + Union(Union<'a>), + Option(OptionType<'a>), + Expected(Expected<'a>), +} + +impl<'a> Parse<'a> for InterType<'a> { + fn parse(parser: Parser<'a>) -> Result { + if parser.peek::() { + parser.parens(|parser| { + if parser.peek::() { + let record = parser.parse()?; + Ok(InterType::Record(record)) + } else if parser.peek::() { + let variant = parser.parse()?; + Ok(InterType::Variant(variant)) + } else if parser.peek::() { + let list = parser.parse()?; + Ok(InterType::List(list)) + } else if parser.peek::() { + let tuple = parser.parse()?; + Ok(InterType::Tuple(tuple)) + } else if parser.peek::() { + let flags = parser.parse()?; + Ok(InterType::Flags(flags)) + } else if parser.peek::() { + let enum_ = parser.parse()?; + Ok(InterType::Enum(enum_)) + } else if parser.peek::() { + let union = parser.parse()?; + Ok(InterType::Union(union)) + } else if parser.peek::() { + let optional = parser.parse()?; + Ok(InterType::Option(optional)) + } else if parser.peek::() { + let expected = parser.parse()?; + Ok(InterType::Expected(expected)) + } else { + Err(parser.error("expected derived intertype")) + } + }) + } else { + Ok(InterType::Primitive(parser.parse()?)) + } } - fn display() -> &'static str { - "intertype" +} + +/// An interface-types type. +#[allow(missing_docs)] +#[derive(Debug, Clone)] +pub enum InterTypeRef<'a> { + Primitive(Primitive), + Inline(InterType<'a>), + Ref(Index<'a>), +} + +impl<'a> Parse<'a> for InterTypeRef<'a> { + fn parse(parser: Parser<'a>) -> Result { + if parser.peek::>() { + Ok(InterTypeRef::Ref(parser.parse()?)) + } else if parser.peek::() { + Ok(InterTypeRef::Inline(parser.parse()?)) + } else { + Ok(InterTypeRef::Primitive(parser.parse()?)) + } } } @@ -156,14 +160,12 @@ pub struct Record<'a> { impl<'a> Parse<'a> for Record<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let mut fields = Vec::new(); - while !parser.is_empty() { - fields.push(parser.parse()?); - } - Ok(Record { fields }) - }) + parser.parse::()?; + let mut fields = Vec::new(); + while !parser.is_empty() { + fields.push(parser.parens(|p| p.parse())?); + } + Ok(Record { fields }) } } @@ -173,17 +175,15 @@ pub struct Field<'a> { /// The name of the field. pub name: &'a str, /// The type of the field. - pub type_: ComponentTypeUse<'a, InterType<'a>>, + pub type_: InterTypeRef<'a>, } impl<'a> Parse<'a> for Field<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - Ok(Field { - name: parser.parse()?, - type_: parser.parse()?, - }) + parser.parse::()?; + Ok(Field { + name: parser.parse()?, + type_: parser.parse()?, }) } } @@ -197,14 +197,12 @@ pub struct Variant<'a> { impl<'a> Parse<'a> for Variant<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let mut cases = Vec::new(); - while !parser.is_empty() { - cases.push(parser.parens(|p| p.parse())?); - } - Ok(Variant { cases }) - }) + parser.parse::()?; + let mut cases = Vec::new(); + while !parser.is_empty() { + cases.push(parser.parens(|p| p.parse())?); + } + Ok(Variant { cases }) } } @@ -216,7 +214,7 @@ pub struct Case<'a> { /// Where this `component` was defined pub span: Span, /// The type of the case. - pub type_: ComponentTypeUse<'a, InterType<'a>>, + pub type_: InterTypeRef<'a>, /// The optional defaults-to name. pub defaults_to: Option<&'a str>, } @@ -247,17 +245,15 @@ impl<'a> Parse<'a> for Case<'a> { #[derive(Debug, Clone)] pub struct List<'a> { /// The element type of the array. - pub element: Box>>, + pub element: Box>, } impl<'a> Parse<'a> for List<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let ty = parser.parse()?; - Ok(List { - element: Box::new(ty), - }) + parser.parse::()?; + let ty = parser.parse()?; + Ok(List { + element: Box::new(ty), }) } } @@ -266,19 +262,17 @@ impl<'a> Parse<'a> for List<'a> { #[derive(Debug, Clone)] pub struct Tuple<'a> { /// The types of the fields of the tuple. - pub fields: Vec>>, + pub fields: Vec>, } impl<'a> Parse<'a> for Tuple<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let mut fields = Vec::new(); - while !parser.is_empty() { - fields.push(parser.parse()?); - } - Ok(Tuple { fields }) - }) + parser.parse::()?; + let mut fields = Vec::new(); + while !parser.is_empty() { + fields.push(parser.parse()?); + } + Ok(Tuple { fields }) } } @@ -291,14 +285,12 @@ pub struct Flags<'a> { impl<'a> Parse<'a> for Flags<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let mut flag_names = Vec::new(); - while !parser.is_empty() { - flag_names.push(parser.parse()?); - } - Ok(Flags { flag_names }) - }) + parser.parse::()?; + let mut flag_names = Vec::new(); + while !parser.is_empty() { + flag_names.push(parser.parse()?); + } + Ok(Flags { flag_names }) } } @@ -311,14 +303,12 @@ pub struct Enum<'a> { impl<'a> Parse<'a> for Enum<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let mut arms = Vec::new(); - while !parser.is_empty() { - arms.push(parser.parse()?); - } - Ok(Enum { arms }) - }) + parser.parse::()?; + let mut arms = Vec::new(); + while !parser.is_empty() { + arms.push(parser.parse()?); + } + Ok(Enum { arms }) } } @@ -326,19 +316,17 @@ impl<'a> Parse<'a> for Enum<'a> { #[derive(Debug, Clone)] pub struct Union<'a> { /// The arms of the union. - pub arms: Vec>>, + pub arms: Vec>, } impl<'a> Parse<'a> for Union<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let mut arms = Vec::new(); - while !parser.is_empty() { - arms.push(parser.parse()?); - } - Ok(Union { arms }) - }) + parser.parse::()?; + let mut arms = Vec::new(); + while !parser.is_empty() { + arms.push(parser.parse()?); + } + Ok(Union { arms }) } } @@ -346,17 +334,15 @@ impl<'a> Parse<'a> for Union<'a> { #[derive(Debug, Clone)] pub struct OptionType<'a> { /// The type of the value, when a value is present. - pub element: Box>>, + pub element: Box>, } impl<'a> Parse<'a> for OptionType<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let ty = parser.parse()?; - Ok(OptionType { - element: Box::new(ty), - }) + parser.parse::()?; + let ty = parser.parse()?; + Ok(OptionType { + element: Box::new(ty), }) } } @@ -365,21 +351,19 @@ impl<'a> Parse<'a> for OptionType<'a> { #[derive(Debug, Clone)] pub struct Expected<'a> { /// The type on success. - pub ok: Box>>, + pub ok: Box>, /// The type on failure. - pub err: Box>>, + pub err: Box>, } impl<'a> Parse<'a> for Expected<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parens(|parser| { - parser.parse::()?; - let ok = parser.parse()?; - let err = parser.parse()?; - Ok(Expected { - ok: Box::new(ok), - err: Box::new(err), - }) + parser.parse::()?; + let ok = parser.parse()?; + let err = parser.parse()?; + Ok(Expected { + ok: Box::new(ok), + err: Box::new(err), }) } } diff --git a/crates/wast/src/component/resolve.rs b/crates/wast/src/component/resolve.rs index 0d79ee78c2..64e190af23 100644 --- a/crates/wast/src/component/resolve.rs +++ b/crates/wast/src/component/resolve.rs @@ -296,56 +296,54 @@ fn resolve_intertype<'a, 'b>( resolve_stack: &'b mut Vec>, ) -> Result<(), Error> { match ty { - InterType::Unit => {} - InterType::Bool => {} - InterType::U8 => {} - InterType::S8 => {} - InterType::U16 => {} - InterType::S16 => {} - InterType::U32 => {} - InterType::S32 => {} - InterType::U64 => {} - InterType::S64 => {} - InterType::Float32 => {} - InterType::Float64 => {} - InterType::String => {} - InterType::Char => {} + InterType::Primitive(_) => {} InterType::Flags(_) => {} InterType::Enum(_) => {} InterType::Record(r) => { for field in r.fields.iter_mut() { - resolve_type_use(&mut field.type_, resolve_stack)?; + resolve_intertype_ref(&mut field.type_, resolve_stack)?; } } InterType::Variant(v) => { for case in v.cases.iter_mut() { - resolve_type_use(&mut case.type_, resolve_stack)?; + resolve_intertype_ref(&mut case.type_, resolve_stack)?; } } InterType::List(l) => { - resolve_type_use(&mut *l.element, resolve_stack)?; + resolve_intertype_ref(&mut *l.element, resolve_stack)?; } InterType::Tuple(t) => { for field in t.fields.iter_mut() { - resolve_type_use(field, resolve_stack)?; + resolve_intertype_ref(field, resolve_stack)?; } } InterType::Union(t) => { for arm in t.arms.iter_mut() { - resolve_type_use(arm, resolve_stack)?; + resolve_intertype_ref(arm, resolve_stack)?; } } InterType::Option(o) => { - resolve_type_use(&mut *o.element, resolve_stack)?; + resolve_intertype_ref(&mut *o.element, resolve_stack)?; } InterType::Expected(r) => { - resolve_type_use(&mut *r.ok, resolve_stack)?; - resolve_type_use(&mut *r.err, resolve_stack)?; + resolve_intertype_ref(&mut *r.ok, resolve_stack)?; + resolve_intertype_ref(&mut *r.err, resolve_stack)?; } } Ok(()) } +fn resolve_intertype_ref<'a, 'b>( + ty: &'b mut InterTypeRef<'a>, + resolve_stack: &'b mut Vec>, +) -> Result<(), Error> { + match ty { + InterTypeRef::Primitive(_) => Ok(()), + InterTypeRef::Ref(idx) => resolve_ns(idx, Ns::Type, resolve_stack), + InterTypeRef::Inline(_) => unreachable!("should be expanded by now"), + } +} + fn resolve_type_field<'a>( field: &mut TypeField<'a>, resolve_stack: &mut Vec>, @@ -353,9 +351,9 @@ fn resolve_type_field<'a>( match &mut field.def { ComponentTypeDef::DefType(DefType::Func(f)) => { for param in f.params.iter_mut() { - resolve_type_use(&mut param.type_, resolve_stack)?; + resolve_intertype_ref(&mut param.type_, resolve_stack)?; } - resolve_type_use(&mut f.result, resolve_stack)?; + resolve_intertype_ref(&mut f.result, resolve_stack)?; } ComponentTypeDef::DefType(DefType::Module(m)) => { resolve_stack.push(ComponentResolver::new(field.id)); @@ -373,7 +371,7 @@ fn resolve_type_field<'a>( resolve_stack.pop(); } ComponentTypeDef::DefType(DefType::Value(v)) => { - resolve_type_use(&mut v.value_type, resolve_stack)? + resolve_intertype_ref(&mut v.value_type, resolve_stack)? } ComponentTypeDef::InterType(i) => resolve_intertype(i, resolve_stack)?, } diff --git a/crates/wast/src/component/types.rs b/crates/wast/src/component/types.rs index 126c6ac1d0..ebc28a317c 100644 --- a/crates/wast/src/component/types.rs +++ b/crates/wast/src/component/types.rs @@ -55,10 +55,10 @@ impl<'a> Parse<'a> for TypeField<'a> { let span = parser.parse::()?.0; let id = parser.parse()?; let name = parser.parse()?; - let def = if parser.peek::() { - ComponentTypeDef::InterType(parser.parse()?) - } else { + let def = if parser.peek2::() { ComponentTypeDef::DefType(parser.parens(|p| p.parse())?) + } else { + ComponentTypeDef::InterType(parser.parse()?) }; Ok(TypeField { span, @@ -82,10 +82,8 @@ pub enum ComponentTypeUse<'a, T> { impl<'a, T: Parse<'a>> Parse<'a> for ComponentTypeUse<'a, T> { fn parse(parser: Parser<'a>) -> Result { - if parser.peek::>() { - Ok(ComponentTypeUse::Ref( - parser.parse::>()?.0, - )) + if parser.peek::>() { + Ok(ComponentTypeUse::Ref(parser.parse()?)) } else { Ok(ComponentTypeUse::Inline(parser.parse()?)) } diff --git a/tests/dump/component-inline-type.wat.dump b/tests/dump/component-inline-type.wat.dump index 1b478c8829..bb507d8d3f 100644 --- a/tests/dump/component-inline-type.wat.dump +++ b/tests/dump/component-inline-type.wat.dump @@ -18,10 +18,9 @@ 0x21 | 02 03 | import section 0x23 | 01 | 1 count 0x24 | 00 02 | [instance 0] ComponentImport { name: "", ty: 2 } - 0x26 | 01 05 | type section - 0x28 | 02 | 2 count - 0x29 | 7f | [type 3] Interface(Primitive(Unit)) - 0x2a | 4c 00 03 | [type 4] Function(ComponentFuncType { params: [], result: Type(3) }) - 0x2d | 02 03 | import section - 0x2f | 01 | 1 count - 0x30 | 00 04 | [func 0] ComponentImport { name: "", ty: 4 } + 0x26 | 01 04 | type section + 0x28 | 01 | 1 count + 0x29 | 4c 00 7f | [type 3] Function(ComponentFuncType { params: [], result: Primitive(Unit) }) + 0x2c | 02 03 | import section + 0x2e | 01 | 1 count + 0x2f | 00 03 | [func 0] ComponentImport { name: "", ty: 3 } diff --git a/tests/dump/component-instance-type.wat.dump b/tests/dump/component-instance-type.wat.dump index 7c4b60ab89..37a97bf508 100644 --- a/tests/dump/component-instance-type.wat.dump +++ b/tests/dump/component-instance-type.wat.dump @@ -1,13 +1,12 @@ 0x0 | 00 61 73 6d | version 65546 (Component) | 0a 00 01 00 - 0x8 | 01 24 | type section + 0x8 | 01 20 | type section 0xa | 01 | 1 count - 0xb | 4d 04 01 7f | [type 0] Instance([Type(Interface(Primitive(Unit))), Type(Function(ComponentFuncType { params: [], result: Type(0) })), Type(Component([Type(Interface(Primitive(Unit))), Type(Function(ComponentFuncType { params: [], result: Type(0) })), OuterType { count: 1, index: 1 }, Import(ComponentImport { name: "1", ty: 1 }), Export { name: "1", ty: 2 }])), Export { name: "c5", ty: 2 }]) - | 01 4c 00 00 - | 01 4e 05 01 - | 7f 01 4c 00 - | 00 09 02 05 - | 01 01 02 01 - | 31 01 07 01 - | 31 02 07 02 - | 63 35 02 + 0xb | 4d 03 01 4c | [type 0] Instance([Type(Function(ComponentFuncType { params: [], result: Primitive(Unit) })), Type(Component([Type(Function(ComponentFuncType { params: [], result: Primitive(Unit) })), OuterType { count: 1, index: 0 }, Import(ComponentImport { name: "1", ty: 0 }), Export { name: "1", ty: 1 }])), Export { name: "c5", ty: 1 }]) + | 00 7f 01 4e + | 04 01 4c 00 + | 7f 09 02 05 + | 01 00 02 01 + | 31 00 07 01 + | 31 01 07 02 + | 63 35 01 From e5d96558a8d87fea44739fc3be97f11f270f7aee Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 18 May 2022 16:52:32 -0700 Subject: [PATCH 2/2] List an issue in FIXME annotations --- crates/wast/src/component/expand.rs | 4 ++-- crates/wast/src/core/resolve/types.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/wast/src/component/expand.rs b/crates/wast/src/component/expand.rs index 1b2ea9ac02..1ba0ac9d41 100644 --- a/crates/wast/src/component/expand.rs +++ b/crates/wast/src/component/expand.rs @@ -413,7 +413,7 @@ impl<'a> Expander<'a> { } // And if this type isn't already defined we append it to the index // space with a fresh and unique name. - let span = Span::from_offset(0); // FIXME: don't manufacture + let span = Span::from_offset(0); // FIXME(#613): don't manufacture let id = gensym::gen(span); self.to_prepend.push(TypeField { span, @@ -432,7 +432,7 @@ impl<'a> Expander<'a> { where T: TypeReference<'a>, { - let span = Span::from_offset(0); // FIXME: don't manufacture + let span = Span::from_offset(0); // FIXME(#613): don't manufacture let dummy = ComponentTypeUse::Ref(ItemRef { idx: Index::Num(0, span), kind: kw::r#type(span), diff --git a/crates/wast/src/core/resolve/types.rs b/crates/wast/src/core/resolve/types.rs index 5b27226c9b..d38a6340c3 100644 --- a/crates/wast/src/core/resolve/types.rs +++ b/crates/wast/src/core/resolve/types.rs @@ -189,7 +189,7 @@ impl<'a> Expander<'a> { } None => T::default().key(), }; - let span = Span::from_offset(0); // FIXME: don't manufacture + let span = Span::from_offset(0); // FIXME(#613): don't manufacture let idx = self.key_to_idx(span, key); item.index = Some(ItemRef { idx,