1use crate::runtime::vm::TableElement;
2use crate::store::{AutoAssertNoGc, StoreOpaque};
3use crate::{
4 prelude::*, AnyRef, ArrayRef, AsContext, AsContextMut, ExternRef, Func, HeapType, RefType,
5 Rooted, RootedGcRefImpl, StructRef, ValType, V128,
6};
7use core::ptr;
8
9pub use crate::runtime::vm::ValRaw;
10
11#[derive(Debug, Clone, Copy)]
17pub enum Val {
18 I32(i32),
23
24 I64(i64),
26
27 F32(u32),
32
33 F64(u64),
38
39 V128(V128),
41
42 FuncRef(Option<Func>),
44
45 ExternRef(Option<Rooted<ExternRef>>),
47
48 AnyRef(Option<Rooted<AnyRef>>),
50}
51
52macro_rules! accessors {
53 ($bind:ident $(($variant:ident($ty:ty) $get:ident $unwrap:ident $cvt:expr))*) => ($(
54 #[inline]
57 pub fn $get(&self) -> Option<$ty> {
58 if let Val::$variant($bind) = self {
59 Some($cvt)
60 } else {
61 None
62 }
63 }
64
65 #[inline]
72 pub fn $unwrap(&self) -> $ty {
73 self.$get().expect(concat!("expected ", stringify!($ty)))
74 }
75 )*)
76}
77
78impl Val {
79 #[inline]
81 pub fn null_ref(heap_type: &HeapType) -> Val {
82 Ref::null(&heap_type).into()
83 }
84
85 #[inline]
90 pub const fn null_func_ref() -> Val {
91 Val::FuncRef(None)
92 }
93
94 #[inline]
99 pub const fn null_extern_ref() -> Val {
100 Val::ExternRef(None)
101 }
102
103 #[inline]
108 pub const fn null_any_ref() -> Val {
109 Val::AnyRef(None)
110 }
111
112 #[inline]
123 pub fn ty(&self, store: impl AsContext) -> Result<ValType> {
124 self.load_ty(&store.as_context().0)
125 }
126
127 #[inline]
128 pub(crate) fn load_ty(&self, store: &StoreOpaque) -> Result<ValType> {
129 Ok(match self {
130 Val::I32(_) => ValType::I32,
131 Val::I64(_) => ValType::I64,
132 Val::F32(_) => ValType::F32,
133 Val::F64(_) => ValType::F64,
134 Val::V128(_) => ValType::V128,
135 Val::ExternRef(Some(_)) => ValType::EXTERNREF,
136 Val::ExternRef(None) => ValType::NULLFUNCREF,
137 Val::FuncRef(None) => ValType::NULLFUNCREF,
138 Val::FuncRef(Some(f)) => ValType::Ref(RefType::new(
139 false,
140 HeapType::ConcreteFunc(f.load_ty(store)),
141 )),
142 Val::AnyRef(None) => ValType::NULLREF,
143 Val::AnyRef(Some(a)) => ValType::Ref(RefType::new(false, a._ty(store)?)),
144 })
145 }
146
147 pub fn matches_ty(&self, store: impl AsContext, ty: &ValType) -> Result<bool> {
155 self._matches_ty(&store.as_context().0, ty)
156 }
157
158 pub(crate) fn _matches_ty(&self, store: &StoreOpaque, ty: &ValType) -> Result<bool> {
159 assert!(self.comes_from_same_store(store));
160 assert!(ty.comes_from_same_engine(store.engine()));
161 Ok(match (self, ty) {
162 (Val::I32(_), ValType::I32)
163 | (Val::I64(_), ValType::I64)
164 | (Val::F32(_), ValType::F32)
165 | (Val::F64(_), ValType::F64)
166 | (Val::V128(_), ValType::V128) => true,
167
168 (Val::FuncRef(f), ValType::Ref(ref_ty)) => Ref::from(*f)._matches_ty(store, ref_ty)?,
169 (Val::ExternRef(e), ValType::Ref(ref_ty)) => {
170 Ref::from(*e)._matches_ty(store, ref_ty)?
171 }
172 (Val::AnyRef(a), ValType::Ref(ref_ty)) => Ref::from(*a)._matches_ty(store, ref_ty)?,
173
174 (Val::I32(_), _)
175 | (Val::I64(_), _)
176 | (Val::F32(_), _)
177 | (Val::F64(_), _)
178 | (Val::V128(_), _)
179 | (Val::FuncRef(_), _)
180 | (Val::ExternRef(_), _)
181 | (Val::AnyRef(_), _) => false,
182 })
183 }
184
185 pub(crate) fn ensure_matches_ty(&self, store: &StoreOpaque, ty: &ValType) -> Result<()> {
186 if !self.comes_from_same_store(store) {
187 bail!("value used with wrong store")
188 }
189 if !ty.comes_from_same_engine(store.engine()) {
190 bail!("type used with wrong engine")
191 }
192 if self._matches_ty(store, ty)? {
193 Ok(())
194 } else {
195 let actual_ty = self.load_ty(store)?;
196 bail!("type mismatch: expected {ty}, found {actual_ty}")
197 }
198 }
199
200 pub unsafe fn to_raw(&self, store: impl AsContextMut) -> Result<ValRaw> {
210 match self {
211 Val::I32(i) => Ok(ValRaw::i32(*i)),
212 Val::I64(i) => Ok(ValRaw::i64(*i)),
213 Val::F32(u) => Ok(ValRaw::f32(*u)),
214 Val::F64(u) => Ok(ValRaw::f64(*u)),
215 Val::V128(b) => Ok(ValRaw::v128(b.as_u128())),
216 Val::ExternRef(e) => Ok(ValRaw::externref(match e {
217 None => 0,
218 Some(e) => e.to_raw(store)?,
219 })),
220 Val::AnyRef(e) => Ok(ValRaw::anyref(match e {
221 None => 0,
222 Some(e) => e.to_raw(store)?,
223 })),
224 Val::FuncRef(f) => Ok(ValRaw::funcref(match f {
225 Some(f) => f.to_raw(store),
226 None => ptr::null_mut(),
227 })),
228 }
229 }
230
231 pub unsafe fn from_raw(store: impl AsContextMut, raw: ValRaw, ty: ValType) -> Val {
239 match ty {
240 ValType::I32 => Val::I32(raw.get_i32()),
241 ValType::I64 => Val::I64(raw.get_i64()),
242 ValType::F32 => Val::F32(raw.get_f32()),
243 ValType::F64 => Val::F64(raw.get_f64()),
244 ValType::V128 => Val::V128(raw.get_v128().into()),
245 ValType::Ref(ref_ty) => {
246 let ref_ = match ref_ty.heap_type() {
247 HeapType::Func | HeapType::ConcreteFunc(_) => {
248 Func::from_raw(store, raw.get_funcref()).into()
249 }
250
251 HeapType::NoFunc => Ref::Func(None),
252
253 HeapType::Extern => ExternRef::from_raw(store, raw.get_externref()).into(),
254
255 HeapType::NoExtern => Ref::Extern(None),
256
257 HeapType::Any
258 | HeapType::Eq
259 | HeapType::I31
260 | HeapType::Array
261 | HeapType::ConcreteArray(_)
262 | HeapType::Struct
263 | HeapType::ConcreteStruct(_) => {
264 AnyRef::from_raw(store, raw.get_anyref()).into()
265 }
266
267 HeapType::None => Ref::Any(None),
268 };
269 assert!(
270 ref_ty.is_nullable() || !ref_.is_null(),
271 "if the type is not nullable, we shouldn't get null; got \
272 type = {ref_ty}, ref = {ref_:?}"
273 );
274 ref_.into()
275 }
276 }
277 }
278
279 accessors! {
280 e
281 (I32(i32) i32 unwrap_i32 *e)
282 (I64(i64) i64 unwrap_i64 *e)
283 (F32(f32) f32 unwrap_f32 f32::from_bits(*e))
284 (F64(f64) f64 unwrap_f64 f64::from_bits(*e))
285 (FuncRef(Option<&Func>) func_ref unwrap_func_ref e.as_ref())
286 (ExternRef(Option<&Rooted<ExternRef>>) extern_ref unwrap_extern_ref e.as_ref())
287 (AnyRef(Option<&Rooted<AnyRef>>) any_ref unwrap_any_ref e.as_ref())
288 (V128(V128) v128 unwrap_v128 *e)
289 }
290
291 #[inline]
293 pub fn ref_(self) -> Option<Ref> {
294 match self {
295 Val::FuncRef(f) => Some(Ref::Func(f)),
296 Val::ExternRef(e) => Some(Ref::Extern(e)),
297 Val::AnyRef(a) => Some(Ref::Any(a)),
298 Val::I32(_) | Val::I64(_) | Val::F32(_) | Val::F64(_) | Val::V128(_) => None,
299 }
300 }
301
302 #[inline]
310 pub fn externref(&self) -> Option<Option<&Rooted<ExternRef>>> {
311 match self {
312 Val::ExternRef(None) => Some(None),
313 Val::ExternRef(Some(e)) => Some(Some(e)),
314 _ => None,
315 }
316 }
317
318 #[inline]
329 pub fn unwrap_externref(&self) -> Option<&Rooted<ExternRef>> {
330 self.externref().expect("expected externref")
331 }
332
333 #[inline]
341 pub fn anyref(&self) -> Option<Option<&Rooted<AnyRef>>> {
342 match self {
343 Val::AnyRef(None) => Some(None),
344 Val::AnyRef(Some(e)) => Some(Some(e)),
345 _ => None,
346 }
347 }
348
349 #[inline]
360 pub fn unwrap_anyref(&self) -> Option<&Rooted<AnyRef>> {
361 self.anyref().expect("expected anyref")
362 }
363
364 #[inline]
372 pub fn funcref(&self) -> Option<Option<&Func>> {
373 match self {
374 Val::FuncRef(None) => Some(None),
375 Val::FuncRef(Some(f)) => Some(Some(f)),
376 _ => None,
377 }
378 }
379
380 #[inline]
391 pub fn unwrap_funcref(&self) -> Option<&Func> {
392 self.funcref().expect("expected funcref")
393 }
394
395 #[inline]
396 pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
397 match self {
398 Val::FuncRef(Some(f)) => f.comes_from_same_store(store),
399 Val::FuncRef(None) => true,
400
401 Val::ExternRef(Some(x)) => x.comes_from_same_store(store),
402 Val::ExternRef(None) => true,
403
404 Val::AnyRef(Some(a)) => a.comes_from_same_store(store),
405 Val::AnyRef(None) => true,
406
407 Val::I32(_) | Val::I64(_) | Val::F32(_) | Val::F64(_) | Val::V128(_) => true,
411 }
412 }
413}
414
415impl From<i32> for Val {
416 #[inline]
417 fn from(val: i32) -> Val {
418 Val::I32(val)
419 }
420}
421
422impl From<i64> for Val {
423 #[inline]
424 fn from(val: i64) -> Val {
425 Val::I64(val)
426 }
427}
428
429impl From<f32> for Val {
430 #[inline]
431 fn from(val: f32) -> Val {
432 Val::F32(val.to_bits())
433 }
434}
435
436impl From<f64> for Val {
437 #[inline]
438 fn from(val: f64) -> Val {
439 Val::F64(val.to_bits())
440 }
441}
442
443impl From<Ref> for Val {
444 #[inline]
445 fn from(val: Ref) -> Val {
446 match val {
447 Ref::Extern(e) => Val::ExternRef(e),
448 Ref::Func(f) => Val::FuncRef(f),
449 Ref::Any(a) => Val::AnyRef(a),
450 }
451 }
452}
453
454impl From<Rooted<ExternRef>> for Val {
455 #[inline]
456 fn from(val: Rooted<ExternRef>) -> Val {
457 Val::ExternRef(Some(val))
458 }
459}
460
461impl From<Option<Rooted<ExternRef>>> for Val {
462 #[inline]
463 fn from(val: Option<Rooted<ExternRef>>) -> Val {
464 Val::ExternRef(val)
465 }
466}
467
468impl From<Rooted<AnyRef>> for Val {
469 #[inline]
470 fn from(val: Rooted<AnyRef>) -> Val {
471 Val::AnyRef(Some(val))
472 }
473}
474
475impl From<Option<Rooted<AnyRef>>> for Val {
476 #[inline]
477 fn from(val: Option<Rooted<AnyRef>>) -> Val {
478 Val::AnyRef(val)
479 }
480}
481
482impl From<Rooted<StructRef>> for Val {
483 #[inline]
484 fn from(val: Rooted<StructRef>) -> Val {
485 Val::AnyRef(Some(val.into()))
486 }
487}
488
489impl From<Option<Rooted<StructRef>>> for Val {
490 #[inline]
491 fn from(val: Option<Rooted<StructRef>>) -> Val {
492 Val::AnyRef(val.map(Into::into))
493 }
494}
495
496impl From<Rooted<ArrayRef>> for Val {
497 #[inline]
498 fn from(val: Rooted<ArrayRef>) -> Val {
499 Val::AnyRef(Some(val.into()))
500 }
501}
502
503impl From<Option<Rooted<ArrayRef>>> for Val {
504 #[inline]
505 fn from(val: Option<Rooted<ArrayRef>>) -> Val {
506 Val::AnyRef(val.map(Into::into))
507 }
508}
509
510impl From<Func> for Val {
511 #[inline]
512 fn from(val: Func) -> Val {
513 Val::FuncRef(Some(val))
514 }
515}
516
517impl From<Option<Func>> for Val {
518 #[inline]
519 fn from(val: Option<Func>) -> Val {
520 Val::FuncRef(val)
521 }
522}
523
524impl From<u128> for Val {
525 #[inline]
526 fn from(val: u128) -> Val {
527 Val::V128(val.into())
528 }
529}
530
531impl From<V128> for Val {
532 #[inline]
533 fn from(val: V128) -> Val {
534 Val::V128(val)
535 }
536}
537
538#[derive(Debug, Clone)]
563pub enum Ref {
564 Func(Option<Func>),
601
602 Extern(Option<Rooted<ExternRef>>),
612
613 Any(Option<Rooted<AnyRef>>),
622}
623
624impl From<Func> for Ref {
625 #[inline]
626 fn from(f: Func) -> Ref {
627 Ref::Func(Some(f))
628 }
629}
630
631impl From<Option<Func>> for Ref {
632 #[inline]
633 fn from(f: Option<Func>) -> Ref {
634 Ref::Func(f)
635 }
636}
637
638impl From<Rooted<ExternRef>> for Ref {
639 #[inline]
640 fn from(e: Rooted<ExternRef>) -> Ref {
641 Ref::Extern(Some(e))
642 }
643}
644
645impl From<Option<Rooted<ExternRef>>> for Ref {
646 #[inline]
647 fn from(e: Option<Rooted<ExternRef>>) -> Ref {
648 Ref::Extern(e)
649 }
650}
651
652impl From<Rooted<AnyRef>> for Ref {
653 #[inline]
654 fn from(e: Rooted<AnyRef>) -> Ref {
655 Ref::Any(Some(e))
656 }
657}
658
659impl From<Option<Rooted<AnyRef>>> for Ref {
660 #[inline]
661 fn from(e: Option<Rooted<AnyRef>>) -> Ref {
662 Ref::Any(e)
663 }
664}
665
666impl From<Rooted<StructRef>> for Ref {
667 #[inline]
668 fn from(e: Rooted<StructRef>) -> Ref {
669 Ref::Any(Some(e.into()))
670 }
671}
672
673impl From<Option<Rooted<StructRef>>> for Ref {
674 #[inline]
675 fn from(e: Option<Rooted<StructRef>>) -> Ref {
676 Ref::Any(e.map(Into::into))
677 }
678}
679
680impl From<Rooted<ArrayRef>> for Ref {
681 #[inline]
682 fn from(e: Rooted<ArrayRef>) -> Ref {
683 Ref::Any(Some(e.into()))
684 }
685}
686
687impl From<Option<Rooted<ArrayRef>>> for Ref {
688 #[inline]
689 fn from(e: Option<Rooted<ArrayRef>>) -> Ref {
690 Ref::Any(e.map(Into::into))
691 }
692}
693
694impl Ref {
695 #[inline]
697 pub fn null(heap_type: &HeapType) -> Self {
698 match heap_type.top() {
699 HeapType::Any => Ref::Any(None),
700 HeapType::Extern => Ref::Extern(None),
701 HeapType::Func => Ref::Func(None),
702 ty => unreachable!("not a heap type: {ty:?}"),
703 }
704 }
705
706 #[inline]
708 pub fn is_null(&self) -> bool {
709 match self {
710 Ref::Any(None) | Ref::Extern(None) | Ref::Func(None) => true,
711 Ref::Any(Some(_)) | Ref::Extern(Some(_)) | Ref::Func(Some(_)) => false,
712 }
713 }
714
715 #[inline]
717 pub fn is_non_null(&self) -> bool {
718 !self.is_null()
719 }
720
721 #[inline]
723 pub fn is_extern(&self) -> bool {
724 matches!(self, Ref::Extern(_))
725 }
726
727 #[inline]
736 pub fn as_extern(&self) -> Option<Option<&Rooted<ExternRef>>> {
737 match self {
738 Ref::Extern(e) => Some(e.as_ref()),
739 _ => None,
740 }
741 }
742
743 #[inline]
750 pub fn unwrap_extern(&self) -> Option<&Rooted<ExternRef>> {
751 self.as_extern()
752 .expect("Ref::unwrap_extern on non-extern reference")
753 }
754
755 #[inline]
757 pub fn is_any(&self) -> bool {
758 matches!(self, Ref::Any(_))
759 }
760
761 #[inline]
770 pub fn as_any(&self) -> Option<Option<&Rooted<AnyRef>>> {
771 match self {
772 Ref::Any(e) => Some(e.as_ref()),
773 _ => None,
774 }
775 }
776
777 #[inline]
784 pub fn unwrap_any(&self) -> Option<&Rooted<AnyRef>> {
785 self.as_any().expect("Ref::unwrap_any on non-any reference")
786 }
787
788 #[inline]
790 pub fn is_func(&self) -> bool {
791 matches!(self, Ref::Func(_))
792 }
793
794 #[inline]
803 pub fn as_func(&self) -> Option<Option<&Func>> {
804 match self {
805 Ref::Func(f) => Some(f.as_ref()),
806 _ => None,
807 }
808 }
809
810 #[inline]
817 pub fn unwrap_func(&self) -> Option<&Func> {
818 self.as_func()
819 .expect("Ref::unwrap_func on non-func reference")
820 }
821
822 pub fn ty(&self, store: impl AsContext) -> Result<RefType> {
832 self.load_ty(&store.as_context().0)
833 }
834
835 pub(crate) fn load_ty(&self, store: &StoreOpaque) -> Result<RefType> {
836 assert!(self.comes_from_same_store(store));
837 Ok(RefType::new(
838 self.is_null(),
839 match self {
843 Ref::Extern(None) => HeapType::NoExtern,
844 Ref::Extern(Some(_)) => HeapType::Extern,
845
846 Ref::Func(None) => HeapType::NoFunc,
847 Ref::Func(Some(f)) => HeapType::ConcreteFunc(f.load_ty(store)),
848
849 Ref::Any(None) => HeapType::None,
850 Ref::Any(Some(a)) => a._ty(store)?,
851 },
852 ))
853 }
854
855 pub fn matches_ty(&self, store: impl AsContext, ty: &RefType) -> Result<bool> {
863 self._matches_ty(&store.as_context().0, ty)
864 }
865
866 pub(crate) fn _matches_ty(&self, store: &StoreOpaque, ty: &RefType) -> Result<bool> {
867 assert!(self.comes_from_same_store(store));
868 assert!(ty.comes_from_same_engine(store.engine()));
869 if self.is_null() && !ty.is_nullable() {
870 return Ok(false);
871 }
872 Ok(match (self, ty.heap_type()) {
873 (Ref::Extern(_), HeapType::Extern) => true,
874 (Ref::Extern(_), _) => false,
875
876 (Ref::Func(_), HeapType::Func) => true,
877 (Ref::Func(None), HeapType::NoFunc | HeapType::ConcreteFunc(_)) => true,
878 (Ref::Func(Some(f)), HeapType::ConcreteFunc(func_ty)) => f._matches_ty(store, func_ty),
879 (Ref::Func(_), _) => false,
880
881 (Ref::Any(_), HeapType::Any) => true,
882 (Ref::Any(Some(a)), HeapType::I31) => a._is_i31(store)?,
883 (Ref::Any(Some(a)), HeapType::Struct) => a._is_struct(store)?,
884 (Ref::Any(Some(a)), HeapType::ConcreteStruct(_ty)) => match a._as_struct(store)? {
885 None => false,
886 #[cfg_attr(not(feature = "gc"), allow(unreachable_patterns))]
887 Some(s) => s._matches_ty(store, _ty)?,
888 },
889 (Ref::Any(Some(_)), HeapType::Eq) => todo!("eqref"),
890 (Ref::Any(Some(a)), HeapType::Array) => a._is_array(store)?,
891 (Ref::Any(Some(a)), HeapType::ConcreteArray(_ty)) => match a._as_array(store)? {
892 None => false,
893 #[cfg_attr(not(feature = "gc"), allow(unreachable_patterns))]
894 Some(a) => a._matches_ty(store, _ty)?,
895 },
896 (
897 Ref::Any(None),
898 HeapType::None
899 | HeapType::I31
900 | HeapType::ConcreteStruct(_)
901 | HeapType::Struct
902 | HeapType::ConcreteArray(_)
903 | HeapType::Array,
904 ) => true,
905 (Ref::Any(_), _) => false,
906 })
907 }
908
909 pub(crate) fn ensure_matches_ty(&self, store: &StoreOpaque, ty: &RefType) -> Result<()> {
910 if !self.comes_from_same_store(store) {
911 bail!("reference used with wrong store")
912 }
913 if !ty.comes_from_same_engine(store.engine()) {
914 bail!("type used with wrong engine")
915 }
916 if self._matches_ty(store, ty)? {
917 Ok(())
918 } else {
919 let actual_ty = self.load_ty(store)?;
920 bail!("type mismatch: expected {ty}, found {actual_ty}")
921 }
922 }
923
924 pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
925 match self {
926 Ref::Func(Some(f)) => f.comes_from_same_store(store),
927 Ref::Func(None) => true,
928 Ref::Extern(Some(x)) => x.comes_from_same_store(store),
929 Ref::Extern(None) => true,
930 Ref::Any(Some(a)) => a.comes_from_same_store(store),
931 Ref::Any(None) => true,
932 }
933 }
934
935 pub(crate) fn into_table_element(
936 self,
937 store: &mut StoreOpaque,
938 ty: &RefType,
939 ) -> Result<TableElement> {
940 let mut store = AutoAssertNoGc::new(store);
941 self.ensure_matches_ty(&store, &ty)
942 .context("type mismatch: value does not match table element type")?;
943
944 match (self, ty.heap_type().top()) {
945 (Ref::Func(None), HeapType::Func) => {
946 assert!(ty.is_nullable());
947 Ok(TableElement::FuncRef(ptr::null_mut()))
948 }
949 (Ref::Func(Some(f)), HeapType::Func) => {
950 debug_assert!(
951 f.comes_from_same_store(&store),
952 "checked in `ensure_matches_ty`"
953 );
954 Ok(TableElement::FuncRef(f.vm_func_ref(&mut store).as_ptr()))
955 }
956
957 (Ref::Extern(e), HeapType::Extern) => match e {
958 None => {
959 assert!(ty.is_nullable());
960 Ok(TableElement::GcRef(None))
961 }
962 #[cfg_attr(not(feature = "gc"), allow(unreachable_patterns))]
963 Some(e) => {
964 let gc_ref = e.try_clone_gc_ref(&mut store)?;
965 Ok(TableElement::GcRef(Some(gc_ref)))
966 }
967 },
968
969 (Ref::Any(a), HeapType::Any) => match a {
970 None => {
971 assert!(ty.is_nullable());
972 Ok(TableElement::GcRef(None))
973 }
974 #[cfg_attr(not(feature = "gc"), allow(unreachable_patterns))]
975 Some(a) => {
976 let gc_ref = a.try_clone_gc_ref(&mut store)?;
977 Ok(TableElement::GcRef(Some(gc_ref)))
978 }
979 },
980
981 _ => unreachable!("checked that the value matches the type above"),
982 }
983 }
984}
985
986#[cfg(test)]
987mod tests {
988 use crate::*;
989
990 #[test]
991 fn size_of_val() {
992 assert_eq!(
995 std::mem::size_of::<Val>(),
996 if cfg!(any(
997 target_arch = "x86_64",
998 target_arch = "aarch64",
999 target_arch = "riscv64",
1000 target_arch = "s390x"
1001 )) {
1002 24
1003 } else {
1004 panic!("unsupported architecture")
1005 }
1006 );
1007 }
1008
1009 #[test]
1010 fn size_of_ref() {
1011 assert_eq!(std::mem::size_of::<Ref>(), 24);
1014 }
1015
1016 #[test]
1017 #[should_panic]
1018 fn val_matches_ty_wrong_engine() {
1019 let e1 = Engine::default();
1020 let e2 = Engine::default();
1021
1022 let t1 = FuncType::new(&e1, None, None);
1023 let t2 = FuncType::new(&e2, None, None);
1024
1025 let mut s1 = Store::new(&e1, ());
1026 let f = Func::new(&mut s1, t1.clone(), |_caller, _args, _results| Ok(()));
1027
1028 let _ = Val::FuncRef(Some(f)).matches_ty(
1030 &s1,
1031 &ValType::Ref(RefType::new(true, HeapType::ConcreteFunc(t2))),
1032 );
1033 }
1034
1035 #[test]
1036 #[should_panic]
1037 fn ref_matches_ty_wrong_engine() {
1038 let e1 = Engine::default();
1039 let e2 = Engine::default();
1040
1041 let t1 = FuncType::new(&e1, None, None);
1042 let t2 = FuncType::new(&e2, None, None);
1043
1044 let mut s1 = Store::new(&e1, ());
1045 let f = Func::new(&mut s1, t1.clone(), |_caller, _args, _results| Ok(()));
1046
1047 let _ = Ref::Func(Some(f)).matches_ty(&s1, &RefType::new(true, HeapType::ConcreteFunc(t2)));
1049 }
1050}