1use super::component::ExternKind;
4use super::{CanonicalOptions, Concurrency};
5use crate::validator::StringEncoding;
6use crate::validator::names::KebabString;
7use crate::validator::types::{
8 CoreTypeId, EntityType, SnapshotList, TypeAlloc, TypeData, TypeIdentifier, TypeInfo, TypeList,
9 Types, TypesKind, TypesRef, TypesRefKind,
10};
11use crate::{AbstractHeapType, CompositeInnerType, HeapType, RefType, StorageType, prelude::*};
12use crate::{
13 BinaryReaderError, FuncType, MemoryType, PrimitiveValType, Result, TableType, ValType,
14};
15use core::fmt;
16use core::ops::Index;
17use core::sync::atomic::{AtomicUsize, Ordering};
18use core::{
19 borrow::Borrow,
20 hash::{Hash, Hasher},
21 mem,
22};
23
24const MAX_FLAT_FUNC_PARAMS: usize = 16;
29const MAX_FLAT_ASYNC_PARAMS: usize = 4;
32const MAX_FLAT_FUNC_RESULTS: usize = 1;
37
38const MAX_LOWERED_TYPES: usize = MAX_FLAT_FUNC_PARAMS + 1;
40
41pub(crate) struct LoweredTypes {
43 types: [ValType; MAX_LOWERED_TYPES],
44 len: usize,
45 max: usize,
46}
47
48impl LoweredTypes {
49 fn new(max: usize) -> Self {
50 assert!(max <= MAX_LOWERED_TYPES);
51 Self {
52 types: [ValType::I32; MAX_LOWERED_TYPES],
53 len: 0,
54 max,
55 }
56 }
57
58 fn len(&self) -> usize {
59 self.len
60 }
61
62 fn maxed(&self) -> bool {
63 self.len == self.max
64 }
65
66 fn get_mut(&mut self, index: usize) -> Option<&mut ValType> {
67 if index < self.len {
68 Some(&mut self.types[index])
69 } else {
70 None
71 }
72 }
73
74 #[track_caller]
75 fn assert_push(&mut self, ty: ValType) {
76 assert!(self.try_push(ty));
77 }
78
79 #[must_use = "value is not actually pushed when maxed"]
80 fn try_push(&mut self, ty: ValType) -> bool {
81 if self.maxed() {
82 return false;
83 }
84
85 self.types[self.len] = ty;
86 self.len += 1;
87 true
88 }
89
90 fn clear(&mut self) {
91 self.len = 0;
92 }
93
94 pub fn as_slice(&self) -> &[ValType] {
95 &self.types[..self.len]
96 }
97
98 pub fn iter(&self) -> impl Iterator<Item = ValType> + '_ {
99 self.as_slice().iter().copied()
100 }
101}
102
103impl fmt::Debug for LoweredTypes {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 self.as_slice().fmt(f)
106 }
107}
108
109#[derive(Debug)]
112struct LoweredSignature {
113 params: LoweredTypes,
114 results: LoweredTypes,
115}
116
117impl LoweredSignature {
118 pub(crate) fn into_func_type(self) -> FuncType {
119 FuncType::new(
120 self.params.as_slice().iter().copied(),
121 self.results.as_slice().iter().copied(),
122 )
123 }
124}
125
126impl Default for LoweredSignature {
127 fn default() -> Self {
128 Self {
129 params: LoweredTypes::new(MAX_FLAT_FUNC_PARAMS),
130 results: LoweredTypes::new(MAX_FLAT_FUNC_RESULTS),
131 }
132 }
133}
134
135impl PrimitiveValType {
136 pub(crate) fn lower_gc(
137 &self,
138 types: &TypeList,
139 _abi: Abi,
140 options: &CanonicalOptions,
141 offset: usize,
142 core: ArgOrField,
143 ) -> Result<()> {
144 match (self, core) {
145 (
146 PrimitiveValType::Bool,
147 ArgOrField::Field(StorageType::I8) | ArgOrField::Arg(ValType::I32),
148 ) => Ok(()),
149 (PrimitiveValType::Bool, ArgOrField::Arg(_)) => bail!(
150 offset,
151 "expected to lower component `bool` type to core `i32` type, found `{core}`"
152 ),
153 (PrimitiveValType::Bool, ArgOrField::Field(_)) => bail!(
154 offset,
155 "expected to lower component `bool` type to core `i8` type, found `{core}`"
156 ),
157
158 (
159 PrimitiveValType::S8,
160 ArgOrField::Field(StorageType::I8) | ArgOrField::Arg(ValType::I32),
161 ) => Ok(()),
162 (PrimitiveValType::S8, ArgOrField::Arg(_)) => bail!(
163 offset,
164 "expected to lower component `s8` type to core `i32` type, found `{core}`"
165 ),
166 (PrimitiveValType::S8, ArgOrField::Field(_)) => bail!(
167 offset,
168 "expected to lower component `s8` type to core `i8` type, found `{core}`"
169 ),
170
171 (
172 PrimitiveValType::U8,
173 ArgOrField::Field(StorageType::I8) | ArgOrField::Arg(ValType::I32),
174 ) => Ok(()),
175 (PrimitiveValType::U8, ArgOrField::Arg(_)) => bail!(
176 offset,
177 "expected to lower component `u8` type to core `i32` type, found `{core}`"
178 ),
179 (PrimitiveValType::U8, ArgOrField::Field(_)) => bail!(
180 offset,
181 "expected to lower component `u8` type to core `i8` type, found `{core}`"
182 ),
183
184 (
185 PrimitiveValType::S16,
186 ArgOrField::Field(StorageType::I16) | ArgOrField::Arg(ValType::I32),
187 ) => Ok(()),
188 (PrimitiveValType::S16, ArgOrField::Arg(_)) => bail!(
189 offset,
190 "expected to lower component `s16` type to core `i32` type, found `{core}`"
191 ),
192 (PrimitiveValType::S16, ArgOrField::Field(_)) => bail!(
193 offset,
194 "expected to lower component `s16` type to core `i16` type, found `{core}`"
195 ),
196
197 (
198 PrimitiveValType::U16,
199 ArgOrField::Field(StorageType::I16) | ArgOrField::Arg(ValType::I32),
200 ) => Ok(()),
201 (PrimitiveValType::U16, ArgOrField::Arg(_)) => bail!(
202 offset,
203 "expected to lower component `u16` type to core `i32` type, found `{core}`"
204 ),
205 (PrimitiveValType::U16, ArgOrField::Field(_)) => bail!(
206 offset,
207 "expected to lower component `u16` type to core `i16` type, found `{core}`"
208 ),
209
210 (PrimitiveValType::S32, _) if core.as_val_type() == Some(ValType::I32) => Ok(()),
211 (PrimitiveValType::S32, _) => bail!(
212 offset,
213 "expected to lower component `s32` type to core `i32` type, found `{core}`"
214 ),
215
216 (PrimitiveValType::U32, _) if core.as_val_type() == Some(ValType::I32) => Ok(()),
217 (PrimitiveValType::U32, _) => bail!(
218 offset,
219 "expected to lower component `u32` type to core `i32` type, found `{core}`"
220 ),
221
222 (PrimitiveValType::S64, _) if core.as_val_type() == Some(ValType::I64) => Ok(()),
223 (PrimitiveValType::S64, _) => bail!(
224 offset,
225 "expected to lower component `s64` type to core `i64` type, found `{core}`"
226 ),
227
228 (PrimitiveValType::U64, _) if core.as_val_type() == Some(ValType::I64) => Ok(()),
229 (PrimitiveValType::U64, _) => bail!(
230 offset,
231 "expected to lower component `u64` type to core `i64` type, found `{core}`"
232 ),
233
234 (PrimitiveValType::F32, _) if core.as_val_type() == Some(ValType::F32) => Ok(()),
235 (PrimitiveValType::F32, _) => bail!(
236 offset,
237 "expected to lower component `f32` type to core `f32` type, found `{core}`"
238 ),
239
240 (PrimitiveValType::F64, _) if core.as_val_type() == Some(ValType::F64) => Ok(()),
241 (PrimitiveValType::F64, _) => bail!(
242 offset,
243 "expected to lower component `f64` type to core `f64` type, found `{core}`"
244 ),
245
246 (PrimitiveValType::Char, _) if core.as_val_type() == Some(ValType::I32) => Ok(()),
247 (PrimitiveValType::Char, _) => bail!(
248 offset,
249 "expected to lower component `char` type to core `i32` type, found `{core}`"
250 ),
251
252 (PrimitiveValType::String, _) => {
253 let type_mismatch_err = || {
254 let expected = match options.string_encoding {
255 StringEncoding::Utf8 | StringEncoding::CompactUtf16 => {
256 "(ref null? (array (mut? i8)))"
257 }
258 StringEncoding::Utf16 => "(ref null? (array (mut? i16)))",
259 };
260 bail!(
261 offset,
262 "expected to lower component `string` type to core `{expected}` \
263 type, found `{core}`"
264 )
265 };
266
267 match core.as_concrete_ref() {
268 Some(id) => match types[id].composite_type.inner {
269 CompositeInnerType::Array(ty) => {
270 match (options.string_encoding, ty.0.element_type) {
271 (
272 StringEncoding::Utf8 | StringEncoding::CompactUtf16,
273 StorageType::I8,
274 )
275 | (StringEncoding::Utf16, StorageType::I16) => Ok(()),
276 _ => type_mismatch_err(),
277 }
278 }
279 _ => type_mismatch_err(),
280 },
281 _ => type_mismatch_err(),
282 }
283 }
284
285 (PrimitiveValType::ErrorContext, _) => {
286 if let Some(r) = core.as_ref_type() {
287 if let HeapType::Abstract {
288 shared: _,
289 ty: AbstractHeapType::Extern,
290 } = r.heap_type()
291 {
292 return Ok(());
293 }
294 }
295 bail!(
296 offset,
297 "expected to lower component `error-context` type into core `(ref null? extern)` type, but \
298 found `{core}`",
299 )
300 }
301 }
302 }
303}
304
305fn push_primitive_wasm_types(ty: &PrimitiveValType, lowered_types: &mut LoweredTypes) -> bool {
306 match ty {
307 PrimitiveValType::Bool
308 | PrimitiveValType::S8
309 | PrimitiveValType::U8
310 | PrimitiveValType::S16
311 | PrimitiveValType::U16
312 | PrimitiveValType::S32
313 | PrimitiveValType::U32
314 | PrimitiveValType::Char
315 | PrimitiveValType::ErrorContext => lowered_types.try_push(ValType::I32),
316 PrimitiveValType::S64 | PrimitiveValType::U64 => lowered_types.try_push(ValType::I64),
317 PrimitiveValType::F32 => lowered_types.try_push(ValType::F32),
318 PrimitiveValType::F64 => lowered_types.try_push(ValType::F64),
319 PrimitiveValType::String => {
320 lowered_types.try_push(ValType::I32) && lowered_types.try_push(ValType::I32)
321 }
322 }
323}
324
325pub trait Aliasable {
327 #[doc(hidden)]
328 fn alias_id(&self) -> u32;
329
330 #[doc(hidden)]
331 fn set_alias_id(&mut self, alias_id: u32);
332}
333
334const NO_ALIAS: u32 = u32::MAX;
341
342macro_rules! define_wrapper_id {
343 (
344 $(#[$outer_attrs:meta])*
345 pub enum $name:ident {
346 $(
347 #[unwrap = $unwrap:ident]
348 $(#[$inner_attrs:meta])*
349 $variant:ident ( $inner:ty ) ,
350 )*
351 }
352 ) => {
353 $(#[$outer_attrs])*
354 pub enum $name {
355 $(
356 $(#[$inner_attrs])*
357 $variant ( $inner ) ,
358 )*
359 }
360
361 $(
362 impl From<$inner> for $name {
363 #[inline]
364 fn from(x: $inner) -> Self {
365 Self::$variant(x)
366 }
367 }
368
369 impl TryFrom<$name> for $inner {
370 type Error = ();
371
372 #[inline]
373 fn try_from(x: $name) -> Result<Self, Self::Error> {
374 match x {
375 $name::$variant(x) => Ok(x),
376 _ => Err(())
377 }
378 }
379 }
380 )*
381
382 impl $name {
383 $(
384 #[doc = "Unwrap a `"]
385 #[doc = stringify!($inner)]
386 #[doc = "` or panic."]
387 #[inline]
388 pub fn $unwrap(self) -> $inner {
389 <$inner>::try_from(self).unwrap()
390 }
391 )*
392 }
393 };
394}
395
396macro_rules! define_transitive_conversions {
397 (
398 $(
399 $outer:ty,
400 $middle:ty,
401 $inner:ty,
402 $unwrap:ident;
403 )*
404 ) => {
405 $(
406 impl From<$inner> for $outer {
407 #[inline]
408 fn from(x: $inner) -> Self {
409 <$middle>::from(x).into()
410 }
411 }
412
413 impl TryFrom<$outer> for $inner {
414 type Error = ();
415
416 #[inline]
417 fn try_from(x: $outer) -> Result<Self, Self::Error> {
418 let middle = <$middle>::try_from(x)?;
419 <$inner>::try_from(middle)
420 }
421 }
422
423 impl $outer {
424 #[doc = "Unwrap a `"]
425 #[doc = stringify!($inner)]
426 #[doc = "` or panic."]
427 #[inline]
428 pub fn $unwrap(self) -> $inner {
429 <$inner>::try_from(self).unwrap()
430 }
431 }
432 )*
433 };
434}
435
436define_wrapper_id! {
437 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
439 pub enum AnyTypeId {
440 #[unwrap = unwrap_component_core_type]
441 Core(ComponentCoreTypeId),
443
444 #[unwrap = unwrap_component_any_type]
445 Component(ComponentAnyTypeId),
447 }
448}
449
450define_transitive_conversions! {
451 AnyTypeId, ComponentCoreTypeId, CoreTypeId, unwrap_core_type;
452 AnyTypeId, ComponentCoreTypeId, ComponentCoreModuleTypeId, unwrap_component_core_module_type;
453 AnyTypeId, ComponentAnyTypeId, AliasableResourceId, unwrap_aliasable_resource;
454 AnyTypeId, ComponentAnyTypeId, ComponentDefinedTypeId, unwrap_component_defined_type;
455 AnyTypeId, ComponentAnyTypeId, ComponentFuncTypeId, unwrap_component_func_type;
456 AnyTypeId, ComponentAnyTypeId, ComponentInstanceTypeId, unwrap_component_instance_type;
457 AnyTypeId, ComponentAnyTypeId, ComponentTypeId, unwrap_component_type;
458}
459
460impl AnyTypeId {
461 pub fn peel_alias(&self, types: &Types) -> Option<Self> {
464 match *self {
465 Self::Core(id) => id.peel_alias(types).map(Self::Core),
466 Self::Component(id) => types.peel_alias(id).map(Self::Component),
467 }
468 }
469}
470
471define_wrapper_id! {
472 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
474 pub enum ComponentCoreTypeId {
475 #[unwrap = unwrap_sub]
476 Sub(CoreTypeId),
478
479 #[unwrap = unwrap_module]
480 Module(ComponentCoreModuleTypeId),
482 }
483}
484
485impl ComponentCoreTypeId {
486 pub fn peel_alias(&self, types: &Types) -> Option<Self> {
489 match *self {
490 Self::Sub(_) => None,
491 Self::Module(id) => types.peel_alias(id).map(Self::Module),
492 }
493 }
494}
495
496#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
498pub struct AliasableResourceId {
499 id: ResourceId,
500 alias_id: u32,
501}
502
503impl Aliasable for AliasableResourceId {
504 fn alias_id(&self) -> u32 {
505 self.alias_id
506 }
507
508 fn set_alias_id(&mut self, alias_id: u32) {
509 self.alias_id = alias_id;
510 }
511}
512
513impl AliasableResourceId {
514 pub fn with_resource_id(&self, id: ResourceId) -> Self {
517 Self {
518 id,
519 alias_id: self.alias_id,
520 }
521 }
522
523 pub fn resource(&self) -> ResourceId {
525 self.id
526 }
527
528 pub(crate) fn resource_mut(&mut self) -> &mut ResourceId {
529 &mut self.id
530 }
531}
532
533define_wrapper_id! {
534 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
536 pub enum ComponentAnyTypeId {
537 #[unwrap = unwrap_resource]
538 Resource(AliasableResourceId),
540
541 #[unwrap = unwrap_defined]
542 Defined(ComponentDefinedTypeId),
544
545 #[unwrap = unwrap_func]
546 Func(ComponentFuncTypeId),
548
549 #[unwrap = unwrap_instance]
550 Instance(ComponentInstanceTypeId),
552
553 #[unwrap = unwrap_component]
554 Component(ComponentTypeId),
556 }
557}
558
559impl Aliasable for ComponentAnyTypeId {
560 fn alias_id(&self) -> u32 {
561 match self {
562 ComponentAnyTypeId::Resource(x) => x.alias_id(),
563 ComponentAnyTypeId::Defined(x) => x.alias_id(),
564 ComponentAnyTypeId::Func(x) => x.alias_id(),
565 ComponentAnyTypeId::Instance(x) => x.alias_id(),
566 ComponentAnyTypeId::Component(x) => x.alias_id(),
567 }
568 }
569
570 fn set_alias_id(&mut self, alias_id: u32) {
571 match self {
572 ComponentAnyTypeId::Resource(x) => x.set_alias_id(alias_id),
573 ComponentAnyTypeId::Defined(x) => x.set_alias_id(alias_id),
574 ComponentAnyTypeId::Func(x) => x.set_alias_id(alias_id),
575 ComponentAnyTypeId::Instance(x) => x.set_alias_id(alias_id),
576 ComponentAnyTypeId::Component(x) => x.set_alias_id(alias_id),
577 }
578 }
579}
580
581impl ComponentAnyTypeId {
582 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
583 match *self {
584 Self::Resource(_) => TypeInfo::new(),
585 Self::Defined(id) => types[id].type_info(types),
586 Self::Func(id) => types[id].type_info(types),
587 Self::Instance(id) => types[id].type_info(types),
588 Self::Component(id) => types[id].type_info(types),
589 }
590 }
591
592 pub(crate) fn desc(&self) -> &'static str {
593 match self {
594 Self::Resource(_) => "resource",
595 Self::Defined(_) => "defined type",
596 Self::Func(_) => "func",
597 Self::Instance(_) => "instance",
598 Self::Component(_) => "component",
599 }
600 }
601}
602
603macro_rules! define_type_id {
604 ($name:ident $($rest:tt)*) => {
605 super::types::define_type_id!($name $($rest)*);
606
607 impl Aliasable for $name {
608 fn alias_id(&self) -> u32 {
609 NO_ALIAS
610 }
611
612 fn set_alias_id(&mut self, _: u32) {}
613 }
614 }
615}
616
617define_type_id!(
618 ComponentTypeId,
619 ComponentType,
620 component.components,
621 "component"
622);
623
624define_type_id!(
625 ComponentValueTypeId,
626 ComponentValType,
627 component.component_values,
628 "component value"
629);
630
631define_type_id!(
632 ComponentInstanceTypeId,
633 ComponentInstanceType,
634 component.component_instances,
635 "component instance"
636);
637
638define_type_id!(
639 ComponentFuncTypeId,
640 ComponentFuncType,
641 component.component_funcs,
642 "component function"
643);
644
645define_type_id!(
646 ComponentCoreInstanceTypeId,
647 InstanceType,
648 component.core_instances,
649 "component's core instance"
650);
651
652define_type_id!(
653 ComponentCoreModuleTypeId,
654 ModuleType,
655 component.core_modules,
656 "component's core module"
657);
658
659#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
662#[repr(C)]
663pub struct ComponentDefinedTypeId {
664 index: u32,
665 alias_id: u32,
666}
667
668#[test]
669fn assert_defined_type_small() {
670 assert!(core::mem::size_of::<ComponentDefinedTypeId>() <= 8);
671}
672
673impl TypeIdentifier for ComponentDefinedTypeId {
674 type Data = ComponentDefinedType;
675
676 fn from_index(index: u32) -> Self {
677 ComponentDefinedTypeId {
678 index,
679 alias_id: NO_ALIAS,
680 }
681 }
682
683 fn list(types: &TypeList) -> &SnapshotList<Self::Data> {
684 &types.component.component_defined_types
685 }
686
687 fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> {
688 &mut types.component.component_defined_types
689 }
690
691 fn index(&self) -> usize {
692 usize::try_from(self.index).unwrap()
693 }
694}
695
696impl Aliasable for ComponentDefinedTypeId {
697 fn alias_id(&self) -> u32 {
698 self.alias_id
699 }
700
701 fn set_alias_id(&mut self, alias_id: u32) {
702 self.alias_id = alias_id;
703 }
704}
705
706#[derive(Debug, Clone, Copy)]
708pub enum ComponentValType {
709 Primitive(PrimitiveValType),
711 Type(ComponentDefinedTypeId),
713}
714
715impl TypeData for ComponentValType {
716 type Id = ComponentValueTypeId;
717 const IS_CORE_SUB_TYPE: bool = false;
718 fn type_info(&self, types: &TypeList) -> TypeInfo {
719 match self {
720 ComponentValType::Primitive(_) => TypeInfo::new(),
721 ComponentValType::Type(id) => types[*id].type_info(types),
722 }
723 }
724}
725
726impl ComponentValType {
727 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
728 match self {
729 ComponentValType::Primitive(ty) => ty.contains_ptr(),
730 ComponentValType::Type(ty) => types[*ty].contains_ptr(types),
731 }
732 }
733
734 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
735 match self {
736 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
737 Self::Type(id) => types[*id].push_wasm_types(types, lowered_types),
738 }
739 }
740
741 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
742 match self {
743 Self::Primitive(_) => TypeInfo::new(),
744 Self::Type(id) => types[*id].type_info(types),
745 }
746 }
747
748 fn lower_gc(
749 &self,
750 types: &TypeList,
751 abi: Abi,
752 options: &CanonicalOptions,
753 offset: usize,
754 core: ArgOrField,
755 ) -> Result<()> {
756 match self {
757 ComponentValType::Primitive(ty) => ty.lower_gc(types, abi, options, offset, core),
758 ComponentValType::Type(ty) => types[*ty].lower_gc(types, abi, options, offset, core),
759 }
760 }
761}
762
763trait ModuleImportKey {
764 fn module(&self) -> &str;
765 fn name(&self) -> &str;
766}
767
768impl<'a> Borrow<dyn ModuleImportKey + 'a> for (String, String) {
769 fn borrow(&self) -> &(dyn ModuleImportKey + 'a) {
770 self
771 }
772}
773
774impl Hash for dyn ModuleImportKey + '_ {
775 fn hash<H: Hasher>(&self, state: &mut H) {
776 self.module().hash(state);
777 self.name().hash(state);
778 }
779}
780
781impl PartialEq for dyn ModuleImportKey + '_ {
782 fn eq(&self, other: &Self) -> bool {
783 self.module() == other.module() && self.name() == other.name()
784 }
785}
786
787impl Eq for dyn ModuleImportKey + '_ {}
788
789impl Ord for dyn ModuleImportKey + '_ {
790 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
791 match self.module().cmp(other.module()) {
792 core::cmp::Ordering::Equal => (),
793 order => return order,
794 };
795 self.name().cmp(other.name())
796 }
797}
798
799impl PartialOrd for dyn ModuleImportKey + '_ {
800 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
801 Some(self.cmp(other))
802 }
803}
804
805impl ModuleImportKey for (String, String) {
806 fn module(&self) -> &str {
807 &self.0
808 }
809
810 fn name(&self) -> &str {
811 &self.1
812 }
813}
814
815impl ModuleImportKey for (&str, &str) {
816 fn module(&self) -> &str {
817 self.0
818 }
819
820 fn name(&self) -> &str {
821 self.1
822 }
823}
824
825#[derive(Debug, Clone)]
827pub struct ModuleType {
828 pub(crate) info: TypeInfo,
830 pub imports: IndexMap<(String, String), EntityType>,
832 pub exports: IndexMap<String, EntityType>,
834}
835
836impl TypeData for ModuleType {
837 type Id = ComponentCoreModuleTypeId;
838 const IS_CORE_SUB_TYPE: bool = false;
839 fn type_info(&self, _types: &TypeList) -> TypeInfo {
840 self.info
841 }
842}
843
844impl ModuleType {
845 pub fn lookup_import(&self, module: &str, name: &str) -> Option<&EntityType> {
849 self.imports.get(&(module, name) as &dyn ModuleImportKey)
850 }
851}
852
853#[derive(Debug, Clone)]
855pub enum CoreInstanceTypeKind {
856 Instantiated(ComponentCoreModuleTypeId),
858
859 Exports(IndexMap<String, EntityType>),
861}
862
863#[derive(Debug, Clone)]
865pub struct InstanceType {
866 pub(crate) info: TypeInfo,
868 pub kind: CoreInstanceTypeKind,
870}
871
872impl TypeData for InstanceType {
873 type Id = ComponentCoreInstanceTypeId;
874 const IS_CORE_SUB_TYPE: bool = false;
875 fn type_info(&self, _types: &TypeList) -> TypeInfo {
876 self.info
877 }
878}
879
880impl InstanceType {
881 pub fn exports<'a>(&'a self, types: TypesRef<'a>) -> &'a IndexMap<String, EntityType> {
883 self.internal_exports(types.list)
884 }
885
886 pub(crate) fn internal_exports<'a>(
887 &'a self,
888 types: &'a TypeList,
889 ) -> &'a IndexMap<String, EntityType> {
890 match &self.kind {
891 CoreInstanceTypeKind::Instantiated(id) => &types[*id].exports,
892 CoreInstanceTypeKind::Exports(exports) => exports,
893 }
894 }
895}
896
897#[derive(Debug, Clone, Copy)]
899pub enum ComponentEntityType {
900 Module(ComponentCoreModuleTypeId),
902 Func(ComponentFuncTypeId),
904 Value(ComponentValType),
906 Type {
908 referenced: ComponentAnyTypeId,
911 created: ComponentAnyTypeId,
918 },
919 Instance(ComponentInstanceTypeId),
921 Component(ComponentTypeId),
923}
924
925impl ComponentEntityType {
926 pub fn is_subtype_of(a: &Self, at: TypesRef<'_>, b: &Self, bt: TypesRef<'_>) -> bool {
933 assert_eq!(at.id(), bt.id());
934 SubtypeCx::new(at.list, bt.list)
935 .component_entity_type(a, b, 0)
936 .is_ok()
937 }
938
939 pub(crate) fn desc(&self) -> &'static str {
940 match self {
941 Self::Module(_) => "module",
942 Self::Func(_) => "func",
943 Self::Value(_) => "value",
944 Self::Type { .. } => "type",
945 Self::Instance(_) => "instance",
946 Self::Component(_) => "component",
947 }
948 }
949
950 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
951 match self {
952 Self::Module(ty) => types[*ty].type_info(types),
953 Self::Func(ty) => types[*ty].type_info(types),
954 Self::Type { referenced: ty, .. } => ty.info(types),
955 Self::Instance(ty) => types[*ty].type_info(types),
956 Self::Component(ty) => types[*ty].type_info(types),
957 Self::Value(ty) => ty.info(types),
958 }
959 }
960}
961
962#[derive(Debug, Clone)]
964pub struct ComponentType {
965 pub(crate) info: TypeInfo,
967
968 pub imports: IndexMap<String, ComponentEntityType>,
973
974 pub exports: IndexMap<String, ComponentEntityType>,
979
980 pub imported_resources: Vec<(ResourceId, Vec<usize>)>,
996
997 pub defined_resources: Vec<(ResourceId, Vec<usize>)>,
1006
1007 pub explicit_resources: IndexMap<ResourceId, Vec<usize>>,
1016}
1017
1018impl TypeData for ComponentType {
1019 type Id = ComponentTypeId;
1020 const IS_CORE_SUB_TYPE: bool = false;
1021 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1022 self.info
1023 }
1024}
1025
1026#[derive(Debug, Clone)]
1028pub struct ComponentInstanceType {
1029 pub(crate) info: TypeInfo,
1031
1032 pub exports: IndexMap<String, ComponentEntityType>,
1036
1037 pub defined_resources: Vec<ResourceId>,
1070
1071 pub explicit_resources: IndexMap<ResourceId, Vec<usize>>,
1074}
1075
1076impl TypeData for ComponentInstanceType {
1077 type Id = ComponentInstanceTypeId;
1078 const IS_CORE_SUB_TYPE: bool = false;
1079 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1080 self.info
1081 }
1082}
1083
1084#[derive(Debug, Clone)]
1086pub struct ComponentFuncType {
1087 pub(crate) info: TypeInfo,
1089 pub params: Box<[(KebabString, ComponentValType)]>,
1091 pub result: Option<ComponentValType>,
1093}
1094
1095impl TypeData for ComponentFuncType {
1096 type Id = ComponentFuncTypeId;
1097 const IS_CORE_SUB_TYPE: bool = false;
1098 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1099 self.info
1100 }
1101}
1102
1103#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1104pub(crate) enum Abi {
1105 Lift,
1106 Lower,
1107}
1108
1109impl Abi {
1110 fn invert(&self) -> Self {
1111 match self {
1112 Abi::Lift => Abi::Lower,
1113 Abi::Lower => Abi::Lift,
1114 }
1115 }
1116}
1117
1118#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1119pub(crate) enum ArgOrField {
1120 Arg(ValType),
1122 Field(StorageType),
1124}
1125
1126impl From<ValType> for ArgOrField {
1127 fn from(v: ValType) -> Self {
1128 Self::Arg(v)
1129 }
1130}
1131
1132impl From<StorageType> for ArgOrField {
1133 fn from(v: StorageType) -> Self {
1134 Self::Field(v)
1135 }
1136}
1137
1138impl core::fmt::Display for ArgOrField {
1139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1140 match self {
1141 ArgOrField::Arg(ty) => core::fmt::Display::fmt(ty, f),
1142 ArgOrField::Field(ty) => core::fmt::Display::fmt(ty, f),
1143 }
1144 }
1145}
1146
1147impl ArgOrField {
1148 pub(crate) fn as_val_type(self) -> Option<ValType> {
1149 match self {
1150 ArgOrField::Arg(ty) | ArgOrField::Field(StorageType::Val(ty)) => Some(ty),
1151 _ => None,
1152 }
1153 }
1154
1155 pub(crate) fn as_ref_type(self) -> Option<RefType> {
1156 self.as_val_type()?.as_reference_type()
1157 }
1158
1159 pub(crate) fn as_concrete_ref(self) -> Option<CoreTypeId> {
1160 match self.as_ref_type()?.heap_type() {
1161 HeapType::Abstract { .. } => None,
1162 HeapType::Concrete(idx) => {
1163 let id = idx
1164 .as_core_type_id()
1165 .expect("validation only sees core type ids");
1166 Some(id)
1167 }
1168 }
1169 }
1170}
1171
1172pub(crate) enum LoweredFuncType {
1173 New(FuncType),
1174 Existing(CoreTypeId),
1175}
1176
1177impl LoweredFuncType {
1178 pub(crate) fn intern(self, types: &mut TypeAlloc, offset: usize) -> CoreTypeId {
1179 match self {
1180 LoweredFuncType::New(ty) => types.intern_func_type(ty, offset),
1181 LoweredFuncType::Existing(id) => id,
1182 }
1183 }
1184}
1185
1186impl ComponentFuncType {
1187 pub(crate) fn lower(
1190 &self,
1191 types: &TypeList,
1192 options: &CanonicalOptions,
1193 abi: Abi,
1194 offset: usize,
1195 ) -> Result<LoweredFuncType> {
1196 let mut sig = LoweredSignature::default();
1197
1198 if options.gc {
1199 return self.lower_gc(types, abi, options, offset);
1200 }
1201
1202 if abi == Abi::Lower && options.concurrency.is_async() {
1203 sig.params.max = MAX_FLAT_ASYNC_PARAMS;
1204 }
1205
1206 for (_, ty) in self.params.iter() {
1207 match abi {
1214 Abi::Lower => {
1215 options.require_memory_if(offset, || ty.contains_ptr(types))?;
1216 }
1217 Abi::Lift => {
1218 options.require_realloc_if(offset, || ty.contains_ptr(types))?;
1219 }
1220 }
1221
1222 if !ty.push_wasm_types(types, &mut sig.params) {
1223 sig.params.clear();
1227 assert!(sig.params.try_push(ValType::I32));
1228 options.require_memory(offset)?;
1229
1230 if let Abi::Lift = abi {
1232 options.require_realloc(offset)?;
1233 }
1234 break;
1235 }
1236 }
1237
1238 match (abi, options.concurrency) {
1239 (Abi::Lower | Abi::Lift, Concurrency::Sync) => {
1240 if let Some(ty) = &self.result {
1241 options.require_realloc_if(offset, || {
1246 abi == Abi::Lower && ty.contains_ptr(types)
1247 })?;
1248
1249 if !ty.push_wasm_types(types, &mut sig.results) {
1250 sig.results.clear();
1254 options.require_memory(offset)?;
1255 match abi {
1256 Abi::Lower => {
1257 sig.params.max = MAX_LOWERED_TYPES;
1258 assert!(sig.params.try_push(ValType::I32));
1259 }
1260 Abi::Lift => {
1261 assert!(sig.results.try_push(ValType::I32));
1262 }
1263 }
1264 }
1265 }
1266 }
1267 (Abi::Lower, Concurrency::Async { callback: _ }) => {
1268 if self.result.is_some() {
1269 sig.params.max = MAX_LOWERED_TYPES;
1270 sig.params.assert_push(ValType::I32);
1271 options.require_memory(offset)?;
1272 }
1273 sig.results.assert_push(ValType::I32);
1274 }
1275 (Abi::Lift, Concurrency::Async { callback }) => {
1276 if callback.is_some() {
1277 sig.results.assert_push(ValType::I32);
1278 }
1279 }
1280 }
1281
1282 Ok(LoweredFuncType::New(sig.into_func_type()))
1283 }
1284
1285 fn lower_gc(
1286 &self,
1287 types: &TypeList,
1288 abi: Abi,
1289 options: &CanonicalOptions,
1290 offset: usize,
1291 ) -> Result<LoweredFuncType> {
1292 let core_type_id = options.core_type.unwrap();
1293 let core_func_ty = types[core_type_id].unwrap_func();
1294
1295 ensure!(
1296 core_func_ty.params().len() == self.params.len(),
1297 offset,
1298 "declared `core-type` has {} parameters, but component function has {} parameters",
1299 core_func_ty.params().len(),
1300 self.params.len(),
1301 );
1302 for (core, (_name, comp)) in core_func_ty.params().iter().zip(self.params.iter()) {
1303 comp.lower_gc(types, abi.invert(), options, offset, (*core).into())?;
1304 }
1305
1306 ensure!(
1307 core_func_ty.results().len() == usize::from(self.result.is_some()),
1308 offset,
1309 "declared `core-type` has {} results, but component function has {} results",
1310 core_func_ty.results().len(),
1311 usize::from(self.result.is_some()),
1312 );
1313 if let Some(result) = self.result {
1314 result.lower_gc(
1315 types,
1316 abi,
1317 options,
1318 offset,
1319 core_func_ty.results()[0].into(),
1320 )?;
1321 }
1322
1323 Ok(LoweredFuncType::Existing(core_type_id))
1324 }
1325}
1326
1327#[derive(Debug, Clone)]
1329pub struct VariantCase {
1330 pub ty: Option<ComponentValType>,
1332 pub refines: Option<KebabString>,
1334}
1335
1336#[derive(Debug, Clone)]
1338pub struct RecordType {
1339 pub(crate) info: TypeInfo,
1341 pub fields: IndexMap<KebabString, ComponentValType>,
1343}
1344
1345impl RecordType {
1346 fn lower_gc(
1347 &self,
1348 types: &TypeList,
1349 abi: Abi,
1350 options: &CanonicalOptions,
1351 offset: usize,
1352 core: ArgOrField,
1353 ) -> Result<()> {
1354 lower_gc_product_type(
1355 self.fields.values(),
1356 types,
1357 abi,
1358 options,
1359 offset,
1360 core,
1361 "record",
1362 )
1363 }
1364}
1365
1366#[derive(Debug, Clone)]
1368pub struct VariantType {
1369 pub(crate) info: TypeInfo,
1371 pub cases: IndexMap<KebabString, VariantCase>,
1373}
1374
1375impl VariantType {
1376 fn lower_gc(
1377 &self,
1378 types: &TypeList,
1379 abi: Abi,
1380 options: &CanonicalOptions,
1381 offset: usize,
1382 core: ArgOrField,
1383 ) -> Result<()> {
1384 lower_gc_sum_type(types, abi, options, offset, core, "variant")
1385 }
1386}
1387
1388fn lower_gc_sum_type(
1391 types: &TypeList,
1392 _abi: Abi,
1393 _options: &CanonicalOptions,
1394 offset: usize,
1395 core: ArgOrField,
1396 kind: &str,
1397) -> Result<()> {
1398 if let Some(id) = core.as_concrete_ref() {
1399 if let CompositeInnerType::Struct(ty) = &types[id].composite_type.inner {
1400 if ty.fields.is_empty() {
1401 return Ok(());
1402 }
1403 }
1404 }
1405
1406 bail!(
1407 offset,
1408 "expected to lower component `{kind}` type to core `(ref null? (struct))`, \
1409 but found `{core}`",
1410 )
1411}
1412
1413#[derive(Debug, Clone)]
1415pub struct TupleType {
1416 pub(crate) info: TypeInfo,
1418 pub types: Box<[ComponentValType]>,
1420}
1421
1422impl TupleType {
1423 fn lower_gc(
1424 &self,
1425 types: &TypeList,
1426 abi: Abi,
1427 options: &CanonicalOptions,
1428 offset: usize,
1429 core: ArgOrField,
1430 ) -> Result<()> {
1431 lower_gc_product_type(
1432 self.types.iter(),
1433 types,
1434 abi,
1435 options,
1436 offset,
1437 core,
1438 "tuple",
1439 )
1440 }
1441}
1442
1443#[derive(Debug, Clone)]
1445pub enum ComponentDefinedType {
1446 Primitive(PrimitiveValType),
1448 Record(RecordType),
1450 Variant(VariantType),
1452 List(ComponentValType),
1454 FixedSizeList(ComponentValType, u32),
1456 Tuple(TupleType),
1458 Flags(IndexSet<KebabString>),
1460 Enum(IndexSet<KebabString>),
1462 Option(ComponentValType),
1464 Result {
1466 ok: Option<ComponentValType>,
1468 err: Option<ComponentValType>,
1470 },
1471 Own(AliasableResourceId),
1473 Borrow(AliasableResourceId),
1475 Future(Option<ComponentValType>),
1477 Stream(Option<ComponentValType>),
1479}
1480
1481impl TypeData for ComponentDefinedType {
1482 type Id = ComponentDefinedTypeId;
1483 const IS_CORE_SUB_TYPE: bool = false;
1484 fn type_info(&self, types: &TypeList) -> TypeInfo {
1485 match self {
1486 Self::Primitive(_)
1487 | Self::Flags(_)
1488 | Self::Enum(_)
1489 | Self::Own(_)
1490 | Self::Future(_)
1491 | Self::Stream(_) => TypeInfo::new(),
1492 Self::Borrow(_) => TypeInfo::borrow(),
1493 Self::Record(r) => r.info,
1494 Self::Variant(v) => v.info,
1495 Self::Tuple(t) => t.info,
1496 Self::List(ty) | Self::FixedSizeList(ty, _) | Self::Option(ty) => ty.info(types),
1497 Self::Result { ok, err } => {
1498 let default = TypeInfo::new();
1499 let mut info = ok.map(|ty| ty.type_info(types)).unwrap_or(default);
1500 info.combine(err.map(|ty| ty.type_info(types)).unwrap_or(default), 0)
1501 .unwrap();
1502 info
1503 }
1504 }
1505 }
1506}
1507
1508impl ComponentDefinedType {
1509 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
1510 match self {
1511 Self::Primitive(ty) => ty.contains_ptr(),
1512 Self::Record(r) => r.fields.values().any(|ty| ty.contains_ptr(types)),
1513 Self::Variant(v) => v
1514 .cases
1515 .values()
1516 .any(|case| case.ty.map(|ty| ty.contains_ptr(types)).unwrap_or(false)),
1517 Self::List(_) => true,
1518 Self::Tuple(t) => t.types.iter().any(|ty| ty.contains_ptr(types)),
1519 Self::Flags(_)
1520 | Self::Enum(_)
1521 | Self::Own(_)
1522 | Self::Borrow(_)
1523 | Self::Future(_)
1524 | Self::Stream(_) => false,
1525 Self::Option(ty) | Self::FixedSizeList(ty, _) => ty.contains_ptr(types),
1526 Self::Result { ok, err } => {
1527 ok.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1528 || err.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1529 }
1530 }
1531 }
1532
1533 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1534 match self {
1535 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1536 Self::Record(r) => r
1537 .fields
1538 .iter()
1539 .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1540 Self::Variant(v) => Self::push_variant_wasm_types(
1541 v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1542 types,
1543 lowered_types,
1544 ),
1545 Self::List(_) => {
1546 lowered_types.try_push(ValType::I32) && lowered_types.try_push(ValType::I32)
1547 }
1548 Self::FixedSizeList(ty, length) => {
1549 (0..*length).all(|_n| ty.push_wasm_types(types, lowered_types))
1550 }
1551 Self::Tuple(t) => t
1552 .types
1553 .iter()
1554 .all(|ty| ty.push_wasm_types(types, lowered_types)),
1555 Self::Flags(names) => {
1556 (0..(names.len() + 31) / 32).all(|_| lowered_types.try_push(ValType::I32))
1557 }
1558 Self::Enum(_) | Self::Own(_) | Self::Borrow(_) | Self::Future(_) | Self::Stream(_) => {
1559 lowered_types.try_push(ValType::I32)
1560 }
1561 Self::Option(ty) => {
1562 Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1563 }
1564 Self::Result { ok, err } => {
1565 Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1566 }
1567 }
1568 }
1569
1570 fn push_variant_wasm_types<'a>(
1571 cases: impl Iterator<Item = &'a ComponentValType>,
1572 types: &TypeList,
1573 lowered_types: &mut LoweredTypes,
1574 ) -> bool {
1575 if !lowered_types.try_push(ValType::I32) {
1577 return false;
1578 }
1579
1580 let start = lowered_types.len();
1581
1582 for ty in cases {
1583 let mut temp = LoweredTypes::new(lowered_types.max);
1584
1585 if !ty.push_wasm_types(types, &mut temp) {
1586 return false;
1587 }
1588
1589 for (i, ty) in temp.iter().enumerate() {
1590 match lowered_types.get_mut(start + i) {
1591 Some(prev) => *prev = Self::join_types(*prev, ty),
1592 None => {
1593 if !lowered_types.try_push(ty) {
1594 return false;
1595 }
1596 }
1597 }
1598 }
1599 }
1600
1601 true
1602 }
1603
1604 fn join_types(a: ValType, b: ValType) -> ValType {
1605 use ValType::*;
1606
1607 match (a, b) {
1608 (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1609 (I32, F32) | (F32, I32) => I32,
1610 (_, I64 | F64) | (I64 | F64, _) => I64,
1611 _ => panic!("unexpected wasm type for canonical ABI"),
1612 }
1613 }
1614
1615 fn desc(&self) -> &'static str {
1616 match self {
1617 ComponentDefinedType::Record(_) => "record",
1618 ComponentDefinedType::Primitive(_) => "primitive",
1619 ComponentDefinedType::Variant(_) => "variant",
1620 ComponentDefinedType::Tuple(_) => "tuple",
1621 ComponentDefinedType::Enum(_) => "enum",
1622 ComponentDefinedType::Flags(_) => "flags",
1623 ComponentDefinedType::Option(_) => "option",
1624 ComponentDefinedType::List(_) => "list",
1625 ComponentDefinedType::FixedSizeList(_, _) => "fixed size list",
1626 ComponentDefinedType::Result { .. } => "result",
1627 ComponentDefinedType::Own(_) => "own",
1628 ComponentDefinedType::Borrow(_) => "borrow",
1629 ComponentDefinedType::Future(_) => "future",
1630 ComponentDefinedType::Stream(_) => "stream",
1631 }
1632 }
1633
1634 fn lower_gc(
1635 &self,
1636 types: &TypeList,
1637 abi: Abi,
1638 options: &CanonicalOptions,
1639 offset: usize,
1640 core: ArgOrField,
1641 ) -> Result<()> {
1642 match self {
1643 ComponentDefinedType::Primitive(ty) => ty.lower_gc(types, abi, options, offset, core),
1644
1645 ComponentDefinedType::Record(ty) => ty.lower_gc(types, abi, options, offset, core),
1646
1647 ComponentDefinedType::Variant(ty) => ty.lower_gc(types, abi, options, offset, core),
1648
1649 ComponentDefinedType::List(ty) | ComponentDefinedType::FixedSizeList(ty, _) => {
1650 let id = match core.as_concrete_ref() {
1651 Some(id) => id,
1652 None => bail!(
1653 offset,
1654 "expected to lower component `list` type into `(ref null? (array ...))`, but \
1655 found `{core}`",
1656 ),
1657 };
1658 let array_ty = match types[id].composite_type.inner {
1659 CompositeInnerType::Array(ty) => ty,
1660 _ => bail!(
1661 offset,
1662 "expected to lower component `list` type into `(ref null? (array ...))`, but \
1663 found `{core}`",
1664 ),
1665 };
1666 ty.lower_gc(types, abi, options, offset, array_ty.0.element_type.into())
1667 }
1668
1669 ComponentDefinedType::Tuple(ty) => ty.lower_gc(types, abi, options, offset, core),
1670
1671 ComponentDefinedType::Flags(flags) => {
1672 assert!(flags.len() <= 32, "required by validation");
1673 if core.as_val_type() == Some(ValType::I32) {
1674 Ok(())
1675 } else {
1676 bail!(
1677 offset,
1678 "expected to lower component `flags` type into core `i32` type, but \
1679 found `{core}`",
1680 )
1681 }
1682 }
1683
1684 ComponentDefinedType::Enum(_) => {
1685 if core.as_val_type() == Some(ValType::I32) {
1686 Ok(())
1687 } else {
1688 bail!(
1689 offset,
1690 "expected to lower component `enum` type into core `i32` type, but \
1691 found `{core}`",
1692 )
1693 }
1694 }
1695
1696 ComponentDefinedType::Option(_) => {
1697 lower_gc_sum_type(types, abi, options, offset, core, "option")
1698 }
1699
1700 ComponentDefinedType::Result { .. } => {
1701 lower_gc_sum_type(types, abi, options, offset, core, "result")
1702 }
1703
1704 ComponentDefinedType::Own(_)
1705 | ComponentDefinedType::Borrow(_)
1706 | ComponentDefinedType::Future(_)
1707 | ComponentDefinedType::Stream(_) => {
1708 if let Some(r) = core.as_ref_type() {
1709 if let HeapType::Abstract {
1710 shared: _,
1711 ty: AbstractHeapType::Extern,
1712 } = r.heap_type()
1713 {
1714 return Ok(());
1715 }
1716 }
1717 bail!(
1718 offset,
1719 "expected to lower component `{}` type into core `(ref null? extern)` type, but \
1720 found `{core}`",
1721 self.desc()
1722 )
1723 }
1724 }
1725 }
1726}
1727
1728fn lower_gc_product_type<'a, I>(
1731 fields: I,
1732 types: &TypeList,
1733 abi: Abi,
1734 options: &CanonicalOptions,
1735 offset: usize,
1736 core: ArgOrField,
1737 kind: &str,
1738) -> core::result::Result<(), BinaryReaderError>
1739where
1740 I: IntoIterator<Item = &'a ComponentValType>,
1741 I::IntoIter: ExactSizeIterator,
1742{
1743 let fields = fields.into_iter();
1744 let fields_len = fields.len();
1745
1746 if let Some(id) = core.as_concrete_ref() {
1747 if let CompositeInnerType::Struct(ty) = &types[id].composite_type.inner {
1748 ensure!(
1749 ty.fields.len() == fields_len,
1750 offset,
1751 "core `struct` has {} fields, but component `{kind}` has {fields_len} fields",
1752 ty.fields.len(),
1753 );
1754 for (core, comp) in ty.fields.iter().zip(fields) {
1755 comp.lower_gc(types, abi, options, offset, core.element_type.into())?;
1756 }
1757 return Ok(());
1758 }
1759 }
1760
1761 bail!(
1762 offset,
1763 "expected to lower component `{kind}` type to core `(ref null? (struct ...))`, \
1764 but found `{core}`",
1765 )
1766}
1767
1768#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
1771#[repr(packed(4))] pub struct ResourceId {
1773 globally_unique_id: usize,
1783
1784 contextually_unique_id: u32,
1793}
1794
1795impl<'a> TypesRef<'a> {
1796 pub fn core_type_at_in_component(&self, index: u32) -> ComponentCoreTypeId {
1807 match &self.kind {
1808 TypesRefKind::Module(_) => panic!("use `component_type_at_in_module` instead"),
1809 TypesRefKind::Component(component) => component.core_types[index as usize],
1810 }
1811 }
1812
1813 pub fn core_type_count_in_component(&self) -> u32 {
1818 match &self.kind {
1819 TypesRefKind::Module(_) => 0,
1820 TypesRefKind::Component(component) => component.core_types.len() as u32,
1821 }
1822 }
1823
1824 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1831 match &self.kind {
1832 TypesRefKind::Module(_) => panic!("not a component"),
1833 TypesRefKind::Component(component) => component.types[index as usize],
1834 }
1835 }
1836
1837 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1844 match self.component_any_type_at(index) {
1845 ComponentAnyTypeId::Component(id) => id,
1846 _ => panic!("not a component type"),
1847 }
1848 }
1849
1850 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1857 match self.component_any_type_at(index) {
1858 ComponentAnyTypeId::Defined(id) => id,
1859 _ => panic!("not a defined type"),
1860 }
1861 }
1862
1863 pub fn component_type_count(&self) -> u32 {
1865 match &self.kind {
1866 TypesRefKind::Module(_module) => 0,
1867 TypesRefKind::Component(component) => component.types.len() as u32,
1868 }
1869 }
1870
1871 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
1878 match &self.kind {
1879 TypesRefKind::Module(_) => panic!("not a component"),
1880 TypesRefKind::Component(component) => component.funcs[index as usize],
1881 }
1882 }
1883
1884 pub fn component_function_count(&self) -> u32 {
1886 match &self.kind {
1887 TypesRefKind::Module(_module) => 0,
1888 TypesRefKind::Component(component) => component.funcs.len() as u32,
1889 }
1890 }
1891
1892 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
1899 match &self.kind {
1900 TypesRefKind::Module(_) => panic!("not a component"),
1901 TypesRefKind::Component(component) => component.core_modules[index as usize],
1902 }
1903 }
1904
1905 pub fn module_count(&self) -> u32 {
1907 match &self.kind {
1908 TypesRefKind::Module(_module) => 0,
1909 TypesRefKind::Component(component) => component.core_modules.len() as u32,
1910 }
1911 }
1912
1913 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
1920 match &self.kind {
1921 TypesRefKind::Module(_) => panic!("not a component"),
1922 TypesRefKind::Component(component) => component.core_instances[index as usize],
1923 }
1924 }
1925
1926 pub fn core_instance_count(&self) -> u32 {
1928 match &self.kind {
1929 TypesRefKind::Module(_module) => 0,
1930 TypesRefKind::Component(component) => component.core_instances.len() as u32,
1931 }
1932 }
1933
1934 pub fn component_at(&self, index: u32) -> ComponentTypeId {
1941 match &self.kind {
1942 TypesRefKind::Module(_) => panic!("not a component"),
1943 TypesRefKind::Component(component) => component.components[index as usize],
1944 }
1945 }
1946
1947 pub fn component_count(&self) -> u32 {
1949 match &self.kind {
1950 TypesRefKind::Module(_module) => 0,
1951 TypesRefKind::Component(component) => component.components.len() as u32,
1952 }
1953 }
1954
1955 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
1962 match &self.kind {
1963 TypesRefKind::Module(_) => panic!("not a component"),
1964 TypesRefKind::Component(component) => component.instances[index as usize],
1965 }
1966 }
1967
1968 pub fn component_instance_count(&self) -> u32 {
1970 match &self.kind {
1971 TypesRefKind::Module(_module) => 0,
1972 TypesRefKind::Component(component) => component.instances.len() as u32,
1973 }
1974 }
1975
1976 pub fn value_at(&self, index: u32) -> ComponentValType {
1983 match &self.kind {
1984 TypesRefKind::Module(_) => panic!("not a component"),
1985 TypesRefKind::Component(component) => component.values[index as usize].0,
1986 }
1987 }
1988
1989 pub fn value_count(&self) -> u32 {
1991 match &self.kind {
1992 TypesRefKind::Module(_module) => 0,
1993 TypesRefKind::Component(component) => component.values.len() as u32,
1994 }
1995 }
1996
1997 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
1999 match &self.kind {
2000 TypesRefKind::Module(_) => None,
2001 TypesRefKind::Component(component) => Some(*component.imports.get(name)?),
2002 }
2003 }
2004
2005 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
2007 match &self.kind {
2008 TypesRefKind::Module(_) => None,
2009 TypesRefKind::Component(component) => Some(*component.exports.get(name)?),
2010 }
2011 }
2012
2013 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2017 where
2018 T: Aliasable,
2019 {
2020 self.list.peel_alias(ty)
2021 }
2022}
2023
2024impl Types {
2025 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
2034 self.as_ref().component_any_type_at(index)
2035 }
2036
2037 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
2043 self.as_ref().component_type_at(index)
2044 }
2045
2046 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
2053 self.as_ref().component_defined_type_at(index)
2054 }
2055
2056 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
2063 self.as_ref().component_function_at(index)
2064 }
2065
2066 pub fn component_function_count(&self) -> u32 {
2068 self.as_ref().component_function_count()
2069 }
2070
2071 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
2078 self.as_ref().module_at(index)
2079 }
2080
2081 pub fn module_count(&self) -> usize {
2083 match &self.kind {
2084 TypesKind::Module(_) => 0,
2085 TypesKind::Component(component) => component.core_modules.len(),
2086 }
2087 }
2088
2089 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
2096 self.as_ref().core_instance_at(index)
2097 }
2098
2099 pub fn core_instance_count(&self) -> usize {
2101 match &self.kind {
2102 TypesKind::Module(_) => 0,
2103 TypesKind::Component(component) => component.core_instances.len(),
2104 }
2105 }
2106
2107 pub fn component_at(&self, index: u32) -> ComponentTypeId {
2114 self.as_ref().component_at(index)
2115 }
2116
2117 pub fn component_count(&self) -> usize {
2119 match &self.kind {
2120 TypesKind::Module(_) => 0,
2121 TypesKind::Component(component) => component.components.len(),
2122 }
2123 }
2124
2125 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
2132 self.as_ref().component_instance_at(index)
2133 }
2134
2135 pub fn component_instance_count(&self) -> usize {
2137 match &self.kind {
2138 TypesKind::Module(_) => 0,
2139 TypesKind::Component(component) => component.instances.len(),
2140 }
2141 }
2142
2143 pub fn value_at(&self, index: u32) -> ComponentValType {
2150 self.as_ref().value_at(index)
2151 }
2152
2153 pub fn value_count(&self) -> usize {
2155 match &self.kind {
2156 TypesKind::Module(_) => 0,
2157 TypesKind::Component(component) => component.values.len(),
2158 }
2159 }
2160
2161 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
2163 self.as_ref().component_entity_type_of_import(name)
2164 }
2165
2166 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
2168 self.as_ref().component_entity_type_of_export(name)
2169 }
2170
2171 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2175 where
2176 T: Aliasable,
2177 {
2178 self.list.peel_alias(ty)
2179 }
2180}
2181
2182#[derive(Debug, Default)]
2184pub(crate) struct ComponentTypeList {
2185 alias_mappings: Map<u32, u32>,
2187 alias_counter: u32,
2189 alias_snapshots: Vec<TypeListAliasSnapshot>,
2191
2192 components: SnapshotList<ComponentType>,
2194 component_defined_types: SnapshotList<ComponentDefinedType>,
2195 component_values: SnapshotList<ComponentValType>,
2196 component_instances: SnapshotList<ComponentInstanceType>,
2197 component_funcs: SnapshotList<ComponentFuncType>,
2198 core_modules: SnapshotList<ModuleType>,
2199 core_instances: SnapshotList<InstanceType>,
2200}
2201
2202#[derive(Clone, Debug)]
2203struct TypeListAliasSnapshot {
2204 alias_counter: u32,
2206
2207 alias_mappings: Map<u32, u32>,
2209}
2210
2211struct TypeListCheckpoint {
2212 core_types: usize,
2213 components: usize,
2214 component_defined_types: usize,
2215 component_values: usize,
2216 component_instances: usize,
2217 component_funcs: usize,
2218 core_modules: usize,
2219 core_instances: usize,
2220 core_type_to_rec_group: usize,
2221 core_type_to_supertype: usize,
2222 core_type_to_depth: usize,
2223 rec_group_elements: usize,
2224 canonical_rec_groups: usize,
2225}
2226
2227impl TypeList {
2228 fn checkpoint(&self) -> TypeListCheckpoint {
2229 let TypeList {
2230 component:
2231 ComponentTypeList {
2232 alias_mappings: _,
2233 alias_counter: _,
2234 alias_snapshots: _,
2235 components,
2236 component_defined_types,
2237 component_values,
2238 component_instances,
2239 component_funcs,
2240 core_modules,
2241 core_instances,
2242 },
2243 core_types,
2244 core_type_to_rec_group,
2245 core_type_to_supertype,
2246 core_type_to_depth,
2247 rec_group_elements,
2248 canonical_rec_groups,
2249 } = self;
2250
2251 TypeListCheckpoint {
2252 core_types: core_types.len(),
2253 components: components.len(),
2254 component_defined_types: component_defined_types.len(),
2255 component_values: component_values.len(),
2256 component_instances: component_instances.len(),
2257 component_funcs: component_funcs.len(),
2258 core_modules: core_modules.len(),
2259 core_instances: core_instances.len(),
2260 core_type_to_rec_group: core_type_to_rec_group.len(),
2261 core_type_to_supertype: core_type_to_supertype.len(),
2262 core_type_to_depth: core_type_to_depth.as_ref().map(|m| m.len()).unwrap_or(0),
2263 rec_group_elements: rec_group_elements.len(),
2264 canonical_rec_groups: canonical_rec_groups.as_ref().map(|m| m.len()).unwrap_or(0),
2265 }
2266 }
2267
2268 fn reset_to_checkpoint(&mut self, checkpoint: TypeListCheckpoint) {
2269 let TypeList {
2270 component:
2271 ComponentTypeList {
2272 alias_mappings: _,
2273 alias_counter: _,
2274 alias_snapshots: _,
2275 components,
2276 component_defined_types,
2277 component_values,
2278 component_instances,
2279 component_funcs,
2280 core_modules,
2281 core_instances,
2282 },
2283 core_types,
2284 core_type_to_rec_group,
2285 core_type_to_supertype,
2286 core_type_to_depth,
2287 rec_group_elements,
2288 canonical_rec_groups,
2289 } = self;
2290
2291 core_types.truncate(checkpoint.core_types);
2292 components.truncate(checkpoint.components);
2293 component_defined_types.truncate(checkpoint.component_defined_types);
2294 component_values.truncate(checkpoint.component_values);
2295 component_instances.truncate(checkpoint.component_instances);
2296 component_funcs.truncate(checkpoint.component_funcs);
2297 core_modules.truncate(checkpoint.core_modules);
2298 core_instances.truncate(checkpoint.core_instances);
2299 core_type_to_rec_group.truncate(checkpoint.core_type_to_rec_group);
2300 core_type_to_supertype.truncate(checkpoint.core_type_to_supertype);
2301 rec_group_elements.truncate(checkpoint.rec_group_elements);
2302
2303 if let Some(core_type_to_depth) = core_type_to_depth {
2304 assert_eq!(
2305 core_type_to_depth.len(),
2306 checkpoint.core_type_to_depth,
2307 "checkpointing does not support resetting `core_type_to_depth` (it would require a \
2308 proper immutable and persistent hash map) so adding new groups is disallowed"
2309 );
2310 }
2311 if let Some(canonical_rec_groups) = canonical_rec_groups {
2312 assert_eq!(
2313 canonical_rec_groups.len(),
2314 checkpoint.canonical_rec_groups,
2315 "checkpointing does not support resetting `canonical_rec_groups` (it would require a \
2316 proper immutable and persistent hash map) so adding new groups is disallowed"
2317 );
2318 }
2319 }
2320
2321 pub fn with_unique<T>(&mut self, mut ty: T) -> T
2323 where
2324 T: Aliasable,
2325 {
2326 self.component
2327 .alias_mappings
2328 .insert(self.component.alias_counter, ty.alias_id());
2329 ty.set_alias_id(self.component.alias_counter);
2330 self.component.alias_counter += 1;
2331 ty
2332 }
2333
2334 pub fn peel_alias<T>(&self, mut ty: T) -> Option<T>
2338 where
2339 T: Aliasable,
2340 {
2341 let alias_id = ty.alias_id();
2342
2343 let i = match self
2350 .component
2351 .alias_snapshots
2352 .binary_search_by_key(&alias_id, |snapshot| snapshot.alias_counter)
2353 {
2354 Ok(_) => unreachable!(),
2355 Err(i) => i,
2356 };
2357
2358 ty.set_alias_id(match self.component.alias_snapshots.get(i) {
2362 Some(snapshot) => *snapshot.alias_mappings.get(&alias_id)?,
2363 None => *self.component.alias_mappings.get(&alias_id)?,
2364 });
2365 Some(ty)
2366 }
2367}
2368
2369impl ComponentTypeList {
2370 pub fn commit(&mut self) -> ComponentTypeList {
2371 let alias_counter = self.alias_counter;
2375 self.alias_counter += 1;
2376
2377 self.alias_snapshots.push(TypeListAliasSnapshot {
2378 alias_counter,
2379 alias_mappings: mem::take(&mut self.alias_mappings),
2380 });
2381
2382 ComponentTypeList {
2383 alias_mappings: Map::default(),
2384 alias_counter: self.alias_counter,
2385 alias_snapshots: self.alias_snapshots.clone(),
2386 components: self.components.commit(),
2387 component_defined_types: self.component_defined_types.commit(),
2388 component_values: self.component_values.commit(),
2389 component_instances: self.component_instances.commit(),
2390 component_funcs: self.component_funcs.commit(),
2391 core_modules: self.core_modules.commit(),
2392 core_instances: self.core_instances.commit(),
2393 }
2394 }
2395}
2396
2397pub(crate) struct ComponentTypeAlloc {
2398 globally_unique_id: usize,
2401
2402 next_resource_id: u32,
2405}
2406
2407impl Default for ComponentTypeAlloc {
2408 fn default() -> ComponentTypeAlloc {
2409 static NEXT_GLOBAL_ID: AtomicUsize = AtomicUsize::new(0);
2410 ComponentTypeAlloc {
2411 globally_unique_id: {
2412 let id = NEXT_GLOBAL_ID.fetch_add(1, Ordering::Relaxed);
2413 if id > usize::MAX - 10_000 {
2414 NEXT_GLOBAL_ID.store(usize::MAX - 10_000, Ordering::Relaxed);
2415 panic!("overflow on the global id counter");
2416 }
2417 id
2418 },
2419 next_resource_id: 0,
2420 }
2421 }
2422}
2423
2424impl TypeAlloc {
2425 pub fn alloc_resource_id(&mut self) -> AliasableResourceId {
2429 let contextually_unique_id = self.component_alloc.next_resource_id;
2430 self.component_alloc.next_resource_id = self
2431 .component_alloc
2432 .next_resource_id
2433 .checked_add(1)
2434 .unwrap();
2435 AliasableResourceId {
2436 id: ResourceId {
2437 globally_unique_id: self.component_alloc.globally_unique_id,
2438 contextually_unique_id,
2439 },
2440 alias_id: NO_ALIAS,
2441 }
2442 }
2443
2444 pub fn free_variables_any_type_id(
2451 &self,
2452 id: ComponentAnyTypeId,
2453 set: &mut IndexSet<ResourceId>,
2454 ) {
2455 match id {
2456 ComponentAnyTypeId::Resource(r) => {
2457 set.insert(r.resource());
2458 }
2459 ComponentAnyTypeId::Defined(id) => {
2460 self.free_variables_component_defined_type_id(id, set)
2461 }
2462 ComponentAnyTypeId::Func(id) => self.free_variables_component_func_type_id(id, set),
2463 ComponentAnyTypeId::Instance(id) => {
2464 self.free_variables_component_instance_type_id(id, set)
2465 }
2466 ComponentAnyTypeId::Component(id) => self.free_variables_component_type_id(id, set),
2467 }
2468 }
2469
2470 pub fn free_variables_component_defined_type_id(
2471 &self,
2472 id: ComponentDefinedTypeId,
2473 set: &mut IndexSet<ResourceId>,
2474 ) {
2475 match &self[id] {
2476 ComponentDefinedType::Primitive(_)
2477 | ComponentDefinedType::Flags(_)
2478 | ComponentDefinedType::Enum(_) => {}
2479 ComponentDefinedType::Record(r) => {
2480 for ty in r.fields.values() {
2481 self.free_variables_valtype(ty, set);
2482 }
2483 }
2484 ComponentDefinedType::Tuple(r) => {
2485 for ty in r.types.iter() {
2486 self.free_variables_valtype(ty, set);
2487 }
2488 }
2489 ComponentDefinedType::Variant(r) => {
2490 for ty in r.cases.values() {
2491 if let Some(ty) = &ty.ty {
2492 self.free_variables_valtype(ty, set);
2493 }
2494 }
2495 }
2496 ComponentDefinedType::List(ty)
2497 | ComponentDefinedType::FixedSizeList(ty, _)
2498 | ComponentDefinedType::Option(ty) => {
2499 self.free_variables_valtype(ty, set);
2500 }
2501 ComponentDefinedType::Result { ok, err } => {
2502 if let Some(ok) = ok {
2503 self.free_variables_valtype(ok, set);
2504 }
2505 if let Some(err) = err {
2506 self.free_variables_valtype(err, set);
2507 }
2508 }
2509 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2510 set.insert(id.resource());
2511 }
2512 ComponentDefinedType::Future(ty) => {
2513 if let Some(ty) = ty {
2514 self.free_variables_valtype(ty, set);
2515 }
2516 }
2517 ComponentDefinedType::Stream(ty) => {
2518 if let Some(ty) = ty {
2519 self.free_variables_valtype(ty, set);
2520 }
2521 }
2522 }
2523 }
2524
2525 pub fn free_variables_component_type_id(
2526 &self,
2527 id: ComponentTypeId,
2528 set: &mut IndexSet<ResourceId>,
2529 ) {
2530 let i = &self[id];
2531 for ty in i.imports.values().chain(i.exports.values()) {
2542 self.free_variables_component_entity(ty, set);
2543 }
2544 for (id, _path) in i.imported_resources.iter().chain(&i.defined_resources) {
2545 set.swap_remove(id);
2546 }
2547 }
2548
2549 pub fn free_variables_component_instance_type_id(
2550 &self,
2551 id: ComponentInstanceTypeId,
2552 set: &mut IndexSet<ResourceId>,
2553 ) {
2554 let i = &self[id];
2555 for ty in i.exports.values() {
2559 self.free_variables_component_entity(ty, set);
2560 }
2561 for id in i.defined_resources.iter() {
2562 set.swap_remove(id);
2563 }
2564 }
2565
2566 pub fn free_variables_component_func_type_id(
2567 &self,
2568 id: ComponentFuncTypeId,
2569 set: &mut IndexSet<ResourceId>,
2570 ) {
2571 let i = &self[id];
2572 for ty in i.params.iter().map(|(_, ty)| ty).chain(&i.result) {
2573 self.free_variables_valtype(ty, set);
2574 }
2575 }
2576
2577 pub fn free_variables_component_entity(
2579 &self,
2580 ty: &ComponentEntityType,
2581 set: &mut IndexSet<ResourceId>,
2582 ) {
2583 match ty {
2584 ComponentEntityType::Module(_) => {}
2585 ComponentEntityType::Func(id) => self.free_variables_component_func_type_id(*id, set),
2586 ComponentEntityType::Instance(id) => {
2587 self.free_variables_component_instance_type_id(*id, set)
2588 }
2589 ComponentEntityType::Component(id) => self.free_variables_component_type_id(*id, set),
2590 ComponentEntityType::Type { created, .. } => {
2591 self.free_variables_any_type_id(*created, set);
2592 }
2593 ComponentEntityType::Value(ty) => self.free_variables_valtype(ty, set),
2594 }
2595 }
2596
2597 fn free_variables_valtype(&self, ty: &ComponentValType, set: &mut IndexSet<ResourceId>) {
2599 match ty {
2600 ComponentValType::Primitive(_) => {}
2601 ComponentValType::Type(id) => self.free_variables_component_defined_type_id(*id, set),
2602 }
2603 }
2604
2605 pub(crate) fn type_named_type_id(
2610 &self,
2611 id: ComponentDefinedTypeId,
2612 set: &Set<ComponentAnyTypeId>,
2613 ) -> bool {
2614 let ty = &self[id];
2615 match ty {
2616 ComponentDefinedType::Primitive(_) => true,
2618
2619 ComponentDefinedType::Flags(_)
2622 | ComponentDefinedType::Enum(_)
2623 | ComponentDefinedType::Record(_)
2624 | ComponentDefinedType::Variant(_) => set.contains(&ComponentAnyTypeId::from(id)),
2625
2626 ComponentDefinedType::Tuple(r) => {
2629 r.types.iter().all(|t| self.type_named_valtype(t, set))
2630 }
2631 ComponentDefinedType::Result { ok, err } => {
2632 ok.as_ref()
2633 .map(|t| self.type_named_valtype(t, set))
2634 .unwrap_or(true)
2635 && err
2636 .as_ref()
2637 .map(|t| self.type_named_valtype(t, set))
2638 .unwrap_or(true)
2639 }
2640 ComponentDefinedType::List(ty)
2641 | ComponentDefinedType::FixedSizeList(ty, _)
2642 | ComponentDefinedType::Option(ty) => self.type_named_valtype(ty, set),
2643
2644 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2647 set.contains(&ComponentAnyTypeId::from(*id))
2648 }
2649
2650 ComponentDefinedType::Future(ty) => ty
2651 .as_ref()
2652 .map(|ty| self.type_named_valtype(ty, set))
2653 .unwrap_or(true),
2654
2655 ComponentDefinedType::Stream(ty) => ty
2656 .as_ref()
2657 .map(|ty| self.type_named_valtype(ty, set))
2658 .unwrap_or(true),
2659 }
2660 }
2661
2662 pub(crate) fn type_named_valtype(
2663 &self,
2664 ty: &ComponentValType,
2665 set: &Set<ComponentAnyTypeId>,
2666 ) -> bool {
2667 match ty {
2668 ComponentValType::Primitive(_) => true,
2669 ComponentValType::Type(id) => self.type_named_type_id(*id, set),
2670 }
2671 }
2672}
2673
2674pub trait Remap
2680where
2681 Self: Index<ComponentTypeId, Output = ComponentType>,
2682 Self: Index<ComponentDefinedTypeId, Output = ComponentDefinedType>,
2683 Self: Index<ComponentInstanceTypeId, Output = ComponentInstanceType>,
2684 Self: Index<ComponentFuncTypeId, Output = ComponentFuncType>,
2685{
2686 #[doc(hidden)]
2691 fn push_ty<T>(&mut self, ty: T) -> T::Id
2692 where
2693 T: TypeData;
2694
2695 fn map_map(
2698 tmp: &mut IndexMap<ResourceId, Vec<usize>>,
2699 any_changed: &mut bool,
2700 map: &Remapping,
2701 ) {
2702 for (id, path) in mem::take(tmp) {
2703 let id = match map.resources.get(&id) {
2704 Some(id) => {
2705 *any_changed = true;
2706 *id
2707 }
2708 None => id,
2709 };
2710 tmp.insert(id, path);
2711 }
2712 }
2713
2714 fn insert_if_any_changed<T>(
2718 &mut self,
2719 map: &mut Remapping,
2720 any_changed: bool,
2721 id: &mut T::Id,
2722 ty: T,
2723 ) -> bool
2724 where
2725 T: TypeData,
2726 T::Id: Into<ComponentAnyTypeId>,
2727 {
2728 let new = if any_changed { self.push_ty(ty) } else { *id };
2729 map.types.insert((*id).into(), new.into());
2730 let changed = *id != new;
2731 *id = new;
2732 changed
2733 }
2734
2735 fn remap_component_any_type_id(
2739 &mut self,
2740 id: &mut ComponentAnyTypeId,
2741 map: &mut Remapping,
2742 ) -> bool {
2743 match id {
2744 ComponentAnyTypeId::Resource(id) => self.remap_resource_id(id, map),
2745 ComponentAnyTypeId::Defined(id) => self.remap_component_defined_type_id(id, map),
2746 ComponentAnyTypeId::Func(id) => self.remap_component_func_type_id(id, map),
2747 ComponentAnyTypeId::Instance(id) => self.remap_component_instance_type_id(id, map),
2748 ComponentAnyTypeId::Component(id) => self.remap_component_type_id(id, map),
2749 }
2750 }
2751
2752 fn remap_resource_id(&mut self, id: &mut AliasableResourceId, map: &Remapping) -> bool {
2755 if let Some(changed) = map.remap_id(id) {
2756 return changed;
2757 }
2758
2759 match map.resources.get(&id.resource()) {
2760 None => false,
2761 Some(new_id) => {
2762 *id.resource_mut() = *new_id;
2763 true
2764 }
2765 }
2766 }
2767
2768 fn remap_component_type_id(&mut self, id: &mut ComponentTypeId, map: &mut Remapping) -> bool {
2772 if let Some(changed) = map.remap_id(id) {
2773 return changed;
2774 }
2775
2776 let mut any_changed = false;
2777 let mut ty = self[*id].clone();
2778 for ty in ty.imports.values_mut().chain(ty.exports.values_mut()) {
2779 any_changed |= self.remap_component_entity(ty, map);
2780 }
2781 for (id, _) in ty
2782 .imported_resources
2783 .iter_mut()
2784 .chain(&mut ty.defined_resources)
2785 {
2786 if let Some(new) = map.resources.get(id) {
2787 *id = *new;
2788 any_changed = true;
2789 }
2790 }
2791 Self::map_map(&mut ty.explicit_resources, &mut any_changed, map);
2792 self.insert_if_any_changed(map, any_changed, id, ty)
2793 }
2794
2795 fn remap_component_defined_type_id(
2799 &mut self,
2800 id: &mut ComponentDefinedTypeId,
2801 map: &mut Remapping,
2802 ) -> bool {
2803 if let Some(changed) = map.remap_id(id) {
2804 return changed;
2805 }
2806
2807 let mut any_changed = false;
2808 let mut tmp = self[*id].clone();
2809 match &mut tmp {
2810 ComponentDefinedType::Primitive(_)
2811 | ComponentDefinedType::Flags(_)
2812 | ComponentDefinedType::Enum(_) => {}
2813 ComponentDefinedType::Record(r) => {
2814 for ty in r.fields.values_mut() {
2815 any_changed |= self.remap_valtype(ty, map);
2816 }
2817 }
2818 ComponentDefinedType::Tuple(r) => {
2819 for ty in r.types.iter_mut() {
2820 any_changed |= self.remap_valtype(ty, map);
2821 }
2822 }
2823 ComponentDefinedType::Variant(r) => {
2824 for ty in r.cases.values_mut() {
2825 if let Some(ty) = &mut ty.ty {
2826 any_changed |= self.remap_valtype(ty, map);
2827 }
2828 }
2829 }
2830 ComponentDefinedType::List(ty)
2831 | ComponentDefinedType::FixedSizeList(ty, _)
2832 | ComponentDefinedType::Option(ty) => {
2833 any_changed |= self.remap_valtype(ty, map);
2834 }
2835 ComponentDefinedType::Result { ok, err } => {
2836 if let Some(ok) = ok {
2837 any_changed |= self.remap_valtype(ok, map);
2838 }
2839 if let Some(err) = err {
2840 any_changed |= self.remap_valtype(err, map);
2841 }
2842 }
2843 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2844 any_changed |= self.remap_resource_id(id, map);
2845 }
2846 ComponentDefinedType::Future(ty) | ComponentDefinedType::Stream(ty) => {
2847 if let Some(ty) = ty {
2848 any_changed |= self.remap_valtype(ty, map);
2849 }
2850 }
2851 }
2852 self.insert_if_any_changed(map, any_changed, id, tmp)
2853 }
2854
2855 fn remap_component_instance_type_id(
2859 &mut self,
2860 id: &mut ComponentInstanceTypeId,
2861 map: &mut Remapping,
2862 ) -> bool {
2863 if let Some(changed) = map.remap_id(id) {
2864 return changed;
2865 }
2866
2867 let mut any_changed = false;
2868 let mut tmp = self[*id].clone();
2869 for ty in tmp.exports.values_mut() {
2870 any_changed |= self.remap_component_entity(ty, map);
2871 }
2872 for id in tmp.defined_resources.iter_mut() {
2873 if let Some(new) = map.resources.get(id) {
2874 *id = *new;
2875 any_changed = true;
2876 }
2877 }
2878 Self::map_map(&mut tmp.explicit_resources, &mut any_changed, map);
2879 self.insert_if_any_changed(map, any_changed, id, tmp)
2880 }
2881
2882 fn remap_component_func_type_id(
2886 &mut self,
2887 id: &mut ComponentFuncTypeId,
2888 map: &mut Remapping,
2889 ) -> bool {
2890 if let Some(changed) = map.remap_id(id) {
2891 return changed;
2892 }
2893
2894 let mut any_changed = false;
2895 let mut tmp = self[*id].clone();
2896 for ty in tmp
2897 .params
2898 .iter_mut()
2899 .map(|(_, ty)| ty)
2900 .chain(&mut tmp.result)
2901 {
2902 any_changed |= self.remap_valtype(ty, map);
2903 }
2904 self.insert_if_any_changed(map, any_changed, id, tmp)
2905 }
2906
2907 fn remap_component_entity(
2909 &mut self,
2910 ty: &mut ComponentEntityType,
2911 map: &mut Remapping,
2912 ) -> bool {
2913 match ty {
2914 ComponentEntityType::Module(_) => {
2915 false
2917 }
2918 ComponentEntityType::Func(id) => self.remap_component_func_type_id(id, map),
2919 ComponentEntityType::Instance(id) => self.remap_component_instance_type_id(id, map),
2920 ComponentEntityType::Component(id) => self.remap_component_type_id(id, map),
2921 ComponentEntityType::Type {
2922 referenced,
2923 created,
2924 } => {
2925 let mut changed = self.remap_component_any_type_id(referenced, map);
2926 if *referenced == *created {
2927 *created = *referenced;
2928 } else {
2929 changed |= self.remap_component_any_type_id(created, map);
2930 }
2931 changed
2932 }
2933 ComponentEntityType::Value(ty) => self.remap_valtype(ty, map),
2934 }
2935 }
2936
2937 fn remap_valtype(&mut self, ty: &mut ComponentValType, map: &mut Remapping) -> bool {
2939 match ty {
2940 ComponentValType::Primitive(_) => false,
2941 ComponentValType::Type(id) => self.remap_component_defined_type_id(id, map),
2942 }
2943 }
2944}
2945
2946#[derive(Debug, Default)]
2949pub struct Remapping {
2950 pub(crate) resources: Map<ResourceId, ResourceId>,
2952
2953 types: Map<ComponentAnyTypeId, ComponentAnyTypeId>,
2957}
2958
2959impl Remap for TypeAlloc {
2960 fn push_ty<T>(&mut self, ty: T) -> T::Id
2961 where
2962 T: TypeData,
2963 {
2964 <TypeList>::push(self, ty)
2965 }
2966}
2967
2968impl Remapping {
2969 pub fn add(&mut self, old: ResourceId, new: ResourceId) {
2971 self.resources.insert(old, new);
2972 }
2973
2974 pub fn reset_type_cache(&mut self) {
2976 self.types.clear()
2977 }
2978
2979 fn remap_id<T>(&self, id: &mut T) -> Option<bool>
2980 where
2981 T: Copy + Into<ComponentAnyTypeId> + TryFrom<ComponentAnyTypeId>,
2982 T::Error: core::fmt::Debug,
2983 {
2984 let old: ComponentAnyTypeId = (*id).into();
2985 let new = self.types.get(&old)?;
2986 if *new == old {
2987 Some(false)
2988 } else {
2989 *id = T::try_from(*new).expect("should never remap across different kinds");
2990 Some(true)
2991 }
2992 }
2993}
2994
2995pub struct SubtypeCx<'a> {
3014 pub a: SubtypeArena<'a>,
3016 pub b: SubtypeArena<'a>,
3018}
3019
3020macro_rules! limits_match {
3021 ($a:expr, $b:expr) => {{
3022 let a = $a;
3023 let b = $b;
3024 a.initial >= b.initial
3025 && match b.maximum {
3026 Some(b_max) => match a.maximum {
3027 Some(a_max) => a_max <= b_max,
3028 None => false,
3029 },
3030 None => true,
3031 }
3032 }};
3033}
3034
3035impl<'a> SubtypeCx<'a> {
3036 pub fn new_with_refs(a: TypesRef<'a>, b: TypesRef<'a>) -> SubtypeCx<'a> {
3043 assert_eq!(a.id(), b.id());
3044 Self::new(a.list, b.list)
3045 }
3046
3047 pub(crate) fn new(a: &'a TypeList, b: &'a TypeList) -> SubtypeCx<'a> {
3048 SubtypeCx {
3049 a: SubtypeArena::new(a),
3050 b: SubtypeArena::new(b),
3051 }
3052 }
3053
3054 pub fn swap(&mut self) {
3056 mem::swap(&mut self.a, &mut self.b);
3057 }
3058
3059 fn with_checkpoint<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
3065 let a = self.a.list.checkpoint();
3066 let b = self.b.list.checkpoint();
3067 let result = f(self);
3068 self.a.list.reset_to_checkpoint(a);
3069 self.b.list.reset_to_checkpoint(b);
3070 result
3071 }
3072
3073 pub fn component_entity_type(
3077 &mut self,
3078 a: &ComponentEntityType,
3079 b: &ComponentEntityType,
3080 offset: usize,
3081 ) -> Result<()> {
3082 use ComponentEntityType::*;
3083
3084 match (a, b) {
3085 (Module(a), Module(b)) => self.module_type(*a, *b, offset),
3086 (Module(_), b) => bail!(offset, "expected {}, found module", b.desc()),
3087
3088 (Func(a), Func(b)) => self.component_func_type(*a, *b, offset),
3089 (Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3090
3091 (Value(a), Value(b)) => self.component_val_type(a, b, offset),
3092 (Value(_), b) => bail!(offset, "expected {}, found value", b.desc()),
3093
3094 (Type { referenced: a, .. }, Type { referenced: b, .. }) => {
3095 self.component_any_type_id(*a, *b, offset)
3096 }
3097 (Type { .. }, b) => bail!(offset, "expected {}, found type", b.desc()),
3098
3099 (Instance(a), Instance(b)) => self.component_instance_type(*a, *b, offset),
3100 (Instance(_), b) => bail!(offset, "expected {}, found instance", b.desc()),
3101
3102 (Component(a), Component(b)) => self.component_type(*a, *b, offset),
3103 (Component(_), b) => bail!(offset, "expected {}, found component", b.desc()),
3104 }
3105 }
3106
3107 pub fn component_type(
3111 &mut self,
3112 a: ComponentTypeId,
3113 b: ComponentTypeId,
3114 offset: usize,
3115 ) -> Result<()> {
3116 let b_imports = self.b[b]
3170 .imports
3171 .iter()
3172 .map(|(name, ty)| (name.clone(), *ty))
3173 .collect();
3174 self.swap();
3175 let mut import_mapping =
3176 self.open_instance_type(&b_imports, a, ExternKind::Import, offset)?;
3177 self.swap();
3178 self.with_checkpoint(|this| {
3179 let mut a_exports = this.a[a]
3180 .exports
3181 .iter()
3182 .map(|(name, ty)| (name.clone(), *ty))
3183 .collect::<IndexMap<_, _>>();
3184 for ty in a_exports.values_mut() {
3185 this.a.remap_component_entity(ty, &mut import_mapping);
3186 }
3187 this.open_instance_type(&a_exports, b, ExternKind::Export, offset)?;
3188 Ok(())
3189 })
3190 }
3191
3192 pub fn component_instance_type(
3196 &mut self,
3197 a_id: ComponentInstanceTypeId,
3198 b_id: ComponentInstanceTypeId,
3199 offset: usize,
3200 ) -> Result<()> {
3201 let a = &self.a[a_id];
3206 let b = &self.b[b_id];
3207
3208 let mut exports = Vec::with_capacity(b.exports.len());
3209 for (k, b) in b.exports.iter() {
3210 match a.exports.get(k) {
3211 Some(a) => exports.push((*a, *b)),
3212 None => bail!(offset, "missing expected export `{k}`"),
3213 }
3214 }
3215 for (i, (a, b)) in exports.iter().enumerate() {
3216 let err = match self.component_entity_type(a, b, offset) {
3217 Ok(()) => continue,
3218 Err(e) => e,
3219 };
3220 let (name, _) = self.b[b_id].exports.get_index(i).unwrap();
3223 return Err(err.with_context(|| format!("type mismatch in instance export `{name}`")));
3224 }
3225 Ok(())
3226 }
3227
3228 pub fn component_func_type(
3232 &mut self,
3233 a: ComponentFuncTypeId,
3234 b: ComponentFuncTypeId,
3235 offset: usize,
3236 ) -> Result<()> {
3237 let a = &self.a[a];
3238 let b = &self.b[b];
3239
3240 if a.params.len() != b.params.len() {
3271 bail!(
3272 offset,
3273 "expected {} parameters, found {}",
3274 b.params.len(),
3275 a.params.len(),
3276 );
3277 }
3278 for ((an, a), (bn, b)) in a.params.iter().zip(b.params.iter()) {
3279 if an != bn {
3280 bail!(offset, "expected parameter named `{bn}`, found `{an}`");
3281 }
3282 self.component_val_type(a, b, offset)
3283 .with_context(|| format!("type mismatch in function parameter `{an}`"))?;
3284 }
3285
3286 match (&a.result, &b.result) {
3287 (Some(a), Some(b)) => self
3288 .component_val_type(a, b, offset)
3289 .with_context(|| "type mismatch with result type")?,
3290 (None, None) => {}
3291
3292 (Some(_), None) => bail!(offset, "expected a result, found none"),
3293 (None, Some(_)) => bail!(offset, "expected no result, found one"),
3294 }
3295 Ok(())
3296 }
3297
3298 pub fn module_type(
3302 &mut self,
3303 a: ComponentCoreModuleTypeId,
3304 b: ComponentCoreModuleTypeId,
3305 offset: usize,
3306 ) -> Result<()> {
3307 self.swap();
3313 let a_imports = &self.b[a].imports;
3314 let b_imports = &self.a[b].imports;
3315 for (k, a) in a_imports {
3316 match b_imports.get(k) {
3317 Some(b) => self
3318 .entity_type(b, a, offset)
3319 .with_context(|| format!("type mismatch in import `{}::{}`", k.0, k.1))?,
3320 None => bail!(offset, "missing expected import `{}::{}`", k.0, k.1),
3321 }
3322 }
3323 self.swap();
3324 let a = &self.a[a];
3325 let b = &self.b[b];
3326 for (k, b) in b.exports.iter() {
3327 match a.exports.get(k) {
3328 Some(a) => self
3329 .entity_type(a, b, offset)
3330 .with_context(|| format!("type mismatch in export `{k}`"))?,
3331 None => bail!(offset, "missing expected export `{k}`"),
3332 }
3333 }
3334 Ok(())
3335 }
3336
3337 pub fn component_any_type_id(
3341 &mut self,
3342 a: ComponentAnyTypeId,
3343 b: ComponentAnyTypeId,
3344 offset: usize,
3345 ) -> Result<()> {
3346 match (a, b) {
3347 (ComponentAnyTypeId::Resource(a), ComponentAnyTypeId::Resource(b)) => {
3348 if a.resource() == b.resource() {
3349 Ok(())
3350 } else {
3351 bail!(
3352 offset,
3353 "resource types are not the same ({:?} vs. {:?})",
3354 a.resource(),
3355 b.resource()
3356 )
3357 }
3358 }
3359 (ComponentAnyTypeId::Resource(_), b) => {
3360 bail!(offset, "expected {}, found resource", b.desc())
3361 }
3362 (ComponentAnyTypeId::Defined(a), ComponentAnyTypeId::Defined(b)) => {
3363 self.component_defined_type(a, b, offset)
3364 }
3365 (ComponentAnyTypeId::Defined(_), b) => {
3366 bail!(offset, "expected {}, found defined type", b.desc())
3367 }
3368
3369 (ComponentAnyTypeId::Func(a), ComponentAnyTypeId::Func(b)) => {
3370 self.component_func_type(a, b, offset)
3371 }
3372 (ComponentAnyTypeId::Func(_), b) => {
3373 bail!(offset, "expected {}, found func type", b.desc())
3374 }
3375
3376 (ComponentAnyTypeId::Instance(a), ComponentAnyTypeId::Instance(b)) => {
3377 self.component_instance_type(a, b, offset)
3378 }
3379 (ComponentAnyTypeId::Instance(_), b) => {
3380 bail!(offset, "expected {}, found instance type", b.desc())
3381 }
3382
3383 (ComponentAnyTypeId::Component(a), ComponentAnyTypeId::Component(b)) => {
3384 self.component_type(a, b, offset)
3385 }
3386 (ComponentAnyTypeId::Component(_), b) => {
3387 bail!(offset, "expected {}, found component type", b.desc())
3388 }
3389 }
3390 }
3391
3392 pub fn open_instance_type(
3416 &mut self,
3417 a: &IndexMap<String, ComponentEntityType>,
3418 b: ComponentTypeId,
3419 kind: ExternKind,
3420 offset: usize,
3421 ) -> Result<Remapping> {
3422 let component_type = &self.b[b];
3452 let entities = match kind {
3453 ExternKind::Import => &component_type.imports,
3454 ExternKind::Export => &component_type.exports,
3455 };
3456 let resources = match kind {
3457 ExternKind::Import => &component_type.imported_resources,
3458 ExternKind::Export => &component_type.defined_resources,
3459 };
3460 let mut mapping = Remapping::default();
3461 'outer: for (resource, path) in resources.iter() {
3462 let (name, ty) = entities.get_index(path[0]).unwrap();
3465 let mut ty = *ty;
3466 let mut arg = a.get(name);
3467
3468 for i in path.iter().skip(1).copied() {
3472 let id = match ty {
3473 ComponentEntityType::Instance(id) => id,
3474 _ => unreachable!(),
3475 };
3476 let (name, next_ty) = self.b[id].exports.get_index(i).unwrap();
3477 ty = *next_ty;
3478 arg = match arg {
3479 Some(ComponentEntityType::Instance(id)) => self.a[*id].exports.get(name),
3480 _ => continue 'outer,
3481 };
3482 }
3483
3484 if cfg!(debug_assertions) {
3487 let id = match ty {
3488 ComponentEntityType::Type { created, .. } => match created {
3489 ComponentAnyTypeId::Resource(id) => id.resource(),
3490 _ => unreachable!(),
3491 },
3492 _ => unreachable!(),
3493 };
3494 assert_eq!(id, *resource);
3495 }
3496
3497 if let Some(ComponentEntityType::Type { created, .. }) = arg {
3501 if let ComponentAnyTypeId::Resource(r) = created {
3502 mapping.resources.insert(*resource, r.resource());
3503 }
3504 }
3505 }
3506
3507 let mut to_typecheck = Vec::new();
3519 for (name, expected) in entities.iter() {
3520 match a.get(name) {
3521 Some(arg) => to_typecheck.push((*arg, *expected)),
3522 None => bail!(offset, "missing {} named `{name}`", kind.desc()),
3523 }
3524 }
3525 let mut type_map = Map::default();
3526 for (i, (actual, expected)) in to_typecheck.into_iter().enumerate() {
3527 let result = self.with_checkpoint(|this| {
3528 let mut expected = expected;
3529 this.b.remap_component_entity(&mut expected, &mut mapping);
3530 mapping.types.clear();
3531 this.component_entity_type(&actual, &expected, offset)
3532 });
3533 let err = match result {
3534 Ok(()) => {
3535 self.register_type_renamings(actual, expected, &mut type_map);
3541 continue;
3542 }
3543 Err(e) => e,
3544 };
3545
3546 let component_type = &self.b[b];
3549 let entities = match kind {
3550 ExternKind::Import => &component_type.imports,
3551 ExternKind::Export => &component_type.exports,
3552 };
3553 let (name, _) = entities.get_index(i).unwrap();
3554 return Err(err.with_context(|| format!("type mismatch for {} `{name}`", kind.desc())));
3555 }
3556 mapping.types = type_map;
3557 Ok(mapping)
3558 }
3559
3560 pub(crate) fn entity_type(&self, a: &EntityType, b: &EntityType, offset: usize) -> Result<()> {
3561 match (a, b) {
3562 (EntityType::Func(a), EntityType::Func(b)) => self.core_func_type(*a, *b, offset),
3563 (EntityType::Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3564 (EntityType::Table(a), EntityType::Table(b)) => Self::table_type(a, b, offset),
3565 (EntityType::Table(_), b) => bail!(offset, "expected {}, found table", b.desc()),
3566 (EntityType::Memory(a), EntityType::Memory(b)) => Self::memory_type(a, b, offset),
3567 (EntityType::Memory(_), b) => bail!(offset, "expected {}, found memory", b.desc()),
3568 (EntityType::Global(a), EntityType::Global(b)) => {
3569 if a.mutable != b.mutable {
3570 bail!(offset, "global types differ in mutability")
3571 }
3572 if a.content_type == b.content_type {
3573 Ok(())
3574 } else {
3575 bail!(
3576 offset,
3577 "expected global type {}, found {}",
3578 b.content_type,
3579 a.content_type,
3580 )
3581 }
3582 }
3583 (EntityType::Global(_), b) => bail!(offset, "expected {}, found global", b.desc()),
3584 (EntityType::Tag(a), EntityType::Tag(b)) => self.core_func_type(*a, *b, offset),
3585 (EntityType::Tag(_), b) => bail!(offset, "expected {}, found tag", b.desc()),
3586 }
3587 }
3588
3589 pub(crate) fn table_type(a: &TableType, b: &TableType, offset: usize) -> Result<()> {
3590 if a.element_type != b.element_type {
3591 bail!(
3592 offset,
3593 "expected table element type {}, found {}",
3594 b.element_type,
3595 a.element_type,
3596 )
3597 }
3598 if a.shared != b.shared {
3599 bail!(offset, "mismatch in the shared flag for tables")
3600 }
3601 if limits_match!(a, b) {
3602 Ok(())
3603 } else {
3604 bail!(offset, "mismatch in table limits")
3605 }
3606 }
3607
3608 pub(crate) fn memory_type(a: &MemoryType, b: &MemoryType, offset: usize) -> Result<()> {
3609 if a.shared != b.shared {
3610 bail!(offset, "mismatch in the shared flag for memories")
3611 }
3612 if a.memory64 != b.memory64 {
3613 bail!(offset, "mismatch in index type used for memories")
3614 }
3615 if limits_match!(a, b) {
3616 Ok(())
3617 } else {
3618 bail!(offset, "mismatch in memory limits")
3619 }
3620 }
3621
3622 fn core_func_type(&self, a: CoreTypeId, b: CoreTypeId, offset: usize) -> Result<()> {
3623 debug_assert!(self.a.get(a).is_some());
3624 debug_assert!(self.b.get(b).is_some());
3625 if self.a.id_is_subtype(a, b) {
3626 debug_assert!(self.a.get(b).is_some());
3627 debug_assert!(self.b.get(a).is_some());
3628 Ok(())
3629 } else {
3630 bail!(
3631 offset,
3632 "expected: {}\n\
3633 found: {}",
3634 self.b[b],
3635 self.a[a],
3636 )
3637 }
3638 }
3639
3640 pub(crate) fn component_val_type(
3641 &self,
3642 a: &ComponentValType,
3643 b: &ComponentValType,
3644 offset: usize,
3645 ) -> Result<()> {
3646 match (a, b) {
3647 (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
3648 self.primitive_val_type(*a, *b, offset)
3649 }
3650 (ComponentValType::Type(a), ComponentValType::Type(b)) => {
3651 self.component_defined_type(*a, *b, offset)
3652 }
3653 (ComponentValType::Primitive(a), ComponentValType::Type(b)) => match &self.b[*b] {
3654 ComponentDefinedType::Primitive(b) => self.primitive_val_type(*a, *b, offset),
3655 b => bail!(offset, "expected {}, found {a}", b.desc()),
3656 },
3657 (ComponentValType::Type(a), ComponentValType::Primitive(b)) => match &self.a[*a] {
3658 ComponentDefinedType::Primitive(a) => self.primitive_val_type(*a, *b, offset),
3659 a => bail!(offset, "expected {b}, found {}", a.desc()),
3660 },
3661 }
3662 }
3663
3664 fn component_defined_type(
3665 &self,
3666 a: ComponentDefinedTypeId,
3667 b: ComponentDefinedTypeId,
3668 offset: usize,
3669 ) -> Result<()> {
3670 use ComponentDefinedType::*;
3671
3672 match (&self.a[a], &self.b[b]) {
3676 (Primitive(a), Primitive(b)) => self.primitive_val_type(*a, *b, offset),
3677 (Primitive(a), b) => bail!(offset, "expected {}, found {a}", b.desc()),
3678 (Record(a), Record(b)) => {
3679 if a.fields.len() != b.fields.len() {
3680 bail!(
3681 offset,
3682 "expected {} fields, found {}",
3683 b.fields.len(),
3684 a.fields.len(),
3685 );
3686 }
3687
3688 for ((aname, a), (bname, b)) in a.fields.iter().zip(b.fields.iter()) {
3689 if aname != bname {
3690 bail!(offset, "expected field name `{bname}`, found `{aname}`");
3691 }
3692 self.component_val_type(a, b, offset)
3693 .with_context(|| format!("type mismatch in record field `{aname}`"))?;
3694 }
3695 Ok(())
3696 }
3697 (Record(_), b) => bail!(offset, "expected {}, found record", b.desc()),
3698 (Variant(a), Variant(b)) => {
3699 if a.cases.len() != b.cases.len() {
3700 bail!(
3701 offset,
3702 "expected {} cases, found {}",
3703 b.cases.len(),
3704 a.cases.len(),
3705 );
3706 }
3707 for ((aname, a), (bname, b)) in a.cases.iter().zip(b.cases.iter()) {
3708 if aname != bname {
3709 bail!(offset, "expected case named `{bname}`, found `{aname}`");
3710 }
3711 match (&a.ty, &b.ty) {
3712 (Some(a), Some(b)) => self
3713 .component_val_type(a, b, offset)
3714 .with_context(|| format!("type mismatch in variant case `{aname}`"))?,
3715 (None, None) => {}
3716 (None, Some(_)) => {
3717 bail!(offset, "expected case `{aname}` to have a type, found none")
3718 }
3719 (Some(_), None) => bail!(offset, "expected case `{aname}` to have no type"),
3720 }
3721 }
3722 Ok(())
3723 }
3724 (Variant(_), b) => bail!(offset, "expected {}, found variant", b.desc()),
3725 (List(a), List(b)) | (Option(a), Option(b)) => self.component_val_type(a, b, offset),
3726 (List(_), b) => bail!(offset, "expected {}, found list", b.desc()),
3727 (FixedSizeList(a, asize), FixedSizeList(b, bsize)) => {
3728 if asize != bsize {
3729 bail!(offset, "expected fixed size {bsize}, found size {asize}")
3730 } else {
3731 self.component_val_type(a, b, offset)
3732 }
3733 }
3734 (FixedSizeList(_, _), b) => bail!(offset, "expected {}, found list", b.desc()),
3735 (Option(_), b) => bail!(offset, "expected {}, found option", b.desc()),
3736 (Tuple(a), Tuple(b)) => {
3737 if a.types.len() != b.types.len() {
3738 bail!(
3739 offset,
3740 "expected {} types, found {}",
3741 b.types.len(),
3742 a.types.len(),
3743 );
3744 }
3745 for (i, (a, b)) in a.types.iter().zip(b.types.iter()).enumerate() {
3746 self.component_val_type(a, b, offset)
3747 .with_context(|| format!("type mismatch in tuple field {i}"))?;
3748 }
3749 Ok(())
3750 }
3751 (Tuple(_), b) => bail!(offset, "expected {}, found tuple", b.desc()),
3752 (at @ Flags(a), Flags(b)) | (at @ Enum(a), Enum(b)) => {
3753 let desc = match at {
3754 Flags(_) => "flags",
3755 _ => "enum",
3756 };
3757 if a.len() == b.len() && a.iter().eq(b.iter()) {
3758 Ok(())
3759 } else {
3760 bail!(offset, "mismatch in {desc} elements")
3761 }
3762 }
3763 (Flags(_), b) => bail!(offset, "expected {}, found flags", b.desc()),
3764 (Enum(_), b) => bail!(offset, "expected {}, found enum", b.desc()),
3765 (Result { ok: ao, err: ae }, Result { ok: bo, err: be }) => {
3766 match (ao, bo) {
3767 (None, None) => {}
3768 (Some(a), Some(b)) => self
3769 .component_val_type(a, b, offset)
3770 .with_context(|| "type mismatch in ok variant")?,
3771 (None, Some(_)) => bail!(offset, "expected ok type, but found none"),
3772 (Some(_), None) => bail!(offset, "expected ok type to not be present"),
3773 }
3774 match (ae, be) {
3775 (None, None) => {}
3776 (Some(a), Some(b)) => self
3777 .component_val_type(a, b, offset)
3778 .with_context(|| "type mismatch in err variant")?,
3779 (None, Some(_)) => bail!(offset, "expected err type, but found none"),
3780 (Some(_), None) => bail!(offset, "expected err type to not be present"),
3781 }
3782 Ok(())
3783 }
3784 (Result { .. }, b) => bail!(offset, "expected {}, found result", b.desc()),
3785 (Own(a), Own(b)) | (Borrow(a), Borrow(b)) => {
3786 if a.resource() == b.resource() {
3787 Ok(())
3788 } else {
3789 bail!(offset, "resource types are not the same")
3790 }
3791 }
3792 (Own(_), b) => bail!(offset, "expected {}, found own", b.desc()),
3793 (Borrow(_), b) => bail!(offset, "expected {}, found borrow", b.desc()),
3794 (Future(a), Future(b)) => match (a, b) {
3795 (None, None) => Ok(()),
3796 (Some(a), Some(b)) => self
3797 .component_val_type(a, b, offset)
3798 .with_context(|| "type mismatch in future"),
3799 (None, Some(_)) => bail!(offset, "expected future type, but found none"),
3800 (Some(_), None) => bail!(offset, "expected future type to not be present"),
3801 },
3802 (Future(_), b) => bail!(offset, "expected {}, found future", b.desc()),
3803 (Stream(a), Stream(b)) => match (a, b) {
3804 (None, None) => Ok(()),
3805 (Some(a), Some(b)) => self
3806 .component_val_type(a, b, offset)
3807 .with_context(|| "type mismatch in stream"),
3808 (None, Some(_)) => bail!(offset, "expected stream type, but found none"),
3809 (Some(_), None) => bail!(offset, "expected stream type to not be present"),
3810 },
3811 (Stream(_), b) => bail!(offset, "expected {}, found stream", b.desc()),
3812 }
3813 }
3814
3815 fn primitive_val_type(
3816 &self,
3817 a: PrimitiveValType,
3818 b: PrimitiveValType,
3819 offset: usize,
3820 ) -> Result<()> {
3821 if a == b {
3828 Ok(())
3829 } else {
3830 bail!(offset, "expected primitive `{b}` found primitive `{a}`")
3831 }
3832 }
3833
3834 fn register_type_renamings(
3835 &self,
3836 actual: ComponentEntityType,
3837 expected: ComponentEntityType,
3838 type_map: &mut Map<ComponentAnyTypeId, ComponentAnyTypeId>,
3839 ) {
3840 match (expected, actual) {
3841 (
3842 ComponentEntityType::Type {
3843 created: expected, ..
3844 },
3845 ComponentEntityType::Type {
3846 created: actual, ..
3847 },
3848 ) => {
3849 let prev = type_map.insert(expected, actual);
3850 assert!(prev.is_none());
3851 }
3852 (ComponentEntityType::Instance(expected), ComponentEntityType::Instance(actual)) => {
3853 let actual = &self.a[actual];
3854 for (name, expected) in self.b[expected].exports.iter() {
3855 let actual = actual.exports[name];
3856 self.register_type_renamings(actual, *expected, type_map);
3857 }
3858 }
3859 _ => {}
3860 }
3861 }
3862}
3863
3864pub struct SubtypeArena<'a> {
3874 types: &'a TypeList,
3875 list: TypeList,
3876}
3877
3878impl<'a> SubtypeArena<'a> {
3879 fn new(types: &'a TypeList) -> SubtypeArena<'a> {
3880 SubtypeArena {
3881 types,
3882 list: TypeList::default(),
3883 }
3884 }
3885
3886 fn get<T>(&self, id: T) -> Option<&T::Data>
3887 where
3888 T: TypeIdentifier,
3889 {
3890 let index = id.index();
3891 if index < T::list(self.types).len() {
3892 self.types.get(id)
3893 } else {
3894 let temp_index = index - T::list(self.types).len();
3895 let temp_index = u32::try_from(temp_index).unwrap();
3896 let temp_id = T::from_index(temp_index);
3897 self.list.get(temp_id)
3898 }
3899 }
3900
3901 fn id_is_subtype(&self, a: CoreTypeId, b: CoreTypeId) -> bool {
3904 self.get(a).is_some() && self.get(b).is_some() && {
3905 debug_assert!(a.index() < CoreTypeId::list(self.types).len());
3908 debug_assert!(b.index() < CoreTypeId::list(self.types).len());
3909 self.types.id_is_subtype(a, b)
3910 }
3911 }
3912}
3913
3914impl<T> Index<T> for SubtypeArena<'_>
3915where
3916 T: TypeIdentifier,
3917{
3918 type Output = T::Data;
3919
3920 fn index(&self, id: T) -> &T::Data {
3921 self.get(id).unwrap()
3922 }
3923}
3924
3925impl Remap for SubtypeArena<'_> {
3926 fn push_ty<T>(&mut self, ty: T) -> T::Id
3927 where
3928 T: TypeData,
3929 {
3930 assert!(
3931 !T::IS_CORE_SUB_TYPE,
3932 "cannot push core sub types into `SubtypeArena`s, that would break type canonicalization"
3933 );
3934 let index = T::Id::list(&self.list).len() + T::Id::list(self.types).len();
3935 let index = u32::try_from(index).unwrap();
3936 self.list.push(ty);
3937 T::Id::from_index(index)
3938 }
3939}
3940
3941pub(crate) trait Context {
3944 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
3945 where
3946 S: Into<String>;
3947}
3948
3949impl<T> Context for Result<T> {
3950 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
3951 where
3952 S: Into<String>,
3953 {
3954 match self {
3955 Ok(val) => Ok(val),
3956 Err(e) => Err(e.with_context(context)),
3957 }
3958 }
3959}
3960
3961impl Context for BinaryReaderError {
3962 fn with_context<S>(mut self, context: impl FnOnce() -> S) -> Self
3963 where
3964 S: Into<String>,
3965 {
3966 self.add_context(context().into());
3967 self
3968 }
3969}