Skip to content

Commit 5033956

Browse files
committed
Fill out some future/stream type-checking
Also expand wildcard matches in `match` statements to exhaustive matches
1 parent 5c8d4f3 commit 5033956

File tree

1 file changed

+81
-28
lines changed

1 file changed

+81
-28
lines changed

crates/wac-types/src/checker.rs

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ impl<'a> SubtypeChecker<'a> {
7979
(ItemKind::Component(a), ItemKind::Component(b)) => self.world(a, at, b, bt),
8080
(ItemKind::Module(a), ItemKind::Module(b)) => self.module(a, at, b, bt),
8181
(ItemKind::Value(a), ItemKind::Value(b)) => self.value_type(a, at, b, bt),
82-
_ => {
82+
83+
(ItemKind::Type(_), _)
84+
| (ItemKind::Func(_), _)
85+
| (ItemKind::Instance(_), _)
86+
| (ItemKind::Component(_), _)
87+
| (ItemKind::Module(_), _)
88+
| (ItemKind::Value(_), _) => {
8389
let (expected, expected_types, found, found_types) =
8490
self.expected_found(&a, at, &b, bt);
8591
bail!(
@@ -128,22 +134,29 @@ impl<'a> SubtypeChecker<'a> {
128134

129135
fn ty(&mut self, a: Type, at: &Types, b: Type, bt: &Types) -> Result<()> {
130136
match (a, b) {
131-
(Type::Resource(a), Type::Resource(b)) => return self.resource(a, at, b, bt),
132-
(Type::Func(a), Type::Func(b)) => return self.func(a, at, b, bt),
133-
(Type::Value(a), Type::Value(b)) => return self.value_type(a, at, b, bt),
134-
(Type::Interface(a), Type::Interface(b)) => return self.interface(a, at, b, bt),
135-
(Type::World(a), Type::World(b)) => return self.world(a, at, b, bt),
136-
(Type::Module(a), Type::Module(b)) => return self.module(a, at, b, bt),
137-
_ => {}
138-
}
139-
140-
let (expected, expected_types, found, found_types) = self.expected_found(&a, at, &b, bt);
141-
142-
bail!(
143-
"expected {expected}, found {found}",
144-
expected = expected.desc(expected_types),
145-
found = found.desc(found_types)
146-
)
137+
(Type::Resource(a), Type::Resource(b)) => self.resource(a, at, b, bt),
138+
(Type::Func(a), Type::Func(b)) => self.func(a, at, b, bt),
139+
(Type::Value(a), Type::Value(b)) => self.value_type(a, at, b, bt),
140+
(Type::Interface(a), Type::Interface(b)) => self.interface(a, at, b, bt),
141+
(Type::World(a), Type::World(b)) => self.world(a, at, b, bt),
142+
(Type::Module(a), Type::Module(b)) => self.module(a, at, b, bt),
143+
144+
(Type::Func(_), _)
145+
| (Type::Resource(_), _)
146+
| (Type::Value(_), _)
147+
| (Type::Interface(_), _)
148+
| (Type::World(_), _)
149+
| (Type::Module(_), _) => {
150+
let (expected, expected_types, found, found_types) =
151+
self.expected_found(&a, at, &b, bt);
152+
153+
bail!(
154+
"expected {expected}, found {found}",
155+
expected = expected.desc(expected_types),
156+
found = found.desc(found_types)
157+
)
158+
}
159+
}
147160
}
148161

149162
fn func(&self, a: FuncTypeId, at: &Types, b: FuncTypeId, bt: &Types) -> Result<()> {
@@ -392,7 +405,7 @@ impl<'a> SubtypeChecker<'a> {
392405
}
393406

394407
match (a, b) {
395-
(CoreExtern::Func(a), CoreExtern::Func(b)) => return self.core_func(a, at, b, bt),
408+
(CoreExtern::Func(a), CoreExtern::Func(b)) => self.core_func(a, at, b, bt),
396409
(
397410
CoreExtern::Table {
398411
element_type: ae,
@@ -418,7 +431,7 @@ impl<'a> SubtypeChecker<'a> {
418431
bail!("mismatched table limits");
419432
}
420433

421-
return Ok(());
434+
Ok(())
422435
}
423436
(
424437
CoreExtern::Memory {
@@ -448,7 +461,7 @@ impl<'a> SubtypeChecker<'a> {
448461
bail!("mismatched memory limits");
449462
}
450463

451-
return Ok(());
464+
Ok(())
452465
}
453466
(
454467
CoreExtern::Global {
@@ -471,14 +484,19 @@ impl<'a> SubtypeChecker<'a> {
471484
bail!("expected global type {expected}, found {found}");
472485
}
473486

474-
return Ok(());
487+
Ok(())
488+
}
489+
(CoreExtern::Tag(a), CoreExtern::Tag(b)) => self.core_func(a, at, b, bt),
490+
491+
(CoreExtern::Func(_), _)
492+
| (CoreExtern::Table { .. }, _)
493+
| (CoreExtern::Memory { .. }, _)
494+
| (CoreExtern::Global { .. }, _)
495+
| (CoreExtern::Tag(_), _) => {
496+
let (expected, _, found, _) = self.expected_found(a, at, b, bt);
497+
bail!("expected {expected}, found {found}");
475498
}
476-
(CoreExtern::Tag(a), CoreExtern::Tag(b)) => return self.core_func(a, at, b, bt),
477-
_ => {}
478499
}
479-
480-
let (expected, _, found, _) = self.expected_found(a, at, b, bt);
481-
bail!("expected {expected}, found {found}");
482500
}
483501

484502
fn core_func(&self, a: &CoreFuncType, at: &Types, b: &CoreFuncType, bt: &Types) -> Result<()> {
@@ -499,7 +517,11 @@ impl<'a> SubtypeChecker<'a> {
499517
(ValueType::Defined(a), ValueType::Defined(b)) => self.defined_type(a, at, b, bt),
500518
(ValueType::Borrow(a), ValueType::Borrow(b))
501519
| (ValueType::Own(a), ValueType::Own(b)) => self.resource(a, at, b, bt),
502-
_ => {
520+
521+
(ValueType::Primitive(_), _)
522+
| (ValueType::Defined(_), _)
523+
| (ValueType::Borrow(_), _)
524+
| (ValueType::Own(_), _) => {
503525
let (expected, expected_types, found, found_types) =
504526
self.expected_found(&a, at, &b, bt);
505527
bail!(
@@ -529,6 +551,12 @@ impl<'a> SubtypeChecker<'a> {
529551
(DefinedType::List(a), DefinedType::List(b)) => self
530552
.value_type(*a, at, *b, bt)
531553
.context("mismatched type for list element"),
554+
(DefinedType::Future(a), DefinedType::Future(b)) => self
555+
.payload(*a, at, *b, bt)
556+
.context("mismatched type for future payload"),
557+
(DefinedType::Stream(a), DefinedType::Stream(b)) => self
558+
.payload(*a, at, *b, bt)
559+
.context("mismatched type for stream payload"),
532560
(DefinedType::Option(a), DefinedType::Option(b)) => self
533561
.value_type(*a, at, *b, bt)
534562
.context("mismatched type for option"),
@@ -552,7 +580,17 @@ impl<'a> SubtypeChecker<'a> {
552580
(DefinedType::Alias(_), _) | (_, DefinedType::Alias(_)) => {
553581
panic!("aliases should have been resolved")
554582
}
555-
_ => {
583+
584+
(DefinedType::Tuple(_), _)
585+
| (DefinedType::List(_), _)
586+
| (DefinedType::Option(_), _)
587+
| (DefinedType::Result { .. }, _)
588+
| (DefinedType::Variant(_), _)
589+
| (DefinedType::Record(_), _)
590+
| (DefinedType::Flags(_), _)
591+
| (DefinedType::Enum(_), _)
592+
| (DefinedType::Stream(_), _)
593+
| (DefinedType::Future(_), _) => {
556594
let (expected, expected_types, found, found_types) =
557595
self.expected_found(a, at, b, bt);
558596
bail!(
@@ -718,6 +756,21 @@ impl<'a> SubtypeChecker<'a> {
718756
Ok(())
719757
}
720758

759+
fn payload(
760+
&self,
761+
a: Option<ValueType>,
762+
at: &Types,
763+
b: Option<ValueType>,
764+
bt: &Types,
765+
) -> Result<()> {
766+
match (a, b) {
767+
(Some(a), Some(b)) => self.value_type(a, at, b, bt),
768+
(None, None) => Ok(()),
769+
(Some(_), None) => bail!("expected a type payload, found none"),
770+
(None, Some(_)) => bail!("expected no type payload, found one"),
771+
}
772+
}
773+
721774
fn primitive(&self, a: PrimitiveType, at: &Types, b: PrimitiveType, bt: &Types) -> Result<()> {
722775
// Note: currently subtyping for primitive types is done in terms of equality
723776
// rather than actual subtyping; the reason for this is that implementing

0 commit comments

Comments
 (0)