1 use crate::ValRaw;
2 use crate::component::ResourceAny;
3 use crate::component::concurrent::{self, ErrorContext, HostFuture, HostStream};
4 use crate::component::func::{Lift, LiftContext, Lower, LowerContext, desc};
5 use crate::prelude::*;
6 use core::mem::MaybeUninit;
7 use core::slice::{Iter, IterMut};
8 use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9 use wasmtime_environ::component::{
10     CanonicalAbiInfo, InterfaceType, TypeEnum, TypeFlags, TypeListIndex, TypeOption, TypeResult,
11     TypeVariant, VariantInfo,
12 };
13 
14 /// Represents possible runtime values which a component function can either
15 /// consume or produce
16 ///
17 /// This is a dynamic representation of possible values in the component model.
18 /// Note that this is not an efficient representation but is instead intended to
19 /// be a flexible and somewhat convenient representation. The most efficient
20 /// representation of component model types is to use the `bindgen!` macro to
21 /// generate native Rust types with specialized liftings and lowerings.
22 ///
23 /// This type is used in conjunction with [`Func::call`] for example if the
24 /// signature of a component is not statically known ahead of time.
25 ///
26 /// # Equality and `Val`
27 ///
28 /// This type implements both the Rust `PartialEq` and `Eq` traits. This type
29 /// additionally contains values which are not necessarily easily equated,
30 /// however, such as floats (`Float32` and `Float64`) and resources. Equality
31 /// does require that two values have the same type, and then these cases are
32 /// handled as:
33 ///
34 /// * Floats are tested if they are "semantically the same" meaning all NaN
35 ///   values are equal to all other NaN values. Additionally zero values must be
36 ///   exactly the same, so positive zero is not equal to negative zero. The
37 ///   primary use case at this time is fuzzing-related equality which this is
38 ///   sufficient for.
39 ///
40 /// * Resources are tested if their types and indices into the host table are
41 ///   equal. This does not compare the underlying representation so borrows of
42 ///   the same guest resource are not considered equal. This additionally
43 ///   doesn't go further and test for equality in the guest itself (for example
44 ///   two different heap allocations of `Box<u32>` can be equal in normal Rust
45 ///   if they contain the same value, but will never be considered equal when
46 ///   compared as `Val::Resource`s).
47 ///
48 /// In general if a strict guarantee about equality is required here it's
49 /// recommended to "build your own" as this equality intended for fuzzing
50 /// Wasmtime may not be suitable for you.
51 ///
52 /// # Component model types and `Val`
53 ///
54 /// The `Val` type here does not contain enough information to say what the
55 /// component model type of a `Val` is. This is instead more of an AST of sorts.
56 /// For example the `Val::Enum` only carries information about a single
57 /// discriminant, not the entire enumeration or what it's a discriminant of.
58 ///
59 /// This means that when a `Val` is passed to Wasmtime, for example as a
60 /// function parameter when calling a function or as a return value from an
61 /// host-defined imported function, then it must pass a type-check. Instances of
62 /// `Val` are type-checked against what's required by the component itself.
63 ///
64 /// [`Func::call`]: crate::component::Func::call
65 #[derive(Debug, Clone)]
66 #[expect(missing_docs, reason = "self-describing variants")]
67 pub enum Val {
68     Bool(bool),
69     S8(i8),
70     U8(u8),
71     S16(i16),
72     U16(u16),
73     S32(i32),
74     U32(u32),
75     S64(i64),
76     U64(u64),
77     Float32(f32),
78     Float64(f64),
79     Char(char),
80     String(String),
81     List(Vec<Val>),
82     Record(Vec<(String, Val)>),
83     Tuple(Vec<Val>),
84     Variant(String, Option<Box<Val>>),
85     Enum(String),
86     Option(Option<Box<Val>>),
87     Result(Result<Option<Box<Val>>, Option<Box<Val>>>),
88     Flags(Vec<String>),
89     Resource(ResourceAny),
90     Future(FutureAny),
91     Stream(StreamAny),
92     ErrorContext(ErrorContextAny),
93 }
94 
95 impl Val {
96     /// Deserialize a value of this type from core Wasm stack values.
97     pub(crate) fn lift(
98         cx: &mut LiftContext<'_>,
99         ty: InterfaceType,
100         src: &mut Iter<'_, ValRaw>,
101     ) -> Result<Val> {
102         Ok(match ty {
103             InterfaceType::Bool => Val::Bool(bool::linear_lift_from_flat(cx, ty, next(src))?),
104             InterfaceType::S8 => Val::S8(i8::linear_lift_from_flat(cx, ty, next(src))?),
105             InterfaceType::U8 => Val::U8(u8::linear_lift_from_flat(cx, ty, next(src))?),
106             InterfaceType::S16 => Val::S16(i16::linear_lift_from_flat(cx, ty, next(src))?),
107             InterfaceType::U16 => Val::U16(u16::linear_lift_from_flat(cx, ty, next(src))?),
108             InterfaceType::S32 => Val::S32(i32::linear_lift_from_flat(cx, ty, next(src))?),
109             InterfaceType::U32 => Val::U32(u32::linear_lift_from_flat(cx, ty, next(src))?),
110             InterfaceType::S64 => Val::S64(i64::linear_lift_from_flat(cx, ty, next(src))?),
111             InterfaceType::U64 => Val::U64(u64::linear_lift_from_flat(cx, ty, next(src))?),
112             InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_flat(cx, ty, next(src))?),
113             InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_flat(cx, ty, next(src))?),
114             InterfaceType::Char => Val::Char(char::linear_lift_from_flat(cx, ty, next(src))?),
115             InterfaceType::Own(_) | InterfaceType::Borrow(_) => {
116                 Val::Resource(ResourceAny::linear_lift_from_flat(cx, ty, next(src))?)
117             }
118             InterfaceType::String => Val::String(<_>::linear_lift_from_flat(
119                 cx,
120                 ty,
121                 &[*next(src), *next(src)],
122             )?),
123             InterfaceType::List(i) => {
124                 // FIXME(#4311): needs memory64 treatment
125                 let ptr = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
126                 let len = u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))? as usize;
127                 load_list(cx, i, ptr, len)?
128             }
129             InterfaceType::Record(i) => Val::Record(
130                 cx.types[i]
131                     .fields
132                     .iter()
133                     .map(|field| {
134                         let val = Self::lift(cx, field.ty, src)?;
135                         Ok((field.name.to_string(), val))
136                     })
137                     .collect::<Result<_>>()?,
138             ),
139             InterfaceType::Tuple(i) => Val::Tuple(
140                 cx.types[i]
141                     .types
142                     .iter()
143                     .map(|ty| Self::lift(cx, *ty, src))
144                     .collect::<Result<_>>()?,
145             ),
146             InterfaceType::Variant(i) => {
147                 let vty = &cx.types[i];
148                 let (discriminant, value) = lift_variant(
149                     cx,
150                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
151                     vty.cases.values().copied(),
152                     src,
153                 )?;
154 
155                 let (k, _) = vty.cases.get_index(discriminant as usize).unwrap();
156                 Val::Variant(k.clone(), value)
157             }
158             InterfaceType::Enum(i) => {
159                 let ety = &cx.types[i];
160                 let (discriminant, _) = lift_variant(
161                     cx,
162                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
163                     ety.names.iter().map(|_| None),
164                     src,
165                 )?;
166 
167                 Val::Enum(ety.names[discriminant as usize].clone())
168             }
169             InterfaceType::Option(i) => {
170                 let (_discriminant, value) = lift_variant(
171                     cx,
172                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
173                     [None, Some(cx.types[i].ty)].into_iter(),
174                     src,
175                 )?;
176 
177                 Val::Option(value)
178             }
179             InterfaceType::Result(i) => {
180                 let result_ty = &cx.types[i];
181                 let (discriminant, value) = lift_variant(
182                     cx,
183                     cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
184                     [result_ty.ok, result_ty.err].into_iter(),
185                     src,
186                 )?;
187 
188                 Val::Result(if discriminant == 0 {
189                     Ok(value)
190                 } else {
191                     Err(value)
192                 })
193             }
194             InterfaceType::Flags(i) => {
195                 let u32_count = cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap();
196                 let ty = &cx.types[i];
197                 let mut flags = Vec::new();
198                 for i in 0..u32::try_from(u32_count).unwrap() {
199                     push_flags(
200                         ty,
201                         &mut flags,
202                         i * 32,
203                         u32::linear_lift_from_flat(cx, InterfaceType::U32, next(src))?,
204                     );
205                 }
206 
207                 Val::Flags(flags)
208             }
209             InterfaceType::Future(_) => {
210                 HostFuture::<()>::linear_lift_from_flat(cx, ty, next(src))?.into_val()
211             }
212             InterfaceType::Stream(_) => {
213                 HostStream::<()>::linear_lift_from_flat(cx, ty, next(src))?.into_val()
214             }
215             InterfaceType::ErrorContext(_) => {
216                 ErrorContext::linear_lift_from_flat(cx, ty, next(src))?.into_val()
217             }
218         })
219     }
220 
221     /// Deserialize a value of this type from the heap.
222     pub(crate) fn load(cx: &mut LiftContext<'_>, ty: InterfaceType, bytes: &[u8]) -> Result<Val> {
223         Ok(match ty {
224             InterfaceType::Bool => Val::Bool(bool::linear_lift_from_memory(cx, ty, bytes)?),
225             InterfaceType::S8 => Val::S8(i8::linear_lift_from_memory(cx, ty, bytes)?),
226             InterfaceType::U8 => Val::U8(u8::linear_lift_from_memory(cx, ty, bytes)?),
227             InterfaceType::S16 => Val::S16(i16::linear_lift_from_memory(cx, ty, bytes)?),
228             InterfaceType::U16 => Val::U16(u16::linear_lift_from_memory(cx, ty, bytes)?),
229             InterfaceType::S32 => Val::S32(i32::linear_lift_from_memory(cx, ty, bytes)?),
230             InterfaceType::U32 => Val::U32(u32::linear_lift_from_memory(cx, ty, bytes)?),
231             InterfaceType::S64 => Val::S64(i64::linear_lift_from_memory(cx, ty, bytes)?),
232             InterfaceType::U64 => Val::U64(u64::linear_lift_from_memory(cx, ty, bytes)?),
233             InterfaceType::Float32 => Val::Float32(f32::linear_lift_from_memory(cx, ty, bytes)?),
234             InterfaceType::Float64 => Val::Float64(f64::linear_lift_from_memory(cx, ty, bytes)?),
235             InterfaceType::Char => Val::Char(char::linear_lift_from_memory(cx, ty, bytes)?),
236             InterfaceType::String => Val::String(<_>::linear_lift_from_memory(cx, ty, bytes)?),
237             InterfaceType::Own(_) | InterfaceType::Borrow(_) => {
238                 Val::Resource(ResourceAny::linear_lift_from_memory(cx, ty, bytes)?)
239             }
240             InterfaceType::List(i) => {
241                 // FIXME(#4311): needs memory64 treatment
242                 let ptr = u32::from_le_bytes(bytes[..4].try_into().unwrap()) as usize;
243                 let len = u32::from_le_bytes(bytes[4..].try_into().unwrap()) as usize;
244                 load_list(cx, i, ptr, len)?
245             }
246 
247             InterfaceType::Record(i) => {
248                 let mut offset = 0;
249                 let fields = cx.types[i].fields.iter();
250                 Val::Record(
251                     fields
252                         .map(|field| -> Result<(String, Val)> {
253                             let abi = cx.types.canonical_abi(&field.ty);
254                             let offset = abi.next_field32(&mut offset);
255                             let offset = usize::try_from(offset).unwrap();
256                             let size = usize::try_from(abi.size32).unwrap();
257                             Ok((
258                                 field.name.to_string(),
259                                 Val::load(cx, field.ty, &bytes[offset..][..size])?,
260                             ))
261                         })
262                         .collect::<Result<_>>()?,
263                 )
264             }
265             InterfaceType::Tuple(i) => {
266                 let types = cx.types[i].types.iter().copied();
267                 let mut offset = 0;
268                 Val::Tuple(
269                     types
270                         .map(|ty| {
271                             let abi = cx.types.canonical_abi(&ty);
272                             let offset = abi.next_field32(&mut offset);
273                             let offset = usize::try_from(offset).unwrap();
274                             let size = usize::try_from(abi.size32).unwrap();
275                             Val::load(cx, ty, &bytes[offset..][..size])
276                         })
277                         .collect::<Result<_>>()?,
278                 )
279             }
280             InterfaceType::Variant(i) => {
281                 let ty = &cx.types[i];
282                 let (discriminant, value) =
283                     load_variant(cx, &ty.info, ty.cases.values().copied(), bytes)?;
284 
285                 let (k, _) = ty.cases.get_index(discriminant as usize).unwrap();
286                 Val::Variant(k.clone(), value)
287             }
288             InterfaceType::Enum(i) => {
289                 let ty = &cx.types[i];
290                 let (discriminant, _) =
291                     load_variant(cx, &ty.info, ty.names.iter().map(|_| None), bytes)?;
292 
293                 Val::Enum(ty.names[discriminant as usize].clone())
294             }
295             InterfaceType::Option(i) => {
296                 let ty = &cx.types[i];
297                 let (_discriminant, value) =
298                     load_variant(cx, &ty.info, [None, Some(ty.ty)].into_iter(), bytes)?;
299 
300                 Val::Option(value)
301             }
302             InterfaceType::Result(i) => {
303                 let ty = &cx.types[i];
304                 let (discriminant, value) =
305                     load_variant(cx, &ty.info, [ty.ok, ty.err].into_iter(), bytes)?;
306 
307                 Val::Result(if discriminant == 0 {
308                     Ok(value)
309                 } else {
310                     Err(value)
311                 })
312             }
313             InterfaceType::Flags(i) => {
314                 let ty = &cx.types[i];
315                 let mut flags = Vec::new();
316                 match FlagsSize::from_count(ty.names.len()) {
317                     FlagsSize::Size0 => {}
318                     FlagsSize::Size1 => {
319                         let bits = u8::linear_lift_from_memory(cx, InterfaceType::U8, bytes)?;
320                         push_flags(ty, &mut flags, 0, u32::from(bits));
321                     }
322                     FlagsSize::Size2 => {
323                         let bits = u16::linear_lift_from_memory(cx, InterfaceType::U16, bytes)?;
324                         push_flags(ty, &mut flags, 0, u32::from(bits));
325                     }
326                     FlagsSize::Size4Plus(n) => {
327                         for i in 0..n {
328                             let bits = u32::linear_lift_from_memory(
329                                 cx,
330                                 InterfaceType::U32,
331                                 &bytes[usize::from(i) * 4..][..4],
332                             )?;
333                             push_flags(ty, &mut flags, u32::from(i) * 32, bits);
334                         }
335                     }
336                 }
337                 Val::Flags(flags)
338             }
339             InterfaceType::Future(_) => {
340                 HostFuture::<()>::linear_lift_from_memory(cx, ty, bytes)?.into_val()
341             }
342             InterfaceType::Stream(_) => {
343                 HostStream::<()>::linear_lift_from_memory(cx, ty, bytes)?.into_val()
344             }
345             InterfaceType::ErrorContext(_) => {
346                 ErrorContext::linear_lift_from_memory(cx, ty, bytes)?.into_val()
347             }
348         })
349     }
350 
351     /// Serialize this value as core Wasm stack values.
352     pub(crate) fn lower<T>(
353         &self,
354         cx: &mut LowerContext<'_, T>,
355         ty: InterfaceType,
356         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
357     ) -> Result<()> {
358         match (ty, self) {
359             (InterfaceType::Bool, Val::Bool(value)) => {
360                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
361             }
362             (InterfaceType::Bool, _) => unexpected(ty, self),
363             (InterfaceType::S8, Val::S8(value)) => {
364                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
365             }
366             (InterfaceType::S8, _) => unexpected(ty, self),
367             (InterfaceType::U8, Val::U8(value)) => {
368                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
369             }
370             (InterfaceType::U8, _) => unexpected(ty, self),
371             (InterfaceType::S16, Val::S16(value)) => {
372                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
373             }
374             (InterfaceType::S16, _) => unexpected(ty, self),
375             (InterfaceType::U16, Val::U16(value)) => {
376                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
377             }
378             (InterfaceType::U16, _) => unexpected(ty, self),
379             (InterfaceType::S32, Val::S32(value)) => {
380                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
381             }
382             (InterfaceType::S32, _) => unexpected(ty, self),
383             (InterfaceType::U32, Val::U32(value)) => {
384                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
385             }
386             (InterfaceType::U32, _) => unexpected(ty, self),
387             (InterfaceType::S64, Val::S64(value)) => {
388                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
389             }
390             (InterfaceType::S64, _) => unexpected(ty, self),
391             (InterfaceType::U64, Val::U64(value)) => {
392                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
393             }
394             (InterfaceType::U64, _) => unexpected(ty, self),
395             (InterfaceType::Float32, Val::Float32(value)) => {
396                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
397             }
398             (InterfaceType::Float32, _) => unexpected(ty, self),
399             (InterfaceType::Float64, Val::Float64(value)) => {
400                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
401             }
402             (InterfaceType::Float64, _) => unexpected(ty, self),
403             (InterfaceType::Char, Val::Char(value)) => {
404                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
405             }
406             (InterfaceType::Char, _) => unexpected(ty, self),
407             // NB: `lower` on `ResourceAny` does its own type-checking, so skip
408             // looking at it here.
409             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
410                 value.linear_lower_to_flat(cx, ty, next_mut(dst))
411             }
412             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
413             (InterfaceType::String, Val::String(value)) => {
414                 let my_dst = &mut MaybeUninit::<[ValRaw; 2]>::uninit();
415                 value.linear_lower_to_flat(cx, ty, my_dst)?;
416                 let my_dst = unsafe { my_dst.assume_init() };
417                 next_mut(dst).write(my_dst[0]);
418                 next_mut(dst).write(my_dst[1]);
419                 Ok(())
420             }
421             (InterfaceType::String, _) => unexpected(ty, self),
422             (InterfaceType::List(ty), Val::List(values)) => {
423                 let ty = &cx.types[ty];
424                 let (ptr, len) = lower_list(cx, ty.element, values)?;
425                 next_mut(dst).write(ValRaw::i64(ptr as i64));
426                 next_mut(dst).write(ValRaw::i64(len as i64));
427                 Ok(())
428             }
429             (InterfaceType::List(_), _) => unexpected(ty, self),
430             (InterfaceType::Record(ty), Val::Record(values)) => {
431                 let ty = &cx.types[ty];
432                 if ty.fields.len() != values.len() {
433                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
434                 }
435                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
436                     if *name != field.name {
437                         bail!("expected field `{}`, got `{name}`", field.name);
438                     }
439                     value.lower(cx, field.ty, dst)?;
440                 }
441                 Ok(())
442             }
443             (InterfaceType::Record(_), _) => unexpected(ty, self),
444             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
445                 let ty = &cx.types[ty];
446                 if ty.types.len() != values.len() {
447                     bail!("expected {} types, got {}", ty.types.len(), values.len());
448                 }
449                 for (value, ty) in values.iter().zip(ty.types.iter()) {
450                     value.lower(cx, *ty, dst)?;
451                 }
452                 Ok(())
453             }
454             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
455             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
456                 GenericVariant::variant(&cx.types[ty], n, v)?.lower(cx, dst)
457             }
458             (InterfaceType::Variant(_), _) => unexpected(ty, self),
459             (InterfaceType::Option(ty), Val::Option(v)) => {
460                 GenericVariant::option(&cx.types[ty], v).lower(cx, dst)
461             }
462             (InterfaceType::Option(_), _) => unexpected(ty, self),
463             (InterfaceType::Result(ty), Val::Result(v)) => {
464                 GenericVariant::result(&cx.types[ty], v)?.lower(cx, dst)
465             }
466             (InterfaceType::Result(_), _) => unexpected(ty, self),
467             (InterfaceType::Enum(ty), Val::Enum(discriminant)) => {
468                 let discriminant = get_enum_discriminant(&cx.types[ty], discriminant)?;
469                 next_mut(dst).write(ValRaw::u32(discriminant));
470                 Ok(())
471             }
472             (InterfaceType::Enum(_), _) => unexpected(ty, self),
473             (InterfaceType::Flags(ty), Val::Flags(value)) => {
474                 let ty = &cx.types[ty];
475                 let storage = flags_to_storage(ty, value)?;
476                 for value in storage {
477                     next_mut(dst).write(ValRaw::u32(value));
478                 }
479                 Ok(())
480             }
481             (InterfaceType::Flags(_), _) => unexpected(ty, self),
482             (InterfaceType::Future(_), Val::Future(FutureAny(rep))) => {
483                 concurrent::lower_future_to_index(*rep, cx, ty)?.linear_lower_to_flat(
484                     cx,
485                     InterfaceType::U32,
486                     next_mut(dst),
487                 )
488             }
489             (InterfaceType::Future(_), _) => unexpected(ty, self),
490             (InterfaceType::Stream(_), Val::Stream(StreamAny(rep))) => {
491                 concurrent::lower_stream_to_index(*rep, cx, ty)?.linear_lower_to_flat(
492                     cx,
493                     InterfaceType::U32,
494                     next_mut(dst),
495                 )
496             }
497             (InterfaceType::Stream(_), _) => unexpected(ty, self),
498             (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
499                 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_flat(
500                     cx,
501                     InterfaceType::U32,
502                     next_mut(dst),
503                 )
504             }
505             (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
506         }
507     }
508 
509     /// Serialize this value to the heap at the specified memory location.
510     pub(crate) fn store<T>(
511         &self,
512         cx: &mut LowerContext<'_, T>,
513         ty: InterfaceType,
514         offset: usize,
515     ) -> Result<()> {
516         debug_assert!(offset % usize::try_from(cx.types.canonical_abi(&ty).align32)? == 0);
517 
518         match (ty, self) {
519             (InterfaceType::Bool, Val::Bool(value)) => value.linear_lower_to_memory(cx, ty, offset),
520             (InterfaceType::Bool, _) => unexpected(ty, self),
521             (InterfaceType::U8, Val::U8(value)) => value.linear_lower_to_memory(cx, ty, offset),
522             (InterfaceType::U8, _) => unexpected(ty, self),
523             (InterfaceType::S8, Val::S8(value)) => value.linear_lower_to_memory(cx, ty, offset),
524             (InterfaceType::S8, _) => unexpected(ty, self),
525             (InterfaceType::U16, Val::U16(value)) => value.linear_lower_to_memory(cx, ty, offset),
526             (InterfaceType::U16, _) => unexpected(ty, self),
527             (InterfaceType::S16, Val::S16(value)) => value.linear_lower_to_memory(cx, ty, offset),
528             (InterfaceType::S16, _) => unexpected(ty, self),
529             (InterfaceType::U32, Val::U32(value)) => value.linear_lower_to_memory(cx, ty, offset),
530             (InterfaceType::U32, _) => unexpected(ty, self),
531             (InterfaceType::S32, Val::S32(value)) => value.linear_lower_to_memory(cx, ty, offset),
532             (InterfaceType::S32, _) => unexpected(ty, self),
533             (InterfaceType::U64, Val::U64(value)) => value.linear_lower_to_memory(cx, ty, offset),
534             (InterfaceType::U64, _) => unexpected(ty, self),
535             (InterfaceType::S64, Val::S64(value)) => value.linear_lower_to_memory(cx, ty, offset),
536             (InterfaceType::S64, _) => unexpected(ty, self),
537             (InterfaceType::Float32, Val::Float32(value)) => {
538                 value.linear_lower_to_memory(cx, ty, offset)
539             }
540             (InterfaceType::Float32, _) => unexpected(ty, self),
541             (InterfaceType::Float64, Val::Float64(value)) => {
542                 value.linear_lower_to_memory(cx, ty, offset)
543             }
544             (InterfaceType::Float64, _) => unexpected(ty, self),
545             (InterfaceType::Char, Val::Char(value)) => value.linear_lower_to_memory(cx, ty, offset),
546             (InterfaceType::Char, _) => unexpected(ty, self),
547             (InterfaceType::String, Val::String(value)) => {
548                 value.linear_lower_to_memory(cx, ty, offset)
549             }
550             (InterfaceType::String, _) => unexpected(ty, self),
551 
552             // NB: resources do type-checking when they lower.
553             (InterfaceType::Borrow(_) | InterfaceType::Own(_), Val::Resource(value)) => {
554                 value.linear_lower_to_memory(cx, ty, offset)
555             }
556             (InterfaceType::Borrow(_) | InterfaceType::Own(_), _) => unexpected(ty, self),
557             (InterfaceType::List(ty), Val::List(values)) => {
558                 let ty = &cx.types[ty];
559                 let (ptr, len) = lower_list(cx, ty.element, values)?;
560                 // FIXME(#4311): needs memory64 handling
561                 *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes();
562                 *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes();
563                 Ok(())
564             }
565             (InterfaceType::List(_), _) => unexpected(ty, self),
566             (InterfaceType::Record(ty), Val::Record(values)) => {
567                 let ty = &cx.types[ty];
568                 if ty.fields.len() != values.len() {
569                     bail!("expected {} fields, got {}", ty.fields.len(), values.len());
570                 }
571                 let mut offset = offset;
572                 for ((name, value), field) in values.iter().zip(ty.fields.iter()) {
573                     if *name != field.name {
574                         bail!("expected field `{}`, got `{name}`", field.name);
575                     }
576                     value.store(
577                         cx,
578                         field.ty,
579                         cx.types
580                             .canonical_abi(&field.ty)
581                             .next_field32_size(&mut offset),
582                     )?;
583                 }
584                 Ok(())
585             }
586             (InterfaceType::Record(_), _) => unexpected(ty, self),
587             (InterfaceType::Tuple(ty), Val::Tuple(values)) => {
588                 let ty = &cx.types[ty];
589                 if ty.types.len() != values.len() {
590                     bail!("expected {} types, got {}", ty.types.len(), values.len());
591                 }
592                 let mut offset = offset;
593                 for (value, ty) in values.iter().zip(ty.types.iter()) {
594                     value.store(
595                         cx,
596                         *ty,
597                         cx.types.canonical_abi(ty).next_field32_size(&mut offset),
598                     )?;
599                 }
600                 Ok(())
601             }
602             (InterfaceType::Tuple(_), _) => unexpected(ty, self),
603 
604             (InterfaceType::Variant(ty), Val::Variant(n, v)) => {
605                 GenericVariant::variant(&cx.types[ty], n, v)?.store(cx, offset)
606             }
607             (InterfaceType::Variant(_), _) => unexpected(ty, self),
608             (InterfaceType::Enum(ty), Val::Enum(v)) => {
609                 GenericVariant::enum_(&cx.types[ty], v)?.store(cx, offset)
610             }
611             (InterfaceType::Enum(_), _) => unexpected(ty, self),
612             (InterfaceType::Option(ty), Val::Option(v)) => {
613                 GenericVariant::option(&cx.types[ty], v).store(cx, offset)
614             }
615             (InterfaceType::Option(_), _) => unexpected(ty, self),
616             (InterfaceType::Result(ty), Val::Result(v)) => {
617                 GenericVariant::result(&cx.types[ty], v)?.store(cx, offset)
618             }
619             (InterfaceType::Result(_), _) => unexpected(ty, self),
620 
621             (InterfaceType::Flags(ty), Val::Flags(flags)) => {
622                 let ty = &cx.types[ty];
623                 let storage = flags_to_storage(ty, flags)?;
624                 match FlagsSize::from_count(ty.names.len()) {
625                     FlagsSize::Size0 => {}
626                     FlagsSize::Size1 => u8::try_from(storage[0]).unwrap().linear_lower_to_memory(
627                         cx,
628                         InterfaceType::U8,
629                         offset,
630                     )?,
631                     FlagsSize::Size2 => u16::try_from(storage[0]).unwrap().linear_lower_to_memory(
632                         cx,
633                         InterfaceType::U16,
634                         offset,
635                     )?,
636                     FlagsSize::Size4Plus(_) => {
637                         let mut offset = offset;
638                         for value in storage {
639                             value.linear_lower_to_memory(cx, InterfaceType::U32, offset)?;
640                             offset += 4;
641                         }
642                     }
643                 }
644                 Ok(())
645             }
646             (InterfaceType::Flags(_), _) => unexpected(ty, self),
647             (InterfaceType::Future(_), Val::Future(FutureAny(rep))) => {
648                 concurrent::lower_future_to_index::<T>(*rep, cx, ty)?.linear_lower_to_memory(
649                     cx,
650                     InterfaceType::U32,
651                     offset,
652                 )
653             }
654             (InterfaceType::Future(_), _) => unexpected(ty, self),
655             (InterfaceType::Stream(_), Val::Stream(StreamAny(rep))) => {
656                 concurrent::lower_stream_to_index::<T>(*rep, cx, ty)?.linear_lower_to_memory(
657                     cx,
658                     InterfaceType::U32,
659                     offset,
660                 )
661             }
662             (InterfaceType::Stream(_), _) => unexpected(ty, self),
663             (InterfaceType::ErrorContext(_), Val::ErrorContext(ErrorContextAny(rep))) => {
664                 concurrent::lower_error_context_to_index(*rep, cx, ty)?.linear_lower_to_memory(
665                     cx,
666                     InterfaceType::U32,
667                     offset,
668                 )
669             }
670             (InterfaceType::ErrorContext(_), _) => unexpected(ty, self),
671         }
672     }
673 
674     pub(crate) fn desc(&self) -> &'static str {
675         match self {
676             Val::Bool(_) => "bool",
677             Val::U8(_) => "u8",
678             Val::S8(_) => "s8",
679             Val::U16(_) => "u16",
680             Val::S16(_) => "s16",
681             Val::U32(_) => "u32",
682             Val::S32(_) => "s32",
683             Val::U64(_) => "u64",
684             Val::S64(_) => "s64",
685             Val::Float32(_) => "f32",
686             Val::Float64(_) => "f64",
687             Val::Char(_) => "char",
688             Val::List(_) => "list",
689             Val::String(_) => "string",
690             Val::Record(_) => "record",
691             Val::Enum(_) => "enum",
692             Val::Variant(..) => "variant",
693             Val::Tuple(_) => "tuple",
694             Val::Option(_) => "option",
695             Val::Result(_) => "result",
696             Val::Resource(_) => "resource",
697             Val::Flags(_) => "flags",
698             Val::Future(_) => "future",
699             Val::Stream(_) => "stream",
700             Val::ErrorContext(_) => "error-context",
701         }
702     }
703 
704     /// Deserialize a [`Val`] from its [`crate::component::wasm_wave`] encoding. Deserialization
705     /// requires a target [`crate::component::Type`].
706     #[cfg(feature = "wave")]
707     pub fn from_wave(ty: &crate::component::Type, s: &str) -> Result<Self> {
708         Ok(wasm_wave::from_str(ty, s)?)
709     }
710 
711     /// Serialize a [`Val`] to its [`crate::component::wasm_wave`] encoding.
712     #[cfg(feature = "wave")]
713     pub fn to_wave(&self) -> Result<String> {
714         Ok(wasm_wave::to_string(self)?)
715     }
716 }
717 
718 impl PartialEq for Val {
719     fn eq(&self, other: &Self) -> bool {
720         match (self, other) {
721             // IEEE 754 equality considers NaN inequal to NaN and negative zero
722             // equal to positive zero, however we do the opposite here, because
723             // this logic is used by testing and fuzzing, which want to know
724             // whether two values are semantically the same, rather than
725             // numerically equal.
726             (Self::Float32(l), Self::Float32(r)) => {
727                 (*l != 0.0 && l == r)
728                     || (*l == 0.0 && l.to_bits() == r.to_bits())
729                     || (l.is_nan() && r.is_nan())
730             }
731             (Self::Float32(_), _) => false,
732             (Self::Float64(l), Self::Float64(r)) => {
733                 (*l != 0.0 && l == r)
734                     || (*l == 0.0 && l.to_bits() == r.to_bits())
735                     || (l.is_nan() && r.is_nan())
736             }
737             (Self::Float64(_), _) => false,
738 
739             (Self::Bool(l), Self::Bool(r)) => l == r,
740             (Self::Bool(_), _) => false,
741             (Self::S8(l), Self::S8(r)) => l == r,
742             (Self::S8(_), _) => false,
743             (Self::U8(l), Self::U8(r)) => l == r,
744             (Self::U8(_), _) => false,
745             (Self::S16(l), Self::S16(r)) => l == r,
746             (Self::S16(_), _) => false,
747             (Self::U16(l), Self::U16(r)) => l == r,
748             (Self::U16(_), _) => false,
749             (Self::S32(l), Self::S32(r)) => l == r,
750             (Self::S32(_), _) => false,
751             (Self::U32(l), Self::U32(r)) => l == r,
752             (Self::U32(_), _) => false,
753             (Self::S64(l), Self::S64(r)) => l == r,
754             (Self::S64(_), _) => false,
755             (Self::U64(l), Self::U64(r)) => l == r,
756             (Self::U64(_), _) => false,
757             (Self::Char(l), Self::Char(r)) => l == r,
758             (Self::Char(_), _) => false,
759             (Self::String(l), Self::String(r)) => l == r,
760             (Self::String(_), _) => false,
761             (Self::List(l), Self::List(r)) => l == r,
762             (Self::List(_), _) => false,
763             (Self::Record(l), Self::Record(r)) => l == r,
764             (Self::Record(_), _) => false,
765             (Self::Tuple(l), Self::Tuple(r)) => l == r,
766             (Self::Tuple(_), _) => false,
767             (Self::Variant(ln, lv), Self::Variant(rn, rv)) => ln == rn && lv == rv,
768             (Self::Variant(..), _) => false,
769             (Self::Enum(l), Self::Enum(r)) => l == r,
770             (Self::Enum(_), _) => false,
771             (Self::Option(l), Self::Option(r)) => l == r,
772             (Self::Option(_), _) => false,
773             (Self::Result(l), Self::Result(r)) => l == r,
774             (Self::Result(_), _) => false,
775             (Self::Flags(l), Self::Flags(r)) => l == r,
776             (Self::Flags(_), _) => false,
777             (Self::Resource(l), Self::Resource(r)) => l == r,
778             (Self::Resource(_), _) => false,
779             (Self::Future(l), Self::Future(r)) => l == r,
780             (Self::Future(_), _) => false,
781             (Self::Stream(l), Self::Stream(r)) => l == r,
782             (Self::Stream(_), _) => false,
783             (Self::ErrorContext(l), Self::ErrorContext(r)) => l == r,
784             (Self::ErrorContext(_), _) => false,
785         }
786     }
787 }
788 
789 impl Eq for Val {}
790 
791 struct GenericVariant<'a> {
792     discriminant: u32,
793     payload: Option<(&'a Val, InterfaceType)>,
794     abi: &'a CanonicalAbiInfo,
795     info: &'a VariantInfo,
796 }
797 
798 impl GenericVariant<'_> {
799     fn result<'a>(
800         ty: &'a TypeResult,
801         r: &'a Result<Option<Box<Val>>, Option<Box<Val>>>,
802     ) -> Result<GenericVariant<'a>> {
803         let (discriminant, payload) = match r {
804             Ok(val) => {
805                 let payload = match (val, ty.ok) {
806                     (Some(val), Some(ty)) => Some((&**val, ty)),
807                     (None, None) => None,
808                     (Some(_), None) => {
809                         bail!("payload provided to `ok` but not expected");
810                     }
811                     (None, Some(_)) => {
812                         bail!("payload expected to `ok` but not provided");
813                     }
814                 };
815                 (0, payload)
816             }
817             Err(val) => {
818                 let payload = match (val, ty.err) {
819                     (Some(val), Some(ty)) => Some((&**val, ty)),
820                     (None, None) => None,
821                     (Some(_), None) => {
822                         bail!("payload provided to `err` but not expected");
823                     }
824                     (None, Some(_)) => {
825                         bail!("payload expected to `err` but not provided");
826                     }
827                 };
828                 (1, payload)
829             }
830         };
831         Ok(GenericVariant {
832             discriminant,
833             payload,
834             abi: &ty.abi,
835             info: &ty.info,
836         })
837     }
838 
839     fn option<'a>(ty: &'a TypeOption, r: &'a Option<Box<Val>>) -> GenericVariant<'a> {
840         let (discriminant, payload) = match r {
841             None => (0, None),
842             Some(val) => (1, Some((&**val, ty.ty))),
843         };
844         GenericVariant {
845             discriminant,
846             payload,
847             abi: &ty.abi,
848             info: &ty.info,
849         }
850     }
851 
852     fn enum_<'a>(ty: &'a TypeEnum, discriminant: &str) -> Result<GenericVariant<'a>> {
853         let discriminant = get_enum_discriminant(ty, discriminant)?;
854 
855         Ok(GenericVariant {
856             discriminant,
857             payload: None,
858             abi: &ty.abi,
859             info: &ty.info,
860         })
861     }
862 
863     fn variant<'a>(
864         ty: &'a TypeVariant,
865         discriminant_name: &str,
866         payload: &'a Option<Box<Val>>,
867     ) -> Result<GenericVariant<'a>> {
868         let (discriminant, payload_ty) = get_variant_discriminant(ty, discriminant_name)?;
869 
870         let payload = match (payload, payload_ty) {
871             (Some(val), Some(ty)) => Some((&**val, *ty)),
872             (None, None) => None,
873             (Some(_), None) => bail!("did not expect a payload for case `{discriminant_name}`"),
874             (None, Some(_)) => bail!("expected a payload for case `{discriminant_name}`"),
875         };
876 
877         Ok(GenericVariant {
878             discriminant,
879             payload,
880             abi: &ty.abi,
881             info: &ty.info,
882         })
883     }
884 
885     fn lower<T>(
886         &self,
887         cx: &mut LowerContext<'_, T>,
888         dst: &mut IterMut<'_, MaybeUninit<ValRaw>>,
889     ) -> Result<()> {
890         next_mut(dst).write(ValRaw::u32(self.discriminant));
891 
892         // For the remaining lowered representation of this variant that
893         // the payload didn't write we write out zeros here to ensure
894         // the entire variant is written.
895         let value_flat = match self.payload {
896             Some((value, ty)) => {
897                 value.lower(cx, ty, dst)?;
898                 cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap()
899             }
900             None => 0,
901         };
902         let variant_flat = self.abi.flat_count(usize::MAX).unwrap();
903         for _ in (1 + value_flat)..variant_flat {
904             next_mut(dst).write(ValRaw::u64(0));
905         }
906         Ok(())
907     }
908 
909     fn store<T>(&self, cx: &mut LowerContext<'_, T>, offset: usize) -> Result<()> {
910         match self.info.size {
911             DiscriminantSize::Size1 => u8::try_from(self.discriminant)
912                 .unwrap()
913                 .linear_lower_to_memory(cx, InterfaceType::U8, offset)?,
914             DiscriminantSize::Size2 => u16::try_from(self.discriminant)
915                 .unwrap()
916                 .linear_lower_to_memory(cx, InterfaceType::U16, offset)?,
917             DiscriminantSize::Size4 => {
918                 self.discriminant
919                     .linear_lower_to_memory(cx, InterfaceType::U32, offset)?
920             }
921         }
922 
923         if let Some((value, ty)) = self.payload {
924             let offset = offset + usize::try_from(self.info.payload_offset32).unwrap();
925             value.store(cx, ty, offset)?;
926         }
927 
928         Ok(())
929     }
930 }
931 
932 fn load_list(cx: &mut LiftContext<'_>, ty: TypeListIndex, ptr: usize, len: usize) -> Result<Val> {
933     let elem = cx.types[ty].element;
934     let abi = cx.types.canonical_abi(&elem);
935     let element_size = usize::try_from(abi.size32).unwrap();
936     let element_alignment = abi.align32;
937 
938     match len
939         .checked_mul(element_size)
940         .and_then(|len| ptr.checked_add(len))
941     {
942         Some(n) if n <= cx.memory().len() => {}
943         _ => bail!("list pointer/length out of bounds of memory"),
944     }
945     if ptr % usize::try_from(element_alignment)? != 0 {
946         bail!("list pointer is not aligned")
947     }
948 
949     Ok(Val::List(
950         (0..len)
951             .map(|index| {
952                 Val::load(
953                     cx,
954                     elem,
955                     &cx.memory()[ptr + (index * element_size)..][..element_size],
956                 )
957             })
958             .collect::<Result<_>>()?,
959     ))
960 }
961 
962 fn load_variant(
963     cx: &mut LiftContext<'_>,
964     info: &VariantInfo,
965     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
966     bytes: &[u8],
967 ) -> Result<(u32, Option<Box<Val>>)> {
968     let discriminant = match info.size {
969         DiscriminantSize::Size1 => u32::from(u8::linear_lift_from_memory(
970             cx,
971             InterfaceType::U8,
972             &bytes[..1],
973         )?),
974         DiscriminantSize::Size2 => u32::from(u16::linear_lift_from_memory(
975             cx,
976             InterfaceType::U16,
977             &bytes[..2],
978         )?),
979         DiscriminantSize::Size4 => {
980             u32::linear_lift_from_memory(cx, InterfaceType::U32, &bytes[..4])?
981         }
982     };
983     let case_ty = types.nth(discriminant as usize).ok_or_else(|| {
984         anyhow!(
985             "discriminant {} out of range [0..{})",
986             discriminant,
987             types.len()
988         )
989     })?;
990     let value = match case_ty {
991         Some(case_ty) => {
992             let payload_offset = usize::try_from(info.payload_offset32).unwrap();
993             let case_abi = cx.types.canonical_abi(&case_ty);
994             let case_size = usize::try_from(case_abi.size32).unwrap();
995             Some(Box::new(Val::load(
996                 cx,
997                 case_ty,
998                 &bytes[payload_offset..][..case_size],
999             )?))
1000         }
1001         None => None,
1002     };
1003     Ok((discriminant, value))
1004 }
1005 
1006 fn lift_variant(
1007     cx: &mut LiftContext<'_>,
1008     flatten_count: usize,
1009     mut types: impl ExactSizeIterator<Item = Option<InterfaceType>>,
1010     src: &mut Iter<'_, ValRaw>,
1011 ) -> Result<(u32, Option<Box<Val>>)> {
1012     let len = types.len();
1013     let discriminant = next(src).get_u32();
1014     let ty = types
1015         .nth(discriminant as usize)
1016         .ok_or_else(|| anyhow!("discriminant {} out of range [0..{})", discriminant, len))?;
1017     let (value, value_flat) = match ty {
1018         Some(ty) => (
1019             Some(Box::new(Val::lift(cx, ty, src)?)),
1020             cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(),
1021         ),
1022         None => (None, 0),
1023     };
1024     for _ in (1 + value_flat)..flatten_count {
1025         next(src);
1026     }
1027     Ok((discriminant, value))
1028 }
1029 
1030 /// Lower a list with the specified element type and values.
1031 fn lower_list<T>(
1032     cx: &mut LowerContext<'_, T>,
1033     element_type: InterfaceType,
1034     items: &[Val],
1035 ) -> Result<(usize, usize)> {
1036     let abi = cx.types.canonical_abi(&element_type);
1037     let elt_size = usize::try_from(abi.size32)?;
1038     let elt_align = abi.align32;
1039     let size = items
1040         .len()
1041         .checked_mul(elt_size)
1042         .ok_or_else(|| anyhow::anyhow!("size overflow copying a list"))?;
1043     let ptr = cx.realloc(0, 0, elt_align, size)?;
1044     let mut element_ptr = ptr;
1045     for item in items {
1046         item.store(cx, element_type, element_ptr)?;
1047         element_ptr += elt_size;
1048     }
1049     Ok((ptr, items.len()))
1050 }
1051 
1052 fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) {
1053     while bits > 0 {
1054         if bits & 1 != 0 {
1055             flags.push(ty.names[offset as usize].clone());
1056         }
1057         bits >>= 1;
1058         offset += 1;
1059     }
1060 }
1061 
1062 fn flags_to_storage(ty: &TypeFlags, flags: &[String]) -> Result<Vec<u32>> {
1063     let mut storage = match FlagsSize::from_count(ty.names.len()) {
1064         FlagsSize::Size0 => Vec::new(),
1065         FlagsSize::Size1 | FlagsSize::Size2 => vec![0],
1066         FlagsSize::Size4Plus(n) => vec![0; n.into()],
1067     };
1068 
1069     for flag in flags {
1070         let bit = ty
1071             .names
1072             .get_index_of(flag)
1073             .ok_or_else(|| anyhow::anyhow!("unknown flag: `{flag}`"))?;
1074         storage[bit / 32] |= 1 << (bit % 32);
1075     }
1076     Ok(storage)
1077 }
1078 
1079 fn get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result<u32> {
1080     ty.names
1081         .get_index_of(n)
1082         .ok_or_else(|| anyhow::anyhow!("enum variant name `{n}` is not valid"))
1083         .map(|i| i.try_into().unwrap())
1084 }
1085 
1086 fn get_variant_discriminant<'a>(
1087     ty: &'a TypeVariant,
1088     name: &str,
1089 ) -> Result<(u32, &'a Option<InterfaceType>)> {
1090     let (i, _, ty) = ty
1091         .cases
1092         .get_full(name)
1093         .ok_or_else(|| anyhow::anyhow!("unknown variant case: `{name}`"))?;
1094     Ok((i.try_into().unwrap(), ty))
1095 }
1096 
1097 fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw {
1098     src.next().unwrap()
1099 }
1100 
1101 fn next_mut<'a>(dst: &mut IterMut<'a, MaybeUninit<ValRaw>>) -> &'a mut MaybeUninit<ValRaw> {
1102     dst.next().unwrap()
1103 }
1104 
1105 #[cold]
1106 fn unexpected<T>(ty: InterfaceType, val: &Val) -> Result<T> {
1107     bail!(
1108         "type mismatch: expected {}, found {}",
1109         desc(&ty),
1110         val.desc()
1111     )
1112 }
1113 
1114 /// Represents a component model `future`.
1115 ///
1116 /// Note that this type is not usable at this time as its implementation has not
1117 /// been filled out. There are no operations on this and there's additionally no
1118 /// ability to "drop" or deallocate this index. This means that from the
1119 /// perspective of wasm it'll appear that this handle has "leaked" without ever
1120 /// being dropped or read from.
1121 //
1122 // FIXME(#11161) this needs to be filled out implementation-wise
1123 #[derive(Debug, Clone, PartialEq, Eq)]
1124 pub struct FutureAny(pub(crate) u32);
1125 
1126 /// Represents a component model `stream`.
1127 ///
1128 /// Note that this type is not usable at this time as its implementation has not
1129 /// been filled out. There are no operations on this and there's additionally no
1130 /// ability to "drop" or deallocate this index. This means that from the
1131 /// perspective of wasm it'll appear that this handle has "leaked" without ever
1132 /// being dropped or read from.
1133 //
1134 // FIXME(#11161) this needs to be filled out implementation-wise
1135 #[derive(Debug, Clone, PartialEq, Eq)]
1136 pub struct StreamAny(pub(crate) u32);
1137 
1138 /// Represents a component model `error-context`.
1139 ///
1140 /// Note that this type is not usable at this time as its implementation has not
1141 /// been filled out. There are no operations on this and there's additionally no
1142 /// ability to "drop" or deallocate this index.
1143 //
1144 // FIXME(#11161) this needs to be filled out implementation-wise
1145 #[derive(Debug, Clone, PartialEq, Eq)]
1146 pub struct ErrorContextAny(pub(crate) u32);
1147