From 672dc3e2a5a4e27ee86e1bc5970fb8fe53b18ad2 Mon Sep 17 00:00:00 2001 From: Julian Adamse Date: Mon, 22 Dec 2025 23:41:33 +0100 Subject: [PATCH 1/3] Add additional `matches` Add matches to: - `GlobalType` - `TableType` - `MemoryType` - `TagType` --- crates/wasmtime/src/runtime/types.rs | 94 ++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/crates/wasmtime/src/runtime/types.rs b/crates/wasmtime/src/runtime/types.rs index 4a67e6668f7b..127a8abacf97 100644 --- a/crates/wasmtime/src/runtime/types.rs +++ b/crates/wasmtime/src/runtime/types.rs @@ -3007,6 +3007,40 @@ impl GlobalType { pub(crate) fn into_registered_type(self) -> Option { self.content.into_registered_type() } + + /// Does this global type match the other? + /// + /// That is, is this global type a subtype of the other? + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn matches(&self, other: &GlobalType) -> bool { + match (self, other) { + ( + GlobalType { + content: a, + mutability: Mutability::Const, + }, + GlobalType { + content: b, + mutability: Mutability::Const, + }, + ) => a.matches(b), + ( + GlobalType { + content: a, + mutability: Mutability::Var, + }, + GlobalType { + content: b, + mutability: Mutability::Var, + }, + ) => a.matches(b) && b.matches(a), + _ => false, + } + } } // Tag Types @@ -3047,6 +3081,18 @@ impl TagType { pub fn default_value(&self, store: impl AsContextMut) -> Result { RuntimeTag::new(store, self) } + + /// Does this tag type match the other? + /// + /// That is, is this tag type a subtype of the other? + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn matches(&self, other: &TagType) -> bool { + self.ty.matches(&other.ty) && other.ty.matches(&self.ty) + } } // Table Types @@ -3162,6 +3208,39 @@ impl TableType { .unwrap(); RuntimeTable::new(store, self.clone(), init_val) } + + /// Does this table type match the other? + /// + /// That is, is this table type a subtype of the other? + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn matches(&self, other: &TableType) -> bool { + return limit_matches( + (self.minimum(), self.maximum()), + (other.minimum(), other.maximum()), + ) && self.element.matches(other.element()) + && other.element().matches(self.element()); + } +} + +/// Does this limit match the other? +/// +/// That is, is this limit contained in the other? +fn limit_matches(this: (u64, Option), other: (u64, Option)) -> bool { + if this.0 < other.0 { + false + } else if let Some(b) = other.1 { + if let Some(a) = this.1 { + if a > b { false } else { true } + } else { + false + } + } else { + true + } } // Memory Types @@ -3514,6 +3593,21 @@ impl MemoryType { Extern::Memory(crate::Memory::new(store, self.clone())?) }) } + + /// Does this memory type match the other? + /// + /// That is, is this memory type a subtype of the other? + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn matches(&self, other: &MemoryType) -> bool { + return limit_matches( + (self.minimum(), self.maximum()), + (other.minimum(), other.maximum()), + ); + } } // Import Types From 8a25e4e7fa3493c0e989870289092d983d0de5c4 Mon Sep 17 00:00:00 2001 From: Julian Adamse Date: Mon, 22 Dec 2025 23:56:02 +0100 Subject: [PATCH 2/3] Add additional `eq` functions Add `eq` functions to: - `GlobalType` - `TableType` - `MemoryType` - `TagType` --- crates/wasmtime/src/runtime/types.rs | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/crates/wasmtime/src/runtime/types.rs b/crates/wasmtime/src/runtime/types.rs index 127a8abacf97..de92d7fab6bc 100644 --- a/crates/wasmtime/src/runtime/types.rs +++ b/crates/wasmtime/src/runtime/types.rs @@ -3041,6 +3041,19 @@ impl GlobalType { _ => false, } } + + /// Is global type `a` precisely equal to global type `b`? + /// + /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they + /// are not exactly the same global type. + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn eq(a: &GlobalType, b: &GlobalType) -> bool { + ValType::eq(&a.content, &b.content) && a.mutability == b.mutability + } } // Tag Types @@ -3093,6 +3106,19 @@ impl TagType { pub fn matches(&self, other: &TagType) -> bool { self.ty.matches(&other.ty) && other.ty.matches(&self.ty) } + + /// Is tag type `a` precisely equal to tag type `b`? + /// + /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they + /// are not exactly the same tag type. + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn eq(a: &TagType, b: &TagType) -> bool { + FuncType::eq(&a.ty, &b.ty) + } } // Table Types @@ -3224,6 +3250,21 @@ impl TableType { ) && self.element.matches(other.element()) && other.element().matches(self.element()); } + + /// Is table type `a` precisely equal to table type `b`? + /// + /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they + /// are not exactly the same table type. + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn eq(a: &TableType, b: &TableType) -> bool { + a.minimum() == b.minimum() + && a.maximum() == b.maximum() + && RefType::eq(&a.element, &b.element) + } } /// Does this limit match the other? @@ -3608,6 +3649,19 @@ impl MemoryType { (other.minimum(), other.maximum()), ); } + + /// Is memory type `a` precisely equal to memory type `b`? + /// + /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they + /// are not exactly the same memory type. + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn eq(a: &MemoryType, b: &MemoryType) -> bool { + a.maximum() == b.maximum() && a.minimum() == b.minimum() + } } // Import Types From 70fa7e669eccf2ed87a723a338de6f1cd8d4bbd8 Mon Sep 17 00:00:00 2001 From: Julian Adamse Date: Tue, 23 Dec 2025 00:06:02 +0100 Subject: [PATCH 3/3] Add `ExternType::matches` and `ExternType::eq` --- crates/wasmtime/src/runtime/types.rs | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/crates/wasmtime/src/runtime/types.rs b/crates/wasmtime/src/runtime/types.rs index de92d7fab6bc..6675ea228fb7 100644 --- a/crates/wasmtime/src/runtime/types.rs +++ b/crates/wasmtime/src/runtime/types.rs @@ -1529,6 +1529,53 @@ impl ExternType { ExternType::Tag(tag_ty) => tag_ty.default_value(store).map(Extern::Tag), } } + + /// Does this extern type match the other extern type? + /// + /// That is, is this extern type a subtype of the other? + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn matches(&self, other: &ExternType) -> bool { + match (self, other) { + (ExternType::Func(a), ExternType::Func(b)) => a.matches(b), + (ExternType::Func(_), _) => false, + (ExternType::Global(a), ExternType::Global(b)) => a.matches(b), + (ExternType::Global(_), _) => false, + (ExternType::Memory(a), ExternType::Memory(b)) => a.matches(b), + (ExternType::Memory(_), _) => false, + (ExternType::Tag(a), ExternType::Tag(b)) => a.matches(b), + (ExternType::Tag(_), _) => false, + (ExternType::Table(a), ExternType::Table(b)) => a.matches(b), + (ExternType::Table(_), _) => false, + } + } + + /// Is extern type `a` precisely equal to extern type `b`? + /// + /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they + /// are not exactly the same extern type. + /// + /// # Panics + /// + /// Panics if either type is associated with a different engine from the + /// other. + pub fn eq(a: &ExternType, b: &ExternType) -> bool { + match (a, b) { + (ExternType::Func(a), ExternType::Func(b)) => FuncType::eq(a, b), + (ExternType::Func(_), _) => false, + (ExternType::Global(a), ExternType::Global(b)) => GlobalType::eq(a, b), + (ExternType::Global(_), _) => false, + (ExternType::Memory(a), ExternType::Memory(b)) => MemoryType::eq(a, b), + (ExternType::Memory(_), _) => false, + (ExternType::Tag(a), ExternType::Tag(b)) => TagType::eq(a, b), + (ExternType::Tag(_), _) => false, + (ExternType::Table(a), ExternType::Table(b)) => TableType::eq(a, b), + (ExternType::Table(_), _) => false, + } + } } impl From for ExternType {