1 use crate::store::{AutoAssertNoGc, StoreOpaque};
2 use crate::{
3     AnyRef, ArrayRef, AsContext, AsContextMut, ExnRef, ExternRef, Func, HeapType, RefType, Rooted,
4     StructRef, V128, ValType, prelude::*,
5 };
6 use core::ptr;
7 use wasmtime_environ::WasmHeapTopType;
8 
9 pub use crate::runtime::vm::ValRaw;
10 
11 /// A stub implementation for continuation references.
12 ///
13 /// This is a placeholder until continuation objects are fully integrated
14 /// with the GC system (see #10248).
15 #[derive(Debug, Clone, Copy)]
16 pub struct ContRef;
17 
18 /// Possible runtime values that a WebAssembly module can either consume or
19 /// produce.
20 ///
21 /// Note that we inline the `enum Ref { ... }` variants into `enum Val { ... }`
22 /// here as a size optimization.
23 #[derive(Debug, Clone, Copy)]
24 pub enum Val {
25     // NB: the ordering here is intended to match the ordering in
26     // `ValType` to improve codegen when learning the type of a value.
27     //
28     /// A 32-bit integer.
29     I32(i32),
30 
31     /// A 64-bit integer.
32     I64(i64),
33 
34     /// A 32-bit float.
35     ///
36     /// Note that the raw bits of the float are stored here, and you can use
37     /// `f32::from_bits` to create an `f32` value.
38     F32(u32),
39 
40     /// A 64-bit float.
41     ///
42     /// Note that the raw bits of the float are stored here, and you can use
43     /// `f64::from_bits` to create an `f64` value.
44     F64(u64),
45 
46     /// A 128-bit number.
47     V128(V128),
48 
49     /// A function reference.
50     FuncRef(Option<Func>),
51 
52     /// An external reference.
53     ExternRef(Option<Rooted<ExternRef>>),
54 
55     /// An internal reference.
56     AnyRef(Option<Rooted<AnyRef>>),
57 
58     /// An exception reference.
59     ExnRef(Option<Rooted<ExnRef>>),
60 
61     /// A continuation reference.
62     ///
63     /// Note: This is currently a stub implementation as continuation objects
64     /// are not yet fully integrated with the GC system. See #10248.
65     ContRef(Option<ContRef>),
66 }
67 
68 macro_rules! accessors {
69     ($bind:ident $(($variant:ident($ty:ty) $get:ident $unwrap:ident $cvt:expr))*) => ($(
70         /// Attempt to access the underlying value of this `Val`, returning
71         /// `None` if it is not the correct type.
72         #[inline]
73         pub fn $get(&self) -> Option<$ty> {
74             if let Val::$variant($bind) = self {
75                 Some($cvt)
76             } else {
77                 None
78             }
79         }
80 
81         /// Returns the underlying value of this `Val`, panicking if it's the
82         /// wrong type.
83         ///
84         /// # Panics
85         ///
86         /// Panics if `self` is not of the right type.
87         #[inline]
88         pub fn $unwrap(&self) -> $ty {
89             self.$get().expect(concat!("expected ", stringify!($ty)))
90         }
91     )*)
92 }
93 
94 impl Val {
95     /// Returns the null reference for the given heap type.
96     #[inline]
null_ref(heap_type: &HeapType) -> Val97     pub fn null_ref(heap_type: &HeapType) -> Val {
98         Ref::null(&heap_type).into()
99     }
100 
101     /// Returns the null function reference value.
102     ///
103     /// The return value has type `(ref null nofunc)` aka `nullfuncref` and is a
104     /// subtype of all function references.
105     #[inline]
null_func_ref() -> Val106     pub const fn null_func_ref() -> Val {
107         Val::FuncRef(None)
108     }
109 
110     /// Returns the null function reference value.
111     ///
112     /// The return value has type `(ref null extern)` aka `nullexternref` and is
113     /// a subtype of all external references.
114     #[inline]
null_extern_ref() -> Val115     pub const fn null_extern_ref() -> Val {
116         Val::ExternRef(None)
117     }
118 
119     /// Returns the null function reference value.
120     ///
121     /// The return value has type `(ref null any)` aka `nullref` and is a
122     /// subtype of all internal references.
123     #[inline]
null_any_ref() -> Val124     pub const fn null_any_ref() -> Val {
125         Val::AnyRef(None)
126     }
127 
null_top(top: WasmHeapTopType) -> Val128     pub(crate) const fn null_top(top: WasmHeapTopType) -> Val {
129         match top {
130             WasmHeapTopType::Func => Val::FuncRef(None),
131             WasmHeapTopType::Extern => Val::ExternRef(None),
132             WasmHeapTopType::Any => Val::AnyRef(None),
133             WasmHeapTopType::Exn => Val::ExnRef(None),
134             WasmHeapTopType::Cont => Val::ContRef(None),
135         }
136     }
137 
138     /// Returns the default value for the given type, if any exists.
139     ///
140     /// Returns `None` if there is no default value for the given type (for
141     /// example, non-nullable reference types do not have a default value).
default_for_ty(ty: &ValType) -> Option<Val>142     pub fn default_for_ty(ty: &ValType) -> Option<Val> {
143         match ty {
144             ValType::I32 => Some(Val::I32(0)),
145             ValType::I64 => Some(Val::I64(0)),
146             ValType::F32 => Some(Val::F32(0)),
147             ValType::F64 => Some(Val::F64(0)),
148             ValType::V128 => Some(Val::V128(V128::from(0))),
149             ValType::Ref(ref_ty) => {
150                 if ref_ty.is_nullable() {
151                     Some(Val::null_ref(ref_ty.heap_type()))
152                 } else {
153                     None
154                 }
155             }
156         }
157     }
158 
159     /// Returns the corresponding [`ValType`] for this `Val`.
160     ///
161     /// # Errors
162     ///
163     /// Returns an error if this value is a GC reference that has since been
164     /// unrooted.
165     ///
166     /// # Panics
167     ///
168     /// Panics if this value is associated with a different store.
169     #[inline]
ty(&self, store: impl AsContext) -> Result<ValType>170     pub fn ty(&self, store: impl AsContext) -> Result<ValType> {
171         self.load_ty(&store.as_context().0)
172     }
173 
174     #[inline]
load_ty(&self, store: &StoreOpaque) -> Result<ValType>175     pub(crate) fn load_ty(&self, store: &StoreOpaque) -> Result<ValType> {
176         Ok(match self {
177             Val::I32(_) => ValType::I32,
178             Val::I64(_) => ValType::I64,
179             Val::F32(_) => ValType::F32,
180             Val::F64(_) => ValType::F64,
181             Val::V128(_) => ValType::V128,
182             Val::ExternRef(Some(_)) => ValType::EXTERNREF,
183             Val::ExternRef(None) => ValType::NULLFUNCREF,
184             Val::FuncRef(None) => ValType::NULLFUNCREF,
185             Val::FuncRef(Some(f)) => ValType::Ref(RefType::new(
186                 false,
187                 HeapType::ConcreteFunc(f.load_ty(store)),
188             )),
189             Val::AnyRef(None) => ValType::NULLREF,
190             Val::AnyRef(Some(a)) => ValType::Ref(RefType::new(false, a._ty(store)?)),
191             Val::ExnRef(None) => ValType::NULLEXNREF,
192             Val::ExnRef(Some(e)) => ValType::Ref(RefType::new(false, e._ty(store)?.into())),
193             Val::ContRef(_) => {
194                 // TODO(#10248): Return proper continuation reference type when available
195                 return Err(crate::format_err!(
196                     "continuation references not yet supported in embedder API"
197                 ));
198             }
199         })
200     }
201 
202     /// Does this value match the given type?
203     ///
204     /// Returns an error is an underlying `Rooted` has been unrooted.
205     ///
206     /// # Panics
207     ///
208     /// Panics if this value is not associated with the given store.
matches_ty(&self, store: impl AsContext, ty: &ValType) -> Result<bool>209     pub fn matches_ty(&self, store: impl AsContext, ty: &ValType) -> Result<bool> {
210         self._matches_ty(&store.as_context().0, ty)
211     }
212 
_matches_ty(&self, store: &StoreOpaque, ty: &ValType) -> Result<bool>213     pub(crate) fn _matches_ty(&self, store: &StoreOpaque, ty: &ValType) -> Result<bool> {
214         assert!(self.comes_from_same_store(store));
215         assert!(ty.comes_from_same_engine(store.engine()));
216         Ok(match (self, ty) {
217             (Val::I32(_), ValType::I32)
218             | (Val::I64(_), ValType::I64)
219             | (Val::F32(_), ValType::F32)
220             | (Val::F64(_), ValType::F64)
221             | (Val::V128(_), ValType::V128) => true,
222 
223             (Val::FuncRef(f), ValType::Ref(ref_ty)) => Ref::from(*f)._matches_ty(store, ref_ty)?,
224             (Val::ExternRef(e), ValType::Ref(ref_ty)) => {
225                 Ref::from(*e)._matches_ty(store, ref_ty)?
226             }
227             (Val::AnyRef(a), ValType::Ref(ref_ty)) => Ref::from(*a)._matches_ty(store, ref_ty)?,
228             (Val::ExnRef(e), ValType::Ref(ref_ty)) => Ref::from(*e)._matches_ty(store, ref_ty)?,
229 
230             (Val::I32(_), _)
231             | (Val::I64(_), _)
232             | (Val::F32(_), _)
233             | (Val::F64(_), _)
234             | (Val::V128(_), _)
235             | (Val::FuncRef(_), _)
236             | (Val::ExternRef(_), _)
237             | (Val::AnyRef(_), _)
238             | (Val::ExnRef(_), _)
239             | (Val::ContRef(_), _) => false,
240         })
241     }
242 
ensure_matches_ty(&self, store: &StoreOpaque, ty: &ValType) -> Result<()>243     pub(crate) fn ensure_matches_ty(&self, store: &StoreOpaque, ty: &ValType) -> Result<()> {
244         if !self.comes_from_same_store(store) {
245             bail!("value used with wrong store")
246         }
247         if !ty.comes_from_same_engine(store.engine()) {
248             bail!("type used with wrong engine")
249         }
250         if self._matches_ty(store, ty)? {
251             Ok(())
252         } else {
253             let actual_ty = self.load_ty(store)?;
254             bail!("type mismatch: expected {ty}, found {actual_ty}")
255         }
256     }
257 
258     /// Convenience method to convert this [`Val`] into a [`ValRaw`].
259     ///
260     /// Returns an error if this value is a GC reference and the GC reference
261     /// has been unrooted.
262     ///
263     /// # Safety
264     ///
265     /// The returned [`ValRaw`] does not carry type information and is only safe
266     /// to use within the context of this store itself. For more information see
267     /// [`ExternRef::to_raw`] and [`Func::to_raw`].
to_raw(&self, store: impl AsContextMut) -> Result<ValRaw>268     pub fn to_raw(&self, store: impl AsContextMut) -> Result<ValRaw> {
269         match self {
270             Val::I32(i) => Ok(ValRaw::i32(*i)),
271             Val::I64(i) => Ok(ValRaw::i64(*i)),
272             Val::F32(u) => Ok(ValRaw::f32(*u)),
273             Val::F64(u) => Ok(ValRaw::f64(*u)),
274             Val::V128(b) => Ok(ValRaw::v128(b.as_u128())),
275             Val::ExternRef(e) => Ok(ValRaw::externref(match e {
276                 None => 0,
277                 Some(e) => e.to_raw(store)?,
278             })),
279             Val::AnyRef(e) => Ok(ValRaw::anyref(match e {
280                 None => 0,
281                 Some(e) => e.to_raw(store)?,
282             })),
283             Val::ExnRef(e) => Ok(ValRaw::exnref(match e {
284                 None => 0,
285                 Some(e) => e.to_raw(store)?,
286             })),
287             Val::FuncRef(f) => Ok(ValRaw::funcref(match f {
288                 Some(f) => f.to_raw(store),
289                 None => ptr::null_mut(),
290             })),
291             Val::ContRef(_) => {
292                 // TODO(#10248): Implement proper continuation reference to_raw conversion
293                 Err(crate::format_err!(
294                     "continuation references not yet supported in to_raw conversion"
295                 ))
296             }
297         }
298     }
299 
300     /// Convenience method to convert a [`ValRaw`] into a [`Val`].
301     ///
302     /// # Unsafety
303     ///
304     /// This method is unsafe for the reasons that [`ExternRef::from_raw`] and
305     /// [`Func::from_raw`] are unsafe. Additionally there's no guarantee
306     /// otherwise that `raw` should have the type `ty` specified.
from_raw(mut store: impl AsContextMut, raw: ValRaw, ty: ValType) -> Val307     pub unsafe fn from_raw(mut store: impl AsContextMut, raw: ValRaw, ty: ValType) -> Val {
308         let mut store = AutoAssertNoGc::new(store.as_context_mut().0);
309         // SAFETY: `_from_raw` has the same contract as this function.
310         unsafe { Self::_from_raw(&mut store, raw, &ty) }
311     }
312 
313     /// Same as [`Self::from_raw`], but with a monomorphic store.
_from_raw( store: &mut AutoAssertNoGc<'_>, raw: ValRaw, ty: &ValType, ) -> Val314     pub(crate) unsafe fn _from_raw(
315         store: &mut AutoAssertNoGc<'_>,
316         raw: ValRaw,
317         ty: &ValType,
318     ) -> Val {
319         match ty {
320             ValType::I32 => Val::I32(raw.get_i32()),
321             ValType::I64 => Val::I64(raw.get_i64()),
322             ValType::F32 => Val::F32(raw.get_f32()),
323             ValType::F64 => Val::F64(raw.get_f64()),
324             ValType::V128 => Val::V128(raw.get_v128().into()),
325             ValType::Ref(ref_ty) => {
326                 let ref_ = match ref_ty.heap_type() {
327                     // SAFETY: it's a safety contract of this function that the
328                     // funcref is valid and owned by the provided store.
329                     HeapType::Func | HeapType::ConcreteFunc(_) => unsafe {
330                         Func::_from_raw(store, raw.get_funcref()).into()
331                     },
332 
333                     HeapType::NoFunc => Ref::Func(None),
334 
335                     HeapType::NoCont | HeapType::ConcreteCont(_) | HeapType::Cont => {
336                         // TODO(#10248): Required to support stack switching in the embedder API.
337                         unimplemented!()
338                     }
339 
340                     HeapType::Extern => ExternRef::_from_raw(store, raw.get_externref()).into(),
341 
342                     HeapType::NoExtern => Ref::Extern(None),
343 
344                     HeapType::Any
345                     | HeapType::Eq
346                     | HeapType::I31
347                     | HeapType::Array
348                     | HeapType::ConcreteArray(_)
349                     | HeapType::Struct
350                     | HeapType::ConcreteStruct(_) => {
351                         AnyRef::_from_raw(store, raw.get_anyref()).into()
352                     }
353 
354                     HeapType::Exn | HeapType::ConcreteExn(_) => {
355                         ExnRef::_from_raw(store, raw.get_exnref()).into()
356                     }
357                     HeapType::NoExn => Ref::Exn(None),
358 
359                     HeapType::None => Ref::Any(None),
360                 };
361                 assert!(
362                     ref_ty.is_nullable() || !ref_.is_null(),
363                     "if the type is not nullable, we shouldn't get null; got \
364                      type = {ref_ty}, ref = {ref_:?}"
365                 );
366                 ref_.into()
367             }
368         }
369     }
370 
371     accessors! {
372         e
373         (I32(i32) i32 unwrap_i32 *e)
374         (I64(i64) i64 unwrap_i64 *e)
375         (F32(f32) f32 unwrap_f32 f32::from_bits(*e))
376         (F64(f64) f64 unwrap_f64 f64::from_bits(*e))
377         (FuncRef(Option<&Func>) func_ref unwrap_func_ref e.as_ref())
378         (ExternRef(Option<&Rooted<ExternRef>>) extern_ref unwrap_extern_ref e.as_ref())
379         (AnyRef(Option<&Rooted<AnyRef>>) any_ref unwrap_any_ref e.as_ref())
380         (V128(V128) v128 unwrap_v128 *e)
381     }
382 
383     /// Get this value's underlying reference, if any.
384     #[inline]
ref_(self) -> Option<Ref>385     pub fn ref_(self) -> Option<Ref> {
386         match self {
387             Val::FuncRef(f) => Some(Ref::Func(f)),
388             Val::ExternRef(e) => Some(Ref::Extern(e)),
389             Val::AnyRef(a) => Some(Ref::Any(a)),
390             Val::ExnRef(e) => Some(Ref::Exn(e)),
391             Val::I32(_) | Val::I64(_) | Val::F32(_) | Val::F64(_) | Val::V128(_) => None,
392             Val::ContRef(_) => None, // TODO(#10248): Return proper Ref::Cont when available
393         }
394     }
395 
396     /// Attempt to access the underlying `externref` value of this `Val`.
397     ///
398     /// If this is not an `externref`, then `None` is returned.
399     ///
400     /// If this is a null `externref`, then `Some(None)` is returned.
401     ///
402     /// If this is a non-null `externref`, then `Some(Some(..))` is returned.
403     #[inline]
externref(&self) -> Option<Option<&Rooted<ExternRef>>>404     pub fn externref(&self) -> Option<Option<&Rooted<ExternRef>>> {
405         match self {
406             Val::ExternRef(None) => Some(None),
407             Val::ExternRef(Some(e)) => Some(Some(e)),
408             _ => None,
409         }
410     }
411 
412     /// Returns the underlying `externref` value of this `Val`, panicking if it's the
413     /// wrong type.
414     ///
415     /// If this is a null `externref`, then `None` is returned.
416     ///
417     /// If this is a non-null `externref`, then `Some(..)` is returned.
418     ///
419     /// # Panics
420     ///
421     /// Panics if `self` is not a (nullable) `externref`.
422     #[inline]
unwrap_externref(&self) -> Option<&Rooted<ExternRef>>423     pub fn unwrap_externref(&self) -> Option<&Rooted<ExternRef>> {
424         self.externref().expect("expected externref")
425     }
426 
427     /// Attempt to access the underlying `anyref` value of this `Val`.
428     ///
429     /// If this is not an `anyref`, then `None` is returned.
430     ///
431     /// If this is a null `anyref`, then `Some(None)` is returned.
432     ///
433     /// If this is a non-null `anyref`, then `Some(Some(..))` is returned.
434     #[inline]
anyref(&self) -> Option<Option<&Rooted<AnyRef>>>435     pub fn anyref(&self) -> Option<Option<&Rooted<AnyRef>>> {
436         match self {
437             Val::AnyRef(None) => Some(None),
438             Val::AnyRef(Some(e)) => Some(Some(e)),
439             _ => None,
440         }
441     }
442 
443     /// Returns the underlying `anyref` value of this `Val`, panicking if it's the
444     /// wrong type.
445     ///
446     /// If this is a null `anyref`, then `None` is returned.
447     ///
448     /// If this is a non-null `anyref`, then `Some(..)` is returned.
449     ///
450     /// # Panics
451     ///
452     /// Panics if `self` is not a (nullable) `anyref`.
453     #[inline]
unwrap_anyref(&self) -> Option<&Rooted<AnyRef>>454     pub fn unwrap_anyref(&self) -> Option<&Rooted<AnyRef>> {
455         self.anyref().expect("expected anyref")
456     }
457 
458     /// Attempt to access the underlying `exnref` value of this `Val`.
459     ///
460     /// If this is not an `exnref`, then `None` is returned.
461     ///
462     /// If this is a null `exnref`, then `Some(None)` is returned.
463     ///
464     /// If this is a non-null `exnref`, then `Some(Some(..))` is returned.
465     #[inline]
exnref(&self) -> Option<Option<&Rooted<ExnRef>>>466     pub fn exnref(&self) -> Option<Option<&Rooted<ExnRef>>> {
467         match self {
468             Val::ExnRef(None) => Some(None),
469             Val::ExnRef(Some(e)) => Some(Some(e)),
470             _ => None,
471         }
472     }
473 
474     /// Returns the underlying `exnref` value of this `Val`, panicking if it's the
475     /// wrong type.
476     ///
477     /// If this is a null `exnref`, then `None` is returned.
478     ///
479     /// If this is a non-null `exnref`, then `Some(..)` is returned.
480     ///
481     /// # Panics
482     ///
483     /// Panics if `self` is not a (nullable) `exnref`.
484     #[inline]
unwrap_exnref(&self) -> Option<&Rooted<ExnRef>>485     pub fn unwrap_exnref(&self) -> Option<&Rooted<ExnRef>> {
486         self.exnref().expect("expected exnref")
487     }
488 
489     /// Attempt to access the underlying `funcref` value of this `Val`.
490     ///
491     /// If this is not an `funcref`, then `None` is returned.
492     ///
493     /// If this is a null `funcref`, then `Some(None)` is returned.
494     ///
495     /// If this is a non-null `funcref`, then `Some(Some(..))` is returned.
496     #[inline]
funcref(&self) -> Option<Option<&Func>>497     pub fn funcref(&self) -> Option<Option<&Func>> {
498         match self {
499             Val::FuncRef(None) => Some(None),
500             Val::FuncRef(Some(f)) => Some(Some(f)),
501             _ => None,
502         }
503     }
504 
505     /// Returns the underlying `funcref` value of this `Val`, panicking if it's the
506     /// wrong type.
507     ///
508     /// If this is a null `funcref`, then `None` is returned.
509     ///
510     /// If this is a non-null `funcref`, then `Some(..)` is returned.
511     ///
512     /// # Panics
513     ///
514     /// Panics if `self` is not a (nullable) `funcref`.
515     #[inline]
unwrap_funcref(&self) -> Option<&Func>516     pub fn unwrap_funcref(&self) -> Option<&Func> {
517         self.funcref().expect("expected funcref")
518     }
519 
520     #[inline]
comes_from_same_store(&self, store: &StoreOpaque) -> bool521     pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
522         match self {
523             Val::FuncRef(Some(f)) => f.comes_from_same_store(store),
524             Val::FuncRef(None) => true,
525 
526             Val::ExternRef(Some(x)) => x.comes_from_same_store(store),
527             Val::ExternRef(None) => true,
528 
529             Val::AnyRef(Some(a)) => a.comes_from_same_store(store),
530             Val::AnyRef(None) => true,
531 
532             Val::ExnRef(Some(e)) => e.comes_from_same_store(store),
533             Val::ExnRef(None) => true,
534 
535             // Integers, floats, and vectors have no association with any
536             // particular store, so they're always considered as "yes I came
537             // from that store",
538             Val::I32(_) | Val::I64(_) | Val::F32(_) | Val::F64(_) | Val::V128(_) => true,
539 
540             // Continuation references are not yet associated with stores
541             Val::ContRef(_) => true, // TODO(#10248): Proper store association when implemented
542         }
543     }
544 }
545 
546 impl From<i32> for Val {
547     #[inline]
from(val: i32) -> Val548     fn from(val: i32) -> Val {
549         Val::I32(val)
550     }
551 }
552 
553 impl From<i64> for Val {
554     #[inline]
from(val: i64) -> Val555     fn from(val: i64) -> Val {
556         Val::I64(val)
557     }
558 }
559 
560 impl From<f32> for Val {
561     #[inline]
from(val: f32) -> Val562     fn from(val: f32) -> Val {
563         Val::F32(val.to_bits())
564     }
565 }
566 
567 impl From<f64> for Val {
568     #[inline]
from(val: f64) -> Val569     fn from(val: f64) -> Val {
570         Val::F64(val.to_bits())
571     }
572 }
573 
574 impl From<Ref> for Val {
575     #[inline]
from(val: Ref) -> Val576     fn from(val: Ref) -> Val {
577         match val {
578             Ref::Extern(e) => Val::ExternRef(e),
579             Ref::Func(f) => Val::FuncRef(f),
580             Ref::Any(a) => Val::AnyRef(a),
581             Ref::Exn(e) => Val::ExnRef(e),
582         }
583     }
584 }
585 
586 impl From<Rooted<ExternRef>> for Val {
587     #[inline]
from(val: Rooted<ExternRef>) -> Val588     fn from(val: Rooted<ExternRef>) -> Val {
589         Val::ExternRef(Some(val))
590     }
591 }
592 
593 impl From<Option<Rooted<ExternRef>>> for Val {
594     #[inline]
from(val: Option<Rooted<ExternRef>>) -> Val595     fn from(val: Option<Rooted<ExternRef>>) -> Val {
596         Val::ExternRef(val)
597     }
598 }
599 
600 impl From<Rooted<AnyRef>> for Val {
601     #[inline]
from(val: Rooted<AnyRef>) -> Val602     fn from(val: Rooted<AnyRef>) -> Val {
603         Val::AnyRef(Some(val))
604     }
605 }
606 
607 impl From<Option<Rooted<AnyRef>>> for Val {
608     #[inline]
from(val: Option<Rooted<AnyRef>>) -> Val609     fn from(val: Option<Rooted<AnyRef>>) -> Val {
610         Val::AnyRef(val)
611     }
612 }
613 
614 impl From<Rooted<StructRef>> for Val {
615     #[inline]
from(val: Rooted<StructRef>) -> Val616     fn from(val: Rooted<StructRef>) -> Val {
617         Val::AnyRef(Some(val.into()))
618     }
619 }
620 
621 impl From<Option<Rooted<StructRef>>> for Val {
622     #[inline]
from(val: Option<Rooted<StructRef>>) -> Val623     fn from(val: Option<Rooted<StructRef>>) -> Val {
624         Val::AnyRef(val.map(Into::into))
625     }
626 }
627 
628 impl From<Rooted<ArrayRef>> for Val {
629     #[inline]
from(val: Rooted<ArrayRef>) -> Val630     fn from(val: Rooted<ArrayRef>) -> Val {
631         Val::AnyRef(Some(val.into()))
632     }
633 }
634 
635 impl From<Option<Rooted<ArrayRef>>> for Val {
636     #[inline]
from(val: Option<Rooted<ArrayRef>>) -> Val637     fn from(val: Option<Rooted<ArrayRef>>) -> Val {
638         Val::AnyRef(val.map(Into::into))
639     }
640 }
641 
642 impl From<Rooted<ExnRef>> for Val {
643     #[inline]
from(val: Rooted<ExnRef>) -> Val644     fn from(val: Rooted<ExnRef>) -> Val {
645         Val::ExnRef(Some(val))
646     }
647 }
648 
649 impl From<Option<Rooted<ExnRef>>> for Val {
650     #[inline]
from(val: Option<Rooted<ExnRef>>) -> Val651     fn from(val: Option<Rooted<ExnRef>>) -> Val {
652         Val::ExnRef(val)
653     }
654 }
655 
656 impl From<Func> for Val {
657     #[inline]
from(val: Func) -> Val658     fn from(val: Func) -> Val {
659         Val::FuncRef(Some(val))
660     }
661 }
662 
663 impl From<Option<Func>> for Val {
664     #[inline]
from(val: Option<Func>) -> Val665     fn from(val: Option<Func>) -> Val {
666         Val::FuncRef(val)
667     }
668 }
669 
670 impl From<u128> for Val {
671     #[inline]
from(val: u128) -> Val672     fn from(val: u128) -> Val {
673         Val::V128(val.into())
674     }
675 }
676 
677 impl From<V128> for Val {
678     #[inline]
from(val: V128) -> Val679     fn from(val: V128) -> Val {
680         Val::V128(val)
681     }
682 }
683 
684 /// A reference.
685 ///
686 /// References come in three broad flavors:
687 ///
688 /// 1. Function references. These are references to a function that can be
689 ///    invoked.
690 ///
691 /// 2. External references. These are references to data that is external
692 ///    and opaque to the Wasm guest, provided by the host.
693 ///
694 /// 3. Internal references. These are references to allocations inside the
695 ///    Wasm's heap, such as structs and arrays. These are part of the GC
696 ///    proposal, and not yet implemented in Wasmtime.
697 ///
698 /// At the Wasm level, there are nullable and non-nullable variants of each type
699 /// of reference. Both variants are represented with `Ref` at the Wasmtime API
700 /// level. For example, values of both `(ref extern)` and `(ref null extern)`
701 /// types will be represented as `Ref::Extern(Option<ExternRef>)` in the
702 /// Wasmtime API. Nullable references are represented as `Option<Ref>` where
703 /// null references are represented as `None`. Wasm can construct null
704 /// references via the `ref.null <heap-type>` instruction.
705 ///
706 /// References are non-forgable: Wasm cannot create invalid references, for
707 /// example, by claiming that the integer `0xbad1bad2` is actually a reference.
708 #[derive(Debug, Clone)]
709 pub enum Ref {
710     // NB: We have a variant for each of the type hierarchies defined in Wasm,
711     // and push the `Option` that provides nullability into each variant. This
712     // allows us to get the most-precise type of any reference value, whether it
713     // is null or not, without any additional metadata.
714     //
715     // Consider if we instead had the nullability inside `Val::Ref` and each of
716     // the `Ref` variants did not have an `Option`:
717     //
718     //     enum Val {
719     //         Ref(Option<Ref>),
720     //         // Etc...
721     //     }
722     //     enum Ref {
723     //         Func(Func),
724     //         External(ExternRef),
725     //         // Etc...
726     //     }
727     //
728     // In this scenario, what type would we return from `Val::ty` for
729     // `Val::Ref(None)`? Because Wasm has multiple separate type hierarchies,
730     // there is no single common bottom type for all the different kinds of
731     // references. So in this scenario, `Val::Ref(None)` doesn't have enough
732     // information to reconstruct the value's type. That's a problem for us
733     // because we need to get a value's type at various times all over the code
734     // base.
735     //
736     /// A first-class reference to a WebAssembly function.
737     ///
738     /// The host, or the Wasm guest, can invoke this function.
739     ///
740     /// The host can create function references via [`Func::new`] or
741     /// [`Func::wrap`].
742     ///
743     /// The Wasm guest can create non-null function references via the
744     /// `ref.func` instruction, or null references via the `ref.null func`
745     /// instruction.
746     Func(Option<Func>),
747 
748     /// A reference to an value outside of the Wasm heap.
749     ///
750     /// These references are opaque to the Wasm itself. Wasm can't create
751     /// non-null external references, nor do anything with them accept pass them
752     /// around as function arguments and returns and place them into globals and
753     /// tables.
754     ///
755     /// Wasm can create null external references via the `ref.null extern`
756     /// instruction.
757     Extern(Option<Rooted<ExternRef>>),
758 
759     /// An internal reference.
760     ///
761     /// The `AnyRef` type represents WebAssembly `anyref` values. These can be
762     /// references to `struct`s and `array`s or inline/unboxed 31-bit
763     /// integers.
764     ///
765     /// Unlike `externref`, Wasm guests can directly allocate `anyref`s, and
766     /// does not need to rely on the host to do that.
767     Any(Option<Rooted<AnyRef>>),
768 
769     /// An exception-object reference.
770     ///
771     /// The `ExnRef` type represents WebAssembly `exnref`
772     /// values. These are references to exception objects as caught by
773     /// `catch_ref` clauses on `try_table` instructions, or as
774     /// allocated via the host API.
775     Exn(Option<Rooted<ExnRef>>),
776 }
777 
778 impl From<Func> for Ref {
779     #[inline]
from(f: Func) -> Ref780     fn from(f: Func) -> Ref {
781         Ref::Func(Some(f))
782     }
783 }
784 
785 impl From<Option<Func>> for Ref {
786     #[inline]
from(f: Option<Func>) -> Ref787     fn from(f: Option<Func>) -> Ref {
788         Ref::Func(f)
789     }
790 }
791 
792 impl From<Rooted<ExternRef>> for Ref {
793     #[inline]
from(e: Rooted<ExternRef>) -> Ref794     fn from(e: Rooted<ExternRef>) -> Ref {
795         Ref::Extern(Some(e))
796     }
797 }
798 
799 impl From<Option<Rooted<ExternRef>>> for Ref {
800     #[inline]
from(e: Option<Rooted<ExternRef>>) -> Ref801     fn from(e: Option<Rooted<ExternRef>>) -> Ref {
802         Ref::Extern(e)
803     }
804 }
805 
806 impl From<Rooted<AnyRef>> for Ref {
807     #[inline]
from(e: Rooted<AnyRef>) -> Ref808     fn from(e: Rooted<AnyRef>) -> Ref {
809         Ref::Any(Some(e))
810     }
811 }
812 
813 impl From<Option<Rooted<AnyRef>>> for Ref {
814     #[inline]
from(e: Option<Rooted<AnyRef>>) -> Ref815     fn from(e: Option<Rooted<AnyRef>>) -> Ref {
816         Ref::Any(e)
817     }
818 }
819 
820 impl From<Rooted<StructRef>> for Ref {
821     #[inline]
from(e: Rooted<StructRef>) -> Ref822     fn from(e: Rooted<StructRef>) -> Ref {
823         Ref::Any(Some(e.into()))
824     }
825 }
826 
827 impl From<Option<Rooted<StructRef>>> for Ref {
828     #[inline]
from(e: Option<Rooted<StructRef>>) -> Ref829     fn from(e: Option<Rooted<StructRef>>) -> Ref {
830         Ref::Any(e.map(Into::into))
831     }
832 }
833 
834 impl From<Rooted<ArrayRef>> for Ref {
835     #[inline]
from(e: Rooted<ArrayRef>) -> Ref836     fn from(e: Rooted<ArrayRef>) -> Ref {
837         Ref::Any(Some(e.into()))
838     }
839 }
840 
841 impl From<Option<Rooted<ArrayRef>>> for Ref {
842     #[inline]
from(e: Option<Rooted<ArrayRef>>) -> Ref843     fn from(e: Option<Rooted<ArrayRef>>) -> Ref {
844         Ref::Any(e.map(Into::into))
845     }
846 }
847 
848 impl From<Rooted<ExnRef>> for Ref {
849     #[inline]
from(e: Rooted<ExnRef>) -> Ref850     fn from(e: Rooted<ExnRef>) -> Ref {
851         Ref::Exn(Some(e))
852     }
853 }
854 
855 impl From<Option<Rooted<ExnRef>>> for Ref {
856     #[inline]
from(e: Option<Rooted<ExnRef>>) -> Ref857     fn from(e: Option<Rooted<ExnRef>>) -> Ref {
858         Ref::Exn(e)
859     }
860 }
861 
862 impl Ref {
863     /// Create a null reference to the given heap type.
864     #[inline]
null(heap_type: &HeapType) -> Self865     pub fn null(heap_type: &HeapType) -> Self {
866         match heap_type.top() {
867             HeapType::Any => Ref::Any(None),
868             HeapType::Extern => Ref::Extern(None),
869             HeapType::Func => Ref::Func(None),
870             HeapType::Exn => Ref::Exn(None),
871             ty => unreachable!("not a heap type: {ty:?}"),
872         }
873     }
874 
875     /// Is this a null reference?
876     #[inline]
is_null(&self) -> bool877     pub fn is_null(&self) -> bool {
878         match self {
879             Ref::Any(None) | Ref::Extern(None) | Ref::Func(None) | Ref::Exn(None) => true,
880             Ref::Any(Some(_)) | Ref::Extern(Some(_)) | Ref::Func(Some(_)) | Ref::Exn(Some(_)) => {
881                 false
882             }
883         }
884     }
885 
886     /// Is this a non-null reference?
887     #[inline]
is_non_null(&self) -> bool888     pub fn is_non_null(&self) -> bool {
889         !self.is_null()
890     }
891 
892     /// Is this an `extern` reference?
893     #[inline]
is_extern(&self) -> bool894     pub fn is_extern(&self) -> bool {
895         matches!(self, Ref::Extern(_))
896     }
897 
898     /// Get the underlying `extern` reference, if any.
899     ///
900     /// Returns `None` if this `Ref` is not an `extern` reference, eg it is a
901     /// `func` reference.
902     ///
903     /// Returns `Some(None)` if this `Ref` is a null `extern` reference.
904     ///
905     /// Returns `Some(Some(_))` if this `Ref` is a non-null `extern` reference.
906     #[inline]
as_extern(&self) -> Option<Option<&Rooted<ExternRef>>>907     pub fn as_extern(&self) -> Option<Option<&Rooted<ExternRef>>> {
908         match self {
909             Ref::Extern(e) => Some(e.as_ref()),
910             _ => None,
911         }
912     }
913 
914     /// Get the underlying `extern` reference, panicking if this is a different
915     /// kind of reference.
916     ///
917     /// Returns `None` if this `Ref` is a null `extern` reference.
918     ///
919     /// Returns `Some(_)` if this `Ref` is a non-null `extern` reference.
920     #[inline]
unwrap_extern(&self) -> Option<&Rooted<ExternRef>>921     pub fn unwrap_extern(&self) -> Option<&Rooted<ExternRef>> {
922         self.as_extern()
923             .expect("Ref::unwrap_extern on non-extern reference")
924     }
925 
926     /// Is this an `any` reference?
927     #[inline]
is_any(&self) -> bool928     pub fn is_any(&self) -> bool {
929         matches!(self, Ref::Any(_))
930     }
931 
932     /// Get the underlying `any` reference, if any.
933     ///
934     /// Returns `None` if this `Ref` is not an `any` reference, eg it is a
935     /// `func` reference.
936     ///
937     /// Returns `Some(None)` if this `Ref` is a null `any` reference.
938     ///
939     /// Returns `Some(Some(_))` if this `Ref` is a non-null `any` reference.
940     #[inline]
as_any(&self) -> Option<Option<&Rooted<AnyRef>>>941     pub fn as_any(&self) -> Option<Option<&Rooted<AnyRef>>> {
942         match self {
943             Ref::Any(e) => Some(e.as_ref()),
944             _ => None,
945         }
946     }
947 
948     /// Get the underlying `any` reference, panicking if this is a different
949     /// kind of reference.
950     ///
951     /// Returns `None` if this `Ref` is a null `any` reference.
952     ///
953     /// Returns `Some(_)` if this `Ref` is a non-null `any` reference.
954     #[inline]
unwrap_any(&self) -> Option<&Rooted<AnyRef>>955     pub fn unwrap_any(&self) -> Option<&Rooted<AnyRef>> {
956         self.as_any().expect("Ref::unwrap_any on non-any reference")
957     }
958 
959     /// Is this an `exn` reference?
960     #[inline]
is_exn(&self) -> bool961     pub fn is_exn(&self) -> bool {
962         matches!(self, Ref::Exn(_))
963     }
964 
965     /// Get the underlying `exn` reference, if any.
966     ///
967     /// Returns `None` if this `Ref` is not an `exn` reference, eg it is a
968     /// `func` reference.
969     ///
970     /// Returns `Some(None)` if this `Ref` is a null `exn` reference.
971     ///
972     /// Returns `Some(Some(_))` if this `Ref` is a non-null `exn` reference.
973     #[inline]
as_exn(&self) -> Option<Option<&Rooted<ExnRef>>>974     pub fn as_exn(&self) -> Option<Option<&Rooted<ExnRef>>> {
975         match self {
976             Ref::Exn(e) => Some(e.as_ref()),
977             _ => None,
978         }
979     }
980 
981     /// Get the underlying `exn` reference, panicking if this is a different
982     /// kind of reference.
983     ///
984     /// Returns `None` if this `Ref` is a null `exn` reference.
985     ///
986     /// Returns `Some(_)` if this `Ref` is a non-null `exn` reference.
987     #[inline]
unwrap_exn(&self) -> Option<&Rooted<ExnRef>>988     pub fn unwrap_exn(&self) -> Option<&Rooted<ExnRef>> {
989         self.as_exn().expect("Ref::unwrap_exn on non-exn reference")
990     }
991 
992     /// Is this a `func` reference?
993     #[inline]
is_func(&self) -> bool994     pub fn is_func(&self) -> bool {
995         matches!(self, Ref::Func(_))
996     }
997 
998     /// Get the underlying `func` reference, if any.
999     ///
1000     /// Returns `None` if this `Ref` is not an `func` reference, eg it is an
1001     /// `extern` reference.
1002     ///
1003     /// Returns `Some(None)` if this `Ref` is a null `func` reference.
1004     ///
1005     /// Returns `Some(Some(_))` if this `Ref` is a non-null `func` reference.
1006     #[inline]
as_func(&self) -> Option<Option<&Func>>1007     pub fn as_func(&self) -> Option<Option<&Func>> {
1008         match self {
1009             Ref::Func(f) => Some(f.as_ref()),
1010             _ => None,
1011         }
1012     }
1013 
1014     /// Get the underlying `func` reference, panicking if this is a different
1015     /// kind of reference.
1016     ///
1017     /// Returns `None` if this `Ref` is a null `func` reference.
1018     ///
1019     /// Returns `Some(_)` if this `Ref` is a non-null `func` reference.
1020     #[inline]
unwrap_func(&self) -> Option<&Func>1021     pub fn unwrap_func(&self) -> Option<&Func> {
1022         self.as_func()
1023             .expect("Ref::unwrap_func on non-func reference")
1024     }
1025 
1026     /// Get the type of this reference.
1027     ///
1028     /// # Errors
1029     ///
1030     /// Return an error if this reference has been unrooted.
1031     ///
1032     /// # Panics
1033     ///
1034     /// Panics if this reference is associated with a different store.
ty(&self, store: impl AsContext) -> Result<RefType>1035     pub fn ty(&self, store: impl AsContext) -> Result<RefType> {
1036         self.load_ty(&store.as_context().0)
1037     }
1038 
load_ty(&self, store: &StoreOpaque) -> Result<RefType>1039     pub(crate) fn load_ty(&self, store: &StoreOpaque) -> Result<RefType> {
1040         assert!(self.comes_from_same_store(store));
1041         Ok(RefType::new(
1042             self.is_null(),
1043             // NB: We choose the most-specific heap type we can here and let
1044             // subtyping do its thing if callers are matching against a
1045             // `HeapType::Func`.
1046             match self {
1047                 Ref::Extern(None) => HeapType::NoExtern,
1048                 Ref::Extern(Some(_)) => HeapType::Extern,
1049 
1050                 Ref::Func(None) => HeapType::NoFunc,
1051                 Ref::Func(Some(f)) => HeapType::ConcreteFunc(f.load_ty(store)),
1052 
1053                 Ref::Any(None) => HeapType::None,
1054                 Ref::Any(Some(a)) => a._ty(store)?,
1055 
1056                 Ref::Exn(None) => HeapType::None,
1057                 Ref::Exn(Some(e)) => e._ty(store)?.into(),
1058             },
1059         ))
1060     }
1061 
1062     /// Does this reference value match the given type?
1063     ///
1064     /// Returns an error if the underlying `Rooted` has been unrooted.
1065     ///
1066     /// # Panics
1067     ///
1068     /// Panics if this reference is not associated with the given store.
matches_ty(&self, store: impl AsContext, ty: &RefType) -> Result<bool>1069     pub fn matches_ty(&self, store: impl AsContext, ty: &RefType) -> Result<bool> {
1070         self._matches_ty(&store.as_context().0, ty)
1071     }
1072 
_matches_ty(&self, store: &StoreOpaque, ty: &RefType) -> Result<bool>1073     pub(crate) fn _matches_ty(&self, store: &StoreOpaque, ty: &RefType) -> Result<bool> {
1074         assert!(self.comes_from_same_store(store));
1075         assert!(ty.comes_from_same_engine(store.engine()));
1076         if self.is_null() && !ty.is_nullable() {
1077             return Ok(false);
1078         }
1079         Ok(match (self, ty.heap_type()) {
1080             (Ref::Extern(_), HeapType::Extern) => true,
1081             (Ref::Extern(None), HeapType::NoExtern) => true,
1082             (Ref::Extern(_), _) => false,
1083 
1084             (Ref::Func(_), HeapType::Func) => true,
1085             (Ref::Func(None), HeapType::NoFunc | HeapType::ConcreteFunc(_)) => true,
1086             (Ref::Func(Some(f)), HeapType::ConcreteFunc(func_ty)) => f._matches_ty(store, func_ty),
1087             (Ref::Func(_), _) => false,
1088 
1089             (Ref::Any(_), HeapType::Any) => true,
1090             (Ref::Any(Some(a)), HeapType::I31) => a._is_i31(store)?,
1091             (Ref::Any(Some(a)), HeapType::Struct) => a._is_struct(store)?,
1092             (Ref::Any(Some(a)), HeapType::ConcreteStruct(_ty)) => match a._as_struct(store)? {
1093                 None => false,
1094                 Some(s) => s._matches_ty(store, _ty)?,
1095             },
1096             (Ref::Any(Some(a)), HeapType::Eq) => a._is_eqref(store)?,
1097             (Ref::Any(Some(a)), HeapType::Array) => a._is_array(store)?,
1098             (Ref::Any(Some(a)), HeapType::ConcreteArray(_ty)) => match a._as_array(store)? {
1099                 None => false,
1100                 Some(a) => a._matches_ty(store, _ty)?,
1101             },
1102             (
1103                 Ref::Any(None),
1104                 HeapType::None
1105                 | HeapType::I31
1106                 | HeapType::ConcreteStruct(_)
1107                 | HeapType::Struct
1108                 | HeapType::ConcreteArray(_)
1109                 | HeapType::Array
1110                 | HeapType::Eq,
1111             ) => true,
1112             (Ref::Any(_), _) => false,
1113 
1114             (Ref::Exn(_), HeapType::Exn) => true,
1115             (Ref::Exn(None), HeapType::NoExn | HeapType::ConcreteExn(_)) => true,
1116             (Ref::Exn(Some(e)), HeapType::ConcreteExn(_)) => {
1117                 e._matches_ty(store, &ty.heap_type())?
1118             }
1119             (Ref::Exn(_), _) => false,
1120         })
1121     }
1122 
ensure_matches_ty(&self, store: &StoreOpaque, ty: &RefType) -> Result<()>1123     pub(crate) fn ensure_matches_ty(&self, store: &StoreOpaque, ty: &RefType) -> Result<()> {
1124         if !self.comes_from_same_store(store) {
1125             bail!("reference used with wrong store")
1126         }
1127         if !ty.comes_from_same_engine(store.engine()) {
1128             bail!("type used with wrong engine")
1129         }
1130         if self._matches_ty(store, ty)? {
1131             Ok(())
1132         } else {
1133             let actual_ty = self.load_ty(store)?;
1134             bail!("type mismatch: expected {ty}, found {actual_ty}")
1135         }
1136     }
1137 
comes_from_same_store(&self, store: &StoreOpaque) -> bool1138     pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
1139         match self {
1140             Ref::Func(Some(f)) => f.comes_from_same_store(store),
1141             Ref::Func(None) => true,
1142             Ref::Extern(Some(x)) => x.comes_from_same_store(store),
1143             Ref::Extern(None) => true,
1144             Ref::Any(Some(a)) => a.comes_from_same_store(store),
1145             Ref::Any(None) => true,
1146             Ref::Exn(Some(e)) => e.comes_from_same_store(store),
1147             Ref::Exn(None) => true,
1148         }
1149     }
1150 }
1151 
1152 #[cfg(test)]
1153 mod tests {
1154     use crate::*;
1155 
1156     #[test]
size_of_val()1157     fn size_of_val() {
1158         // Try to keep tabs on the size of `Val` and make sure we don't grow its
1159         // size.
1160         let expected = if cfg!(target_arch = "x86_64")
1161             || cfg!(target_arch = "aarch64")
1162             || cfg!(target_arch = "s390x")
1163             || cfg!(target_arch = "riscv64")
1164             || cfg!(target_arch = "arm")
1165         {
1166             24
1167         } else if cfg!(target_arch = "x86") {
1168             20
1169         } else {
1170             panic!("unsupported architecture")
1171         };
1172         assert_eq!(std::mem::size_of::<Val>(), expected);
1173     }
1174 
1175     #[test]
size_of_ref()1176     fn size_of_ref() {
1177         // Try to keep tabs on the size of `Ref` and make sure we don't grow its
1178         // size.
1179         let expected = if cfg!(target_arch = "x86_64")
1180             || cfg!(target_arch = "aarch64")
1181             || cfg!(target_arch = "s390x")
1182             || cfg!(target_arch = "riscv64")
1183             || cfg!(target_arch = "arm")
1184         {
1185             24
1186         } else if cfg!(target_arch = "x86") {
1187             20
1188         } else {
1189             panic!("unsupported architecture")
1190         };
1191         assert_eq!(std::mem::size_of::<Ref>(), expected);
1192     }
1193 
1194     #[test]
1195     #[should_panic]
val_matches_ty_wrong_engine()1196     fn val_matches_ty_wrong_engine() {
1197         let e1 = Engine::default();
1198         let e2 = Engine::default();
1199 
1200         let t1 = FuncType::new(&e1, None, None);
1201         let t2 = FuncType::new(&e2, None, None);
1202 
1203         let mut s1 = Store::new(&e1, ());
1204         let f = Func::new(&mut s1, t1.clone(), |_caller, _args, _results| Ok(()));
1205 
1206         // Should panic.
1207         let _ = Val::FuncRef(Some(f)).matches_ty(
1208             &s1,
1209             &ValType::Ref(RefType::new(true, HeapType::ConcreteFunc(t2))),
1210         );
1211     }
1212 
1213     #[test]
1214     #[should_panic]
ref_matches_ty_wrong_engine()1215     fn ref_matches_ty_wrong_engine() {
1216         let e1 = Engine::default();
1217         let e2 = Engine::default();
1218 
1219         let t1 = FuncType::new(&e1, None, None);
1220         let t2 = FuncType::new(&e2, None, None);
1221 
1222         let mut s1 = Store::new(&e1, ());
1223         let f = Func::new(&mut s1, t1.clone(), |_caller, _args, _results| Ok(()));
1224 
1225         // Should panic.
1226         let _ = Ref::Func(Some(f)).matches_ty(&s1, &RefType::new(true, HeapType::ConcreteFunc(t2)));
1227     }
1228 }
1229