From 90b7c7cbff0f7238eaf426df07b87b8c9495f184 Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Mon, 4 May 2020 10:35:24 -0500 Subject: [PATCH 1/7] Remove `nullref` type --- crates/wast/src/ast/types.rs | 13 ------------- crates/wast/src/binary.rs | 2 -- 2 files changed, 15 deletions(-) diff --git a/crates/wast/src/ast/types.rs b/crates/wast/src/ast/types.rs index e0afc46..d4f57f8 100644 --- a/crates/wast/src/ast/types.rs +++ b/crates/wast/src/ast/types.rs @@ -14,7 +14,6 @@ pub enum ValType<'a> { I16, Funcref, Anyref, - Nullref, Exnref, Ref(ast::Index<'a>), Optref(ast::Index<'a>), @@ -56,9 +55,6 @@ impl<'a> Parse<'a> for ValType<'a> { } else if l.peek::() { parser.parse::()?; Ok(ValType::Anyref) - } else if l.peek::() { - parser.parse::()?; - Ok(ValType::Nullref) } else if l.peek::() { parser.parens(|p| { let mut l = parser.lookahead1(); @@ -72,9 +68,6 @@ impl<'a> Parse<'a> for ValType<'a> { } else if l.peek::() { parser.parse::()?; Ok(ValType::Anyref) - } else if l.peek::() { - parser.parse::()?; - Ok(ValType::Nullref) } else if l.peek::() { parser.parse::()?; Ok(ValType::Exnref) @@ -154,8 +147,6 @@ pub enum TableElemType { Funcref, /// An element for a table that is a list of `anyref` values. Anyref, - /// An element for a table that is a list of `nullref` values. - Nullref, /// An element for a table that is a list of `exnref` values. Exnref, } @@ -174,9 +165,6 @@ impl<'a> Parse<'a> for TableElemType { } else if l.peek::() { parser.parse::()?; Ok(TableElemType::Anyref) - } else if l.peek::() { - parser.parse::()?; - Ok(TableElemType::Nullref) } else if l.peek::() { parser.parse::()?; Ok(TableElemType::Exnref) @@ -190,7 +178,6 @@ impl Peek for TableElemType { fn peek(cursor: Cursor<'_>) -> bool { kw::funcref::peek(cursor) || kw::anyref::peek(cursor) - || kw::nullref::peek(cursor) || /* legacy */ kw::anyfunc::peek(cursor) || kw::exnref::peek(cursor) } diff --git a/crates/wast/src/binary.rs b/crates/wast/src/binary.rs index e68890f..0050fc0 100644 --- a/crates/wast/src/binary.rs +++ b/crates/wast/src/binary.rs @@ -252,7 +252,6 @@ impl<'a> Encode for ValType<'a> { ValType::I16 => e.push(0x79), ValType::Funcref => e.push(0x70), ValType::Anyref => e.push(0x6f), - ValType::Nullref => e.push(0x6e), ValType::Ref(index) => { e.push(0x6d); index.encode(e); @@ -331,7 +330,6 @@ impl Encode for TableElemType { match self { TableElemType::Funcref => ValType::Funcref.encode(e), TableElemType::Anyref => ValType::Anyref.encode(e), - TableElemType::Nullref => ValType::Nullref.encode(e), TableElemType::Exnref => ValType::Exnref.encode(e), } } From 815ac0e598bdcc501710f16ee3b6d9d1e9cb0bbc Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Mon, 4 May 2020 10:51:47 -0500 Subject: [PATCH 2/7] Refactor RefType out of ValType No functional changes. This will help parsing of type-immediate ref.null and ref.is_null. Eventually we may be able to combine TableElemType with RefType as well. --- crates/wast/src/ast/types.rs | 90 ++++++++++++++++++-------------- crates/wast/src/binary.rs | 38 +++++++++----- crates/wast/src/resolve/names.rs | 4 +- 3 files changed, 78 insertions(+), 54 deletions(-) diff --git a/crates/wast/src/ast/types.rs b/crates/wast/src/ast/types.rs index d4f57f8..b972af7 100644 --- a/crates/wast/src/ast/types.rs +++ b/crates/wast/src/ast/types.rs @@ -12,13 +12,7 @@ pub enum ValType<'a> { V128, I8, I16, - Funcref, - Anyref, - Exnref, - Ref(ast::Index<'a>), - Optref(ast::Index<'a>), - Eqref, - I31ref, + Ref(RefType<'a>), Rtt(ast::Index<'a>), } @@ -48,46 +42,22 @@ impl<'a> Parse<'a> for ValType<'a> { Ok(ValType::I16) } else if l.peek::() { parser.parse::()?; - Ok(ValType::Funcref) + Ok(ValType::Ref(RefType::Func)) } else if l.peek::() { parser.parse::()?; - Ok(ValType::Funcref) + Ok(ValType::Ref(RefType::Func)) } else if l.peek::() { parser.parse::()?; - Ok(ValType::Anyref) + Ok(ValType::Ref(RefType::Any)) } else if l.peek::() { parser.parens(|p| { let mut l = parser.lookahead1(); if l.peek::() { p.parse::()?; - - let mut l = parser.lookahead1(); - if l.peek::() { - parser.parse::()?; - Ok(ValType::Funcref) - } else if l.peek::() { - parser.parse::()?; - Ok(ValType::Anyref) - } else if l.peek::() { - parser.parse::()?; - Ok(ValType::Exnref) - } else if l.peek::() { - parser.parse::()?; - Ok(ValType::Eqref) - } else if l.peek::() { - parser.parse::()?; - Ok(ValType::I31ref) - } else if l.peek::() { - parser.parse::()?; - Ok(ValType::Optref(parser.parse()?)) - } else if l.peek::() { - Ok(ValType::Ref(parser.parse()?)) - } else { - Err(l.error()) - } + Ok(ValType::Ref(p.parse()?)) } else if l.peek::() { p.parse::()?; - Ok(ValType::Optref(parser.parse()?)) + Ok(ValType::Ref(RefType::OptType(parser.parse()?))) } else if l.peek::() { p.parse::()?; Ok(ValType::Rtt(parser.parse()?)) @@ -97,13 +67,55 @@ impl<'a> Parse<'a> for ValType<'a> { }) } else if l.peek::() { parser.parse::()?; - Ok(ValType::Exnref) + Ok(ValType::Ref(RefType::Exn)) } else if l.peek::() { parser.parse::()?; - Ok(ValType::Eqref) + Ok(ValType::Ref(RefType::Eq)) } else if l.peek::() { parser.parse::()?; - Ok(ValType::I31ref) + Ok(ValType::Ref(RefType::I31)) + } else { + Err(l.error()) + } + } +} + +/// The reference value types for a wasm module. +#[allow(missing_docs)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +pub enum RefType<'a> { + Func, + Any, + Exn, + Eq, + I31, + Type(ast::Index<'a>), + OptType(ast::Index<'a>), +} + +impl<'a> Parse<'a> for RefType<'a> { + fn parse(parser: Parser<'a>) -> Result { + let mut l = parser.lookahead1(); + if l.peek::() { + parser.parse::()?; + Ok(RefType::Func) + } else if l.peek::() { + parser.parse::()?; + Ok(RefType::Any) + } else if l.peek::() { + parser.parse::()?; + Ok(RefType::Exn) + } else if l.peek::() { + parser.parse::()?; + Ok(RefType::Eq) + } else if l.peek::() { + parser.parse::()?; + Ok(RefType::I31) + } else if l.peek::() { + parser.parse::()?; + Ok(RefType::OptType(parser.parse()?)) + } else if l.peek::() { + Ok(RefType::Type(parser.parse()?)) } else { Err(l.error()) } diff --git a/crates/wast/src/binary.rs b/crates/wast/src/binary.rs index 0050fc0..a3c0a18 100644 --- a/crates/wast/src/binary.rs +++ b/crates/wast/src/binary.rs @@ -250,23 +250,33 @@ impl<'a> Encode for ValType<'a> { ValType::V128 => e.push(0x7b), ValType::I8 => e.push(0x7a), ValType::I16 => e.push(0x79), - ValType::Funcref => e.push(0x70), - ValType::Anyref => e.push(0x6f), - ValType::Ref(index) => { - e.push(0x6d); + ValType::Ref(ty) => { + ty.encode(e); + } + ValType::Rtt(index) => { + e.push(0x69); index.encode(e); } - ValType::Optref(index) => { - e.push(0x6c); + } + } +} + +impl<'a> Encode for RefType<'a> { + fn encode(&self, e: &mut Vec) { + match self { + RefType::Func => e.push(0x70), + RefType::Any => e.push(0x6f), + RefType::Eq => e.push(0x6b), + RefType::I31 => e.push(0x6a), + RefType::Exn => e.push(0x68), + RefType::Type(index) => { + e.push(0x6d); index.encode(e); } - ValType::Eqref => e.push(0x6b), - ValType::I31ref => e.push(0x6a), - ValType::Rtt(index) => { - e.push(0x69); + RefType::OptType(index) => { + e.push(0x6c); index.encode(e); } - ValType::Exnref => e.push(0x68), } } } @@ -328,9 +338,9 @@ impl Encode for TableType { impl Encode for TableElemType { fn encode(&self, e: &mut Vec) { match self { - TableElemType::Funcref => ValType::Funcref.encode(e), - TableElemType::Anyref => ValType::Anyref.encode(e), - TableElemType::Exnref => ValType::Exnref.encode(e), + TableElemType::Funcref => RefType::Func.encode(e), + TableElemType::Anyref => RefType::Any.encode(e), + TableElemType::Exnref => RefType::Exn.encode(e), } } } diff --git a/crates/wast/src/resolve/names.rs b/crates/wast/src/resolve/names.rs index e0619f7..8307c47 100644 --- a/crates/wast/src/resolve/names.rs +++ b/crates/wast/src/resolve/names.rs @@ -209,7 +209,9 @@ impl<'a> Resolver<'a> { fn resolve_valtype(&self, ty: &mut ValType<'a>) -> Result<(), Error> { match ty { - ValType::Ref(i) | ValType::Optref(i) | ValType::Rtt(i) => { + ValType::Ref(RefType::Type(i)) + | ValType::Ref(RefType::OptType(i)) + | ValType::Rtt(i) => { self.ns(Ns::Type) .resolve(i) .map_err(|id| self.resolve_error(id, "type"))?; From 0eca9399b4c0ca5dcc2c4c61b5f7757fcec834c3 Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Mon, 4 May 2020 11:49:10 -0500 Subject: [PATCH 3/7] Make ref.null/is_null use a ref-type immediate The type uses the formal reference-types production, so it's `ref.null any` not `ref.null anyref`. The elem segment parser also had to be updated to check the type of ref.null used is compatible with the element segment type. This is tricky with subtypes, so for now it just does strict equality. --- crates/wast/src/ast/expr.rs | 6 +++--- crates/wast/src/ast/table.rs | 12 ++++++++---- crates/wast/src/ast/types.rs | 12 ++++++++++-- crates/wast/src/binary.rs | 4 ++-- crates/wast/src/resolve/names.rs | 19 ++++++++++++++++--- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/crates/wast/src/ast/expr.rs b/crates/wast/src/ast/expr.rs index 1febe48..f0b563c 100644 --- a/crates/wast/src/ast/expr.rs +++ b/crates/wast/src/ast/expr.rs @@ -1,4 +1,4 @@ -use crate::ast::{self, kw}; +use crate::ast::{self, kw, RefType}; use crate::parser::{Parse, Parser, Result}; use std::mem; @@ -411,8 +411,8 @@ instructions! { TableSize(TableArg<'a>) : [0xfc, 0x10] : "table.size", TableGrow(TableArg<'a>) : [0xfc, 0x0f] : "table.grow", - RefNull : [0xd0] : "ref.null", - RefIsNull : [0xd1] : "ref.is_null", + RefNull(RefType<'a>) : [0xd0] : "ref.null", + RefIsNull(RefType<'a>) : [0xd1] : "ref.is_null", RefHost(u32) : [0xff] : "ref.host", // only used in test harness RefFunc(ast::Index<'a>) : [0xd2] : "ref.func", diff --git a/crates/wast/src/ast/table.rs b/crates/wast/src/ast/table.rs index a59bb3a..eee4b24 100644 --- a/crates/wast/src/ast/table.rs +++ b/crates/wast/src/ast/table.rs @@ -208,12 +208,12 @@ impl<'a> ElemPayload<'a> { let func = parser.parens(|p| match p.parse::>()? { Some(_) => { if parser.peek::() { - parser.parens(parse_ref_func) + parser.parens(|p| parse_ref_func(p, ty)) } else { - parse_ref_func(parser) + parse_ref_func(parser, ty) } } - None => parse_ref_func(p), + None => parse_ref_func(parser, ty), })?; exprs.push(func); } @@ -221,10 +221,14 @@ impl<'a> ElemPayload<'a> { } } -fn parse_ref_func<'a>(parser: Parser<'a>) -> Result>> { +fn parse_ref_func<'a>(parser: Parser<'a>, ty: ast::TableElemType) -> Result>> { let mut l = parser.lookahead1(); if l.peek::() { parser.parse::()?; + let null_ty: ast::RefType = parser.parse()?; + if null_ty != ty.into() { + return Err(parser.error("elem segment item doesn't match elem segment type")); + } Ok(None) } else if l.peek::() { parser.parse::()?; diff --git a/crates/wast/src/ast/types.rs b/crates/wast/src/ast/types.rs index b972af7..874533d 100644 --- a/crates/wast/src/ast/types.rs +++ b/crates/wast/src/ast/types.rs @@ -93,6 +93,16 @@ pub enum RefType<'a> { OptType(ast::Index<'a>), } +impl<'a> From for RefType<'a> { + fn from(elem: TableElemType) -> Self { + match elem { + TableElemType::Funcref => RefType::Func, + TableElemType::Anyref => RefType::Any, + TableElemType::Exnref => RefType::Exn, + } + } +} + impl<'a> Parse<'a> for RefType<'a> { fn parse(parser: Parser<'a>) -> Result { let mut l = parser.lookahead1(); @@ -151,8 +161,6 @@ impl<'a> Parse<'a> for GlobalType<'a> { } /// List of different kinds of table types we can have. -/// -/// Currently there's only one, a `funcref`. #[derive(Copy, Clone, Debug)] pub enum TableElemType { /// An element for a table that is a list of functions. diff --git a/crates/wast/src/binary.rs b/crates/wast/src/binary.rs index a3c0a18..a159776 100644 --- a/crates/wast/src/binary.rs +++ b/crates/wast/src/binary.rs @@ -525,7 +525,7 @@ impl Encode for ElemPayload<'_> { fn encode(&self, e: &mut Vec) { match self { ElemPayload::Indices(v) => v.encode(e), - ElemPayload::Exprs { exprs, .. } => { + ElemPayload::Exprs { exprs, ty } => { exprs.len().encode(e); for idx in exprs { match idx { @@ -533,7 +533,7 @@ impl Encode for ElemPayload<'_> { Instruction::RefFunc(*idx).encode(e); } None => { - Instruction::RefNull.encode(e); + Instruction::RefNull((*ty).into()).encode(e); } } Instruction::End(None).encode(e); diff --git a/crates/wast/src/resolve/names.rs b/crates/wast/src/resolve/names.rs index 8307c47..19acef7 100644 --- a/crates/wast/src/resolve/names.rs +++ b/crates/wast/src/resolve/names.rs @@ -209,9 +209,20 @@ impl<'a> Resolver<'a> { fn resolve_valtype(&self, ty: &mut ValType<'a>) -> Result<(), Error> { match ty { - ValType::Ref(RefType::Type(i)) - | ValType::Ref(RefType::OptType(i)) - | ValType::Rtt(i) => { + ValType::Ref(ty) => self.resolve_reftype(ty)?, + ValType::Rtt(i) => { + self.ns(Ns::Type) + .resolve(i) + .map_err(|id| self.resolve_error(id, "type"))?; + } + _ => {} + } + Ok(()) + } + + fn resolve_reftype(&self, ty: &mut RefType<'a>) -> Result<(), Error> { + match ty { + RefType::Type(i) | RefType::OptType(i) => { self.ns(Ns::Type) .resolve(i) .map_err(|id| self.resolve_error(id, "type"))?; @@ -550,6 +561,8 @@ impl<'a, 'b> ExprResolver<'a, 'b> { self.resolver.resolve_valtype(&mut s.to) } + RefNull(ty) | RefIsNull(ty) => self.resolver.resolve_reftype(ty), + _ => Ok(()), } } From c7ac34af2a5e3c52c1b52856f2e7ce7b0d9444d5 Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Mon, 4 May 2020 11:58:25 -0500 Subject: [PATCH 4/7] Rename `anyref` to `externref` but leave a backwards-compat alias `anyref` is going to be a tricky thing to rename, if even possible. For now an alias seems to be reasonable. --- crates/wast/src/ast/mod.rs | 2 ++ crates/wast/src/ast/types.rs | 28 +++++++++++++++++++++------- crates/wast/src/binary.rs | 4 ++-- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/crates/wast/src/ast/mod.rs b/crates/wast/src/ast/mod.rs index 35eaf29..07cd6df 100644 --- a/crates/wast/src/ast/mod.rs +++ b/crates/wast/src/ast/mod.rs @@ -348,6 +348,8 @@ pub mod kw { custom_keyword!(exn); custom_keyword!(exnref); custom_keyword!(export); + custom_keyword!(r#extern = "extern"); + custom_keyword!(externref); custom_keyword!(eq); custom_keyword!(eqref); custom_keyword!(f32); diff --git a/crates/wast/src/ast/types.rs b/crates/wast/src/ast/types.rs index 874533d..601a446 100644 --- a/crates/wast/src/ast/types.rs +++ b/crates/wast/src/ast/types.rs @@ -46,9 +46,14 @@ impl<'a> Parse<'a> for ValType<'a> { } else if l.peek::() { parser.parse::()?; Ok(ValType::Ref(RefType::Func)) + } else if l.peek::() { + parser.parse::()?; + Ok(ValType::Ref(RefType::Extern)) } else if l.peek::() { + // Parse `anyref` as an alias of `externref` until all tests are + // ported to use the new name parser.parse::()?; - Ok(ValType::Ref(RefType::Any)) + Ok(ValType::Ref(RefType::Extern)) } else if l.peek::() { parser.parens(|p| { let mut l = parser.lookahead1(); @@ -85,7 +90,7 @@ impl<'a> Parse<'a> for ValType<'a> { #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] pub enum RefType<'a> { Func, - Any, + Extern, Exn, Eq, I31, @@ -97,7 +102,7 @@ impl<'a> From for RefType<'a> { fn from(elem: TableElemType) -> Self { match elem { TableElemType::Funcref => RefType::Func, - TableElemType::Anyref => RefType::Any, + TableElemType::Externref => RefType::Extern, TableElemType::Exnref => RefType::Exn, } } @@ -109,9 +114,12 @@ impl<'a> Parse<'a> for RefType<'a> { if l.peek::() { parser.parse::()?; Ok(RefType::Func) + } else if l.peek::() { + parser.parse::()?; + Ok(RefType::Extern) } else if l.peek::() { parser.parse::()?; - Ok(RefType::Any) + Ok(RefType::Extern) } else if l.peek::() { parser.parse::()?; Ok(RefType::Exn) @@ -165,8 +173,8 @@ impl<'a> Parse<'a> for GlobalType<'a> { pub enum TableElemType { /// An element for a table that is a list of functions. Funcref, - /// An element for a table that is a list of `anyref` values. - Anyref, + /// An element for a table that is a list of `externref` values. + Externref, /// An element for a table that is a list of `exnref` values. Exnref, } @@ -183,8 +191,13 @@ impl<'a> Parse<'a> for TableElemType { parser.parse::()?; Ok(TableElemType::Funcref) } else if l.peek::() { + // Parse `anyref` as an alias of `externref` until all tests are + // ported to use the new name parser.parse::()?; - Ok(TableElemType::Anyref) + Ok(TableElemType::Externref) + } else if l.peek::() { + parser.parse::()?; + Ok(TableElemType::Externref) } else if l.peek::() { parser.parse::()?; Ok(TableElemType::Exnref) @@ -198,6 +211,7 @@ impl Peek for TableElemType { fn peek(cursor: Cursor<'_>) -> bool { kw::funcref::peek(cursor) || kw::anyref::peek(cursor) + || kw::externref::peek(cursor) || /* legacy */ kw::anyfunc::peek(cursor) || kw::exnref::peek(cursor) } diff --git a/crates/wast/src/binary.rs b/crates/wast/src/binary.rs index a159776..96add44 100644 --- a/crates/wast/src/binary.rs +++ b/crates/wast/src/binary.rs @@ -265,7 +265,7 @@ impl<'a> Encode for RefType<'a> { fn encode(&self, e: &mut Vec) { match self { RefType::Func => e.push(0x70), - RefType::Any => e.push(0x6f), + RefType::Extern => e.push(0x6f), RefType::Eq => e.push(0x6b), RefType::I31 => e.push(0x6a), RefType::Exn => e.push(0x68), @@ -339,7 +339,7 @@ impl Encode for TableElemType { fn encode(&self, e: &mut Vec) { match self { TableElemType::Funcref => RefType::Func.encode(e), - TableElemType::Anyref => RefType::Any.encode(e), + TableElemType::Externref => RefType::Extern.encode(e), TableElemType::Exnref => RefType::Exn.encode(e), } } From d0b76a14bcc5d9ff8456a1c98c2aecfd7c40327f Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Mon, 4 May 2020 12:21:00 -0500 Subject: [PATCH 5/7] Fix regression/gc-struct to use ref-type immediate ref.null --- tests/regression/gc-struct.wat | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/regression/gc-struct.wat b/tests/regression/gc-struct.wat index 0c3bf43..9aec0cc 100644 --- a/tests/regression/gc-struct.wat +++ b/tests/regression/gc-struct.wat @@ -21,6 +21,5 @@ (func struct.narrow i32 f32 struct.narrow anyref funcref - struct.narrow anyref nullref ) ) From 6e9d13c42327fec9022b2e76cd018066aa638dad Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Mon, 4 May 2020 12:21:09 -0500 Subject: [PATCH 6/7] Mark a bunch of wabt tests as failing until they update This is unfortunate, but I don't see a way around it if we want to not be blocked on wabt. At the least, we do have extensive test coverage in spidermonkey for these testsuites that will continue. --- tests/wabt.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/wabt.rs b/tests/wabt.rs index 75ea51c..c20f366 100644 --- a/tests/wabt.rs +++ b/tests/wabt.rs @@ -505,5 +505,23 @@ fn skip_test(test: &Path, contents: &str) -> bool { return true; } + // Waiting for wabt to remove subtyping from reference-types. + if test + .iter() + .any(|x| x == "bulk-memory-operations" || x == "reference-types") + || test.ends_with("reference-types.txt") + || test.ends_with("all-features.txt") + || test.ends_with("all-features.txt") + || test.ends_with("bulk-memory-named.txt") + || test.ends_with("reference-types-named.txt") + || test.ends_with("table-grow.txt") + || test.ends_with("result-exnref.txt") + || test.ends_with("global-exnref.txt") + || test.ends_with("global.txt") + || test.ends_with("bulk-memory.txt") + { + return true; + } + false } From 9e03c5cd3f3cb7ae7e36e745fd9454b644a9e79d Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Tue, 5 May 2020 14:08:11 -0500 Subject: [PATCH 7/7] Respond to review feedback --- crates/wast/src/ast/types.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/wast/src/ast/types.rs b/crates/wast/src/ast/types.rs index 601a446..797792e 100644 --- a/crates/wast/src/ast/types.rs +++ b/crates/wast/src/ast/types.rs @@ -46,8 +46,8 @@ impl<'a> Parse<'a> for ValType<'a> { } else if l.peek::() { parser.parse::()?; Ok(ValType::Ref(RefType::Func)) - } else if l.peek::() { - parser.parse::()?; + } else if l.peek::() { + parser.parse::()?; Ok(ValType::Ref(RefType::Extern)) } else if l.peek::() { // Parse `anyref` as an alias of `externref` until all tests are @@ -89,12 +89,27 @@ impl<'a> Parse<'a> for ValType<'a> { #[allow(missing_docs)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] pub enum RefType<'a> { + /// An untyped function reference: funcref. This is part of the reference + /// types proposal. Func, + /// A reference to any host value: externref. This was originally known as + /// anyref when it was the supertype of all reference value types. This is + /// part of the reference types proposal. Extern, + /// A reference to an exception: exnref. This is part of the exception + /// handling proposal. Exn, + /// A reference that has an identity that can be compared: eqref. This is + /// part of the GC proposal. Eq, + /// An unboxed 31-bit integer: i31ref. This may be going away if there is no common + /// supertype of all reference types. Part of the GC proposal. I31, + /// A reference to a function, struct, or array: ref T. This is part of the + /// GC proposal. Type(ast::Index<'a>), + /// A nullable reference to a function, struct, or array: optref T. This is + /// part of the GC proposal. OptType(ast::Index<'a>), } @@ -117,9 +132,6 @@ impl<'a> Parse<'a> for RefType<'a> { } else if l.peek::() { parser.parse::()?; Ok(RefType::Extern) - } else if l.peek::() { - parser.parse::()?; - Ok(RefType::Extern) } else if l.peek::() { parser.parse::()?; Ok(RefType::Exn)