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 async_: bool,
1091 pub params: Box<[(KebabString, ComponentValType)]>,
1093 pub result: Option<ComponentValType>,
1095}
1096
1097impl TypeData for ComponentFuncType {
1098 type Id = ComponentFuncTypeId;
1099 const IS_CORE_SUB_TYPE: bool = false;
1100 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1101 self.info
1102 }
1103}
1104
1105#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1106pub(crate) enum Abi {
1107 Lift,
1108 Lower,
1109}
1110
1111impl Abi {
1112 fn invert(&self) -> Self {
1113 match self {
1114 Abi::Lift => Abi::Lower,
1115 Abi::Lower => Abi::Lift,
1116 }
1117 }
1118}
1119
1120#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1121pub(crate) enum ArgOrField {
1122 Arg(ValType),
1124 Field(StorageType),
1126}
1127
1128impl From<ValType> for ArgOrField {
1129 fn from(v: ValType) -> Self {
1130 Self::Arg(v)
1131 }
1132}
1133
1134impl From<StorageType> for ArgOrField {
1135 fn from(v: StorageType) -> Self {
1136 Self::Field(v)
1137 }
1138}
1139
1140impl core::fmt::Display for ArgOrField {
1141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1142 match self {
1143 ArgOrField::Arg(ty) => core::fmt::Display::fmt(ty, f),
1144 ArgOrField::Field(ty) => core::fmt::Display::fmt(ty, f),
1145 }
1146 }
1147}
1148
1149impl ArgOrField {
1150 pub(crate) fn as_val_type(self) -> Option<ValType> {
1151 match self {
1152 ArgOrField::Arg(ty) | ArgOrField::Field(StorageType::Val(ty)) => Some(ty),
1153 _ => None,
1154 }
1155 }
1156
1157 pub(crate) fn as_ref_type(self) -> Option<RefType> {
1158 self.as_val_type()?.as_reference_type()
1159 }
1160
1161 pub(crate) fn as_concrete_ref(self) -> Option<CoreTypeId> {
1162 match self.as_ref_type()?.heap_type() {
1163 HeapType::Abstract { .. } => None,
1164 HeapType::Concrete(idx) | HeapType::Exact(idx) => {
1165 let id = idx
1166 .as_core_type_id()
1167 .expect("validation only sees core type ids");
1168 Some(id)
1169 }
1170 }
1171 }
1172}
1173
1174pub(crate) enum LoweredFuncType {
1175 New(FuncType),
1176 Existing(CoreTypeId),
1177}
1178
1179impl LoweredFuncType {
1180 pub(crate) fn intern(self, types: &mut TypeAlloc, offset: usize) -> CoreTypeId {
1181 match self {
1182 LoweredFuncType::New(ty) => types.intern_func_type(ty, offset),
1183 LoweredFuncType::Existing(id) => id,
1184 }
1185 }
1186}
1187
1188impl ComponentFuncType {
1189 pub(crate) fn lower(
1192 &self,
1193 types: &TypeList,
1194 options: &CanonicalOptions,
1195 abi: Abi,
1196 offset: usize,
1197 ) -> Result<LoweredFuncType> {
1198 let mut sig = LoweredSignature::default();
1199
1200 if options.gc {
1201 return self.lower_gc(types, abi, options, offset);
1202 }
1203
1204 if abi == Abi::Lower && options.concurrency.is_async() {
1205 sig.params.max = MAX_FLAT_ASYNC_PARAMS;
1206 }
1207
1208 for (_, ty) in self.params.iter() {
1209 match abi {
1216 Abi::Lower => {
1217 options.require_memory_if(offset, || ty.contains_ptr(types))?;
1218 }
1219 Abi::Lift => {
1220 options.require_realloc_if(offset, || ty.contains_ptr(types))?;
1221 }
1222 }
1223
1224 if !ty.push_wasm_types(types, &mut sig.params) {
1225 sig.params.clear();
1229 assert!(sig.params.try_push(ValType::I32));
1230 options.require_memory(offset)?;
1231
1232 if let Abi::Lift = abi {
1234 options.require_realloc(offset)?;
1235 }
1236 break;
1237 }
1238 }
1239
1240 match (abi, options.concurrency) {
1241 (Abi::Lower | Abi::Lift, Concurrency::Sync) => {
1242 if let Some(ty) = &self.result {
1243 options.require_realloc_if(offset, || {
1248 abi == Abi::Lower && ty.contains_ptr(types)
1249 })?;
1250
1251 if !ty.push_wasm_types(types, &mut sig.results) {
1252 sig.results.clear();
1256 options.require_memory(offset)?;
1257 match abi {
1258 Abi::Lower => {
1259 sig.params.max = MAX_LOWERED_TYPES;
1260 assert!(sig.params.try_push(ValType::I32));
1261 }
1262 Abi::Lift => {
1263 assert!(sig.results.try_push(ValType::I32));
1264 }
1265 }
1266 }
1267 }
1268 }
1269 (Abi::Lower, Concurrency::Async { callback: _ }) => {
1270 if self.result.is_some() {
1271 sig.params.max = MAX_LOWERED_TYPES;
1272 sig.params.assert_push(ValType::I32);
1273 options.require_memory(offset)?;
1274 }
1275 sig.results.assert_push(ValType::I32);
1276 }
1277 (Abi::Lift, Concurrency::Async { callback }) => {
1278 if let Some(ty) = &self.result {
1279 let overflow =
1289 !ty.push_wasm_types(types, &mut LoweredTypes::new(MAX_FLAT_FUNC_PARAMS));
1290
1291 options.require_memory_if(offset, || overflow || ty.contains_ptr(types))?;
1292 }
1293 if callback.is_some() {
1294 sig.results.assert_push(ValType::I32);
1295 }
1296 }
1297 }
1298
1299 Ok(LoweredFuncType::New(sig.into_func_type()))
1300 }
1301
1302 fn lower_gc(
1303 &self,
1304 types: &TypeList,
1305 abi: Abi,
1306 options: &CanonicalOptions,
1307 offset: usize,
1308 ) -> Result<LoweredFuncType> {
1309 let core_type_id = options.core_type.unwrap();
1310 let core_func_ty = types[core_type_id].unwrap_func();
1311
1312 ensure!(
1313 core_func_ty.params().len() == self.params.len(),
1314 offset,
1315 "declared `core-type` has {} parameters, but component function has {} parameters",
1316 core_func_ty.params().len(),
1317 self.params.len(),
1318 );
1319 for (core, (_name, comp)) in core_func_ty.params().iter().zip(self.params.iter()) {
1320 comp.lower_gc(types, abi.invert(), options, offset, (*core).into())?;
1321 }
1322
1323 ensure!(
1324 core_func_ty.results().len() == usize::from(self.result.is_some()),
1325 offset,
1326 "declared `core-type` has {} results, but component function has {} results",
1327 core_func_ty.results().len(),
1328 usize::from(self.result.is_some()),
1329 );
1330 if let Some(result) = self.result {
1331 result.lower_gc(
1332 types,
1333 abi,
1334 options,
1335 offset,
1336 core_func_ty.results()[0].into(),
1337 )?;
1338 }
1339
1340 Ok(LoweredFuncType::Existing(core_type_id))
1341 }
1342}
1343
1344#[derive(Debug, Clone)]
1346pub struct VariantCase {
1347 pub ty: Option<ComponentValType>,
1349}
1350
1351#[derive(Debug, Clone)]
1353pub struct RecordType {
1354 pub(crate) info: TypeInfo,
1356 pub fields: IndexMap<KebabString, ComponentValType>,
1358}
1359
1360impl RecordType {
1361 fn lower_gc(
1362 &self,
1363 types: &TypeList,
1364 abi: Abi,
1365 options: &CanonicalOptions,
1366 offset: usize,
1367 core: ArgOrField,
1368 ) -> Result<()> {
1369 lower_gc_product_type(
1370 self.fields.values(),
1371 types,
1372 abi,
1373 options,
1374 offset,
1375 core,
1376 "record",
1377 )
1378 }
1379}
1380
1381#[derive(Debug, Clone)]
1383pub struct VariantType {
1384 pub(crate) info: TypeInfo,
1386 pub cases: IndexMap<KebabString, VariantCase>,
1388}
1389
1390impl VariantType {
1391 fn lower_gc(
1392 &self,
1393 types: &TypeList,
1394 abi: Abi,
1395 options: &CanonicalOptions,
1396 offset: usize,
1397 core: ArgOrField,
1398 ) -> Result<()> {
1399 lower_gc_sum_type(types, abi, options, offset, core, "variant")
1400 }
1401}
1402
1403fn lower_gc_sum_type(
1406 types: &TypeList,
1407 _abi: Abi,
1408 _options: &CanonicalOptions,
1409 offset: usize,
1410 core: ArgOrField,
1411 kind: &str,
1412) -> Result<()> {
1413 if let Some(id) = core.as_concrete_ref() {
1414 if let CompositeInnerType::Struct(ty) = &types[id].composite_type.inner {
1415 if ty.fields.is_empty() {
1416 return Ok(());
1417 }
1418 }
1419 }
1420
1421 bail!(
1422 offset,
1423 "expected to lower component `{kind}` type to core `(ref null? (struct))`, \
1424 but found `{core}`",
1425 )
1426}
1427
1428#[derive(Debug, Clone)]
1430pub struct TupleType {
1431 pub(crate) info: TypeInfo,
1433 pub types: Box<[ComponentValType]>,
1435}
1436
1437impl TupleType {
1438 fn lower_gc(
1439 &self,
1440 types: &TypeList,
1441 abi: Abi,
1442 options: &CanonicalOptions,
1443 offset: usize,
1444 core: ArgOrField,
1445 ) -> Result<()> {
1446 lower_gc_product_type(
1447 self.types.iter(),
1448 types,
1449 abi,
1450 options,
1451 offset,
1452 core,
1453 "tuple",
1454 )
1455 }
1456}
1457
1458#[derive(Debug, Clone)]
1460pub enum ComponentDefinedType {
1461 Primitive(PrimitiveValType),
1463 Record(RecordType),
1465 Variant(VariantType),
1467 List(ComponentValType),
1469 Map(ComponentValType, ComponentValType),
1471 FixedLengthList(ComponentValType, u32),
1473 Tuple(TupleType),
1475 Flags(IndexSet<KebabString>),
1477 Enum(IndexSet<KebabString>),
1479 Option(ComponentValType),
1481 Result {
1483 ok: Option<ComponentValType>,
1485 err: Option<ComponentValType>,
1487 },
1488 Own(AliasableResourceId),
1490 Borrow(AliasableResourceId),
1492 Future(Option<ComponentValType>),
1494 Stream(Option<ComponentValType>),
1496}
1497
1498impl TypeData for ComponentDefinedType {
1499 type Id = ComponentDefinedTypeId;
1500 const IS_CORE_SUB_TYPE: bool = false;
1501 fn type_info(&self, types: &TypeList) -> TypeInfo {
1502 match self {
1503 Self::Primitive(_)
1504 | Self::Flags(_)
1505 | Self::Enum(_)
1506 | Self::Own(_)
1507 | Self::Future(_)
1508 | Self::Stream(_) => TypeInfo::new(),
1509 Self::Borrow(_) => TypeInfo::borrow(),
1510 Self::Record(r) => r.info,
1511 Self::Variant(v) => v.info,
1512 Self::Tuple(t) => t.info,
1513 Self::List(ty) | Self::FixedLengthList(ty, _) | Self::Option(ty) => ty.info(types),
1514 Self::Map(k, v) => {
1515 let mut info = k.info(types);
1516 info.combine(v.info(types), 0).unwrap();
1517 info
1518 }
1519 Self::Result { ok, err } => {
1520 let default = TypeInfo::new();
1521 let mut info = ok.map(|ty| ty.type_info(types)).unwrap_or(default);
1522 info.combine(err.map(|ty| ty.type_info(types)).unwrap_or(default), 0)
1523 .unwrap();
1524 info
1525 }
1526 }
1527 }
1528}
1529
1530impl ComponentDefinedType {
1531 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
1532 match self {
1533 Self::Primitive(ty) => ty.contains_ptr(),
1534 Self::Record(r) => r.fields.values().any(|ty| ty.contains_ptr(types)),
1535 Self::Variant(v) => v
1536 .cases
1537 .values()
1538 .any(|case| case.ty.map(|ty| ty.contains_ptr(types)).unwrap_or(false)),
1539 Self::List(_) | Self::Map(_, _) => true,
1540 Self::Tuple(t) => t.types.iter().any(|ty| ty.contains_ptr(types)),
1541 Self::Flags(_)
1542 | Self::Enum(_)
1543 | Self::Own(_)
1544 | Self::Borrow(_)
1545 | Self::Future(_)
1546 | Self::Stream(_) => false,
1547 Self::Option(ty) | Self::FixedLengthList(ty, _) => ty.contains_ptr(types),
1548 Self::Result { ok, err } => {
1549 ok.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1550 || err.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1551 }
1552 }
1553 }
1554
1555 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1556 match self {
1557 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1558 Self::Record(r) => r
1559 .fields
1560 .iter()
1561 .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1562 Self::Variant(v) => Self::push_variant_wasm_types(
1563 v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1564 types,
1565 lowered_types,
1566 ),
1567 Self::List(_) | Self::Map(_, _) => {
1568 lowered_types.try_push(ValType::I32) && lowered_types.try_push(ValType::I32)
1569 }
1570 Self::FixedLengthList(ty, length) => {
1571 (0..*length).all(|_n| ty.push_wasm_types(types, lowered_types))
1572 }
1573 Self::Tuple(t) => t
1574 .types
1575 .iter()
1576 .all(|ty| ty.push_wasm_types(types, lowered_types)),
1577 Self::Flags(names) => {
1578 (0..(names.len() + 31) / 32).all(|_| lowered_types.try_push(ValType::I32))
1579 }
1580 Self::Enum(_) | Self::Own(_) | Self::Borrow(_) | Self::Future(_) | Self::Stream(_) => {
1581 lowered_types.try_push(ValType::I32)
1582 }
1583 Self::Option(ty) => {
1584 Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1585 }
1586 Self::Result { ok, err } => {
1587 Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1588 }
1589 }
1590 }
1591
1592 fn push_variant_wasm_types<'a>(
1593 cases: impl Iterator<Item = &'a ComponentValType>,
1594 types: &TypeList,
1595 lowered_types: &mut LoweredTypes,
1596 ) -> bool {
1597 if !lowered_types.try_push(ValType::I32) {
1599 return false;
1600 }
1601
1602 let start = lowered_types.len();
1603
1604 for ty in cases {
1605 let mut temp = LoweredTypes::new(lowered_types.max);
1606
1607 if !ty.push_wasm_types(types, &mut temp) {
1608 return false;
1609 }
1610
1611 for (i, ty) in temp.iter().enumerate() {
1612 match lowered_types.get_mut(start + i) {
1613 Some(prev) => *prev = Self::join_types(*prev, ty),
1614 None => {
1615 if !lowered_types.try_push(ty) {
1616 return false;
1617 }
1618 }
1619 }
1620 }
1621 }
1622
1623 true
1624 }
1625
1626 fn join_types(a: ValType, b: ValType) -> ValType {
1627 use ValType::*;
1628
1629 match (a, b) {
1630 (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1631 (I32, F32) | (F32, I32) => I32,
1632 (_, I64 | F64) | (I64 | F64, _) => I64,
1633 _ => panic!("unexpected wasm type for canonical ABI"),
1634 }
1635 }
1636
1637 fn desc(&self) -> &'static str {
1638 match self {
1639 ComponentDefinedType::Record(_) => "record",
1640 ComponentDefinedType::Primitive(_) => "primitive",
1641 ComponentDefinedType::Variant(_) => "variant",
1642 ComponentDefinedType::Tuple(_) => "tuple",
1643 ComponentDefinedType::Enum(_) => "enum",
1644 ComponentDefinedType::Flags(_) => "flags",
1645 ComponentDefinedType::Option(_) => "option",
1646 ComponentDefinedType::List(_) => "list",
1647 ComponentDefinedType::Map(_, _) => "map",
1648 ComponentDefinedType::FixedLengthList(_, _) => "fixed-length list",
1649 ComponentDefinedType::Result { .. } => "result",
1650 ComponentDefinedType::Own(_) => "own",
1651 ComponentDefinedType::Borrow(_) => "borrow",
1652 ComponentDefinedType::Future(_) => "future",
1653 ComponentDefinedType::Stream(_) => "stream",
1654 }
1655 }
1656
1657 fn lower_gc(
1658 &self,
1659 types: &TypeList,
1660 abi: Abi,
1661 options: &CanonicalOptions,
1662 offset: usize,
1663 core: ArgOrField,
1664 ) -> Result<()> {
1665 match self {
1666 ComponentDefinedType::Primitive(ty) => ty.lower_gc(types, abi, options, offset, core),
1667
1668 ComponentDefinedType::Record(ty) => ty.lower_gc(types, abi, options, offset, core),
1669
1670 ComponentDefinedType::Variant(ty) => ty.lower_gc(types, abi, options, offset, core),
1671
1672 ComponentDefinedType::List(ty) | ComponentDefinedType::FixedLengthList(ty, _) => {
1673 let id = match core.as_concrete_ref() {
1674 Some(id) => id,
1675 None => bail!(
1676 offset,
1677 "expected to lower component `list` type into `(ref null? (array ...))`, but \
1678 found `{core}`",
1679 ),
1680 };
1681 let array_ty = match types[id].composite_type.inner {
1682 CompositeInnerType::Array(ty) => ty,
1683 _ => bail!(
1684 offset,
1685 "expected to lower component `list` type into `(ref null? (array ...))`, but \
1686 found `{core}`",
1687 ),
1688 };
1689 ty.lower_gc(types, abi, options, offset, array_ty.0.element_type.into())
1690 }
1691
1692 ComponentDefinedType::Map(_, _) => bail!(
1693 offset,
1694 "GC lowering for component `map` type is not yet implemented"
1695 ),
1696
1697 ComponentDefinedType::Tuple(ty) => ty.lower_gc(types, abi, options, offset, core),
1698
1699 ComponentDefinedType::Flags(flags) => {
1700 assert!(flags.len() <= 32, "required by validation");
1701 if core.as_val_type() == Some(ValType::I32) {
1702 Ok(())
1703 } else {
1704 bail!(
1705 offset,
1706 "expected to lower component `flags` type into core `i32` type, but \
1707 found `{core}`",
1708 )
1709 }
1710 }
1711
1712 ComponentDefinedType::Enum(_) => {
1713 if core.as_val_type() == Some(ValType::I32) {
1714 Ok(())
1715 } else {
1716 bail!(
1717 offset,
1718 "expected to lower component `enum` type into core `i32` type, but \
1719 found `{core}`",
1720 )
1721 }
1722 }
1723
1724 ComponentDefinedType::Option(_) => {
1725 lower_gc_sum_type(types, abi, options, offset, core, "option")
1726 }
1727
1728 ComponentDefinedType::Result { .. } => {
1729 lower_gc_sum_type(types, abi, options, offset, core, "result")
1730 }
1731
1732 ComponentDefinedType::Own(_)
1733 | ComponentDefinedType::Borrow(_)
1734 | ComponentDefinedType::Future(_)
1735 | ComponentDefinedType::Stream(_) => {
1736 if let Some(r) = core.as_ref_type() {
1737 if let HeapType::Abstract {
1738 shared: _,
1739 ty: AbstractHeapType::Extern,
1740 } = r.heap_type()
1741 {
1742 return Ok(());
1743 }
1744 }
1745 bail!(
1746 offset,
1747 "expected to lower component `{}` type into core `(ref null? extern)` type, but \
1748 found `{core}`",
1749 self.desc()
1750 )
1751 }
1752 }
1753 }
1754}
1755
1756fn lower_gc_product_type<'a, I>(
1759 fields: I,
1760 types: &TypeList,
1761 abi: Abi,
1762 options: &CanonicalOptions,
1763 offset: usize,
1764 core: ArgOrField,
1765 kind: &str,
1766) -> core::result::Result<(), BinaryReaderError>
1767where
1768 I: IntoIterator<Item = &'a ComponentValType>,
1769 I::IntoIter: ExactSizeIterator,
1770{
1771 let fields = fields.into_iter();
1772 let fields_len = fields.len();
1773
1774 if let Some(id) = core.as_concrete_ref() {
1775 if let CompositeInnerType::Struct(ty) = &types[id].composite_type.inner {
1776 ensure!(
1777 ty.fields.len() == fields_len,
1778 offset,
1779 "core `struct` has {} fields, but component `{kind}` has {fields_len} fields",
1780 ty.fields.len(),
1781 );
1782 for (core, comp) in ty.fields.iter().zip(fields) {
1783 comp.lower_gc(types, abi, options, offset, core.element_type.into())?;
1784 }
1785 return Ok(());
1786 }
1787 }
1788
1789 bail!(
1790 offset,
1791 "expected to lower component `{kind}` type to core `(ref null? (struct ...))`, \
1792 but found `{core}`",
1793 )
1794}
1795
1796#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
1799#[repr(packed(4))] pub struct ResourceId {
1801 globally_unique_id: usize,
1811
1812 contextually_unique_id: u32,
1821}
1822
1823impl<'a> TypesRef<'a> {
1824 pub fn core_type_at_in_component(&self, index: u32) -> ComponentCoreTypeId {
1835 match &self.kind {
1836 TypesRefKind::Module(_) => panic!("use `component_type_at_in_module` instead"),
1837 TypesRefKind::Component(component) => component.core_types[index as usize],
1838 }
1839 }
1840
1841 pub fn core_type_count_in_component(&self) -> u32 {
1846 match &self.kind {
1847 TypesRefKind::Module(_) => 0,
1848 TypesRefKind::Component(component) => component.core_types.len() as u32,
1849 }
1850 }
1851
1852 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1859 match &self.kind {
1860 TypesRefKind::Module(_) => panic!("not a component"),
1861 TypesRefKind::Component(component) => component.types[index as usize],
1862 }
1863 }
1864
1865 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1872 match self.component_any_type_at(index) {
1873 ComponentAnyTypeId::Component(id) => id,
1874 _ => panic!("not a component type"),
1875 }
1876 }
1877
1878 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1885 match self.component_any_type_at(index) {
1886 ComponentAnyTypeId::Defined(id) => id,
1887 _ => panic!("not a defined type"),
1888 }
1889 }
1890
1891 pub fn component_type_count(&self) -> u32 {
1893 match &self.kind {
1894 TypesRefKind::Module(_module) => 0,
1895 TypesRefKind::Component(component) => component.types.len() as u32,
1896 }
1897 }
1898
1899 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
1906 match &self.kind {
1907 TypesRefKind::Module(_) => panic!("not a component"),
1908 TypesRefKind::Component(component) => component.funcs[index as usize],
1909 }
1910 }
1911
1912 pub fn component_function_count(&self) -> u32 {
1914 match &self.kind {
1915 TypesRefKind::Module(_module) => 0,
1916 TypesRefKind::Component(component) => component.funcs.len() as u32,
1917 }
1918 }
1919
1920 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
1927 match &self.kind {
1928 TypesRefKind::Module(_) => panic!("not a component"),
1929 TypesRefKind::Component(component) => component.core_modules[index as usize],
1930 }
1931 }
1932
1933 pub fn module_count(&self) -> u32 {
1935 match &self.kind {
1936 TypesRefKind::Module(_module) => 0,
1937 TypesRefKind::Component(component) => component.core_modules.len() as u32,
1938 }
1939 }
1940
1941 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
1948 match &self.kind {
1949 TypesRefKind::Module(_) => panic!("not a component"),
1950 TypesRefKind::Component(component) => component.core_instances[index as usize],
1951 }
1952 }
1953
1954 pub fn core_instance_count(&self) -> u32 {
1956 match &self.kind {
1957 TypesRefKind::Module(_module) => 0,
1958 TypesRefKind::Component(component) => component.core_instances.len() as u32,
1959 }
1960 }
1961
1962 pub fn component_at(&self, index: u32) -> ComponentTypeId {
1969 match &self.kind {
1970 TypesRefKind::Module(_) => panic!("not a component"),
1971 TypesRefKind::Component(component) => component.components[index as usize],
1972 }
1973 }
1974
1975 pub fn component_count(&self) -> u32 {
1977 match &self.kind {
1978 TypesRefKind::Module(_module) => 0,
1979 TypesRefKind::Component(component) => component.components.len() as u32,
1980 }
1981 }
1982
1983 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
1990 match &self.kind {
1991 TypesRefKind::Module(_) => panic!("not a component"),
1992 TypesRefKind::Component(component) => component.instances[index as usize],
1993 }
1994 }
1995
1996 pub fn component_instance_count(&self) -> u32 {
1998 match &self.kind {
1999 TypesRefKind::Module(_module) => 0,
2000 TypesRefKind::Component(component) => component.instances.len() as u32,
2001 }
2002 }
2003
2004 pub fn value_at(&self, index: u32) -> ComponentValType {
2011 match &self.kind {
2012 TypesRefKind::Module(_) => panic!("not a component"),
2013 TypesRefKind::Component(component) => component.values[index as usize].0,
2014 }
2015 }
2016
2017 pub fn value_count(&self) -> u32 {
2019 match &self.kind {
2020 TypesRefKind::Module(_module) => 0,
2021 TypesRefKind::Component(component) => component.values.len() as u32,
2022 }
2023 }
2024
2025 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
2027 match &self.kind {
2028 TypesRefKind::Module(_) => None,
2029 TypesRefKind::Component(component) => Some(*component.imports.get(name)?),
2030 }
2031 }
2032
2033 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
2035 match &self.kind {
2036 TypesRefKind::Module(_) => None,
2037 TypesRefKind::Component(component) => Some(*component.exports.get(name)?),
2038 }
2039 }
2040
2041 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2045 where
2046 T: Aliasable,
2047 {
2048 self.list.peel_alias(ty)
2049 }
2050}
2051
2052impl Types {
2053 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
2062 self.as_ref().component_any_type_at(index)
2063 }
2064
2065 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
2071 self.as_ref().component_type_at(index)
2072 }
2073
2074 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
2081 self.as_ref().component_defined_type_at(index)
2082 }
2083
2084 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
2091 self.as_ref().component_function_at(index)
2092 }
2093
2094 pub fn component_function_count(&self) -> u32 {
2096 self.as_ref().component_function_count()
2097 }
2098
2099 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
2106 self.as_ref().module_at(index)
2107 }
2108
2109 pub fn module_count(&self) -> usize {
2111 match &self.kind {
2112 TypesKind::Module(_) => 0,
2113 TypesKind::Component(component) => component.core_modules.len(),
2114 }
2115 }
2116
2117 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
2124 self.as_ref().core_instance_at(index)
2125 }
2126
2127 pub fn core_instance_count(&self) -> usize {
2129 match &self.kind {
2130 TypesKind::Module(_) => 0,
2131 TypesKind::Component(component) => component.core_instances.len(),
2132 }
2133 }
2134
2135 pub fn component_at(&self, index: u32) -> ComponentTypeId {
2142 self.as_ref().component_at(index)
2143 }
2144
2145 pub fn component_count(&self) -> usize {
2147 match &self.kind {
2148 TypesKind::Module(_) => 0,
2149 TypesKind::Component(component) => component.components.len(),
2150 }
2151 }
2152
2153 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
2160 self.as_ref().component_instance_at(index)
2161 }
2162
2163 pub fn component_instance_count(&self) -> usize {
2165 match &self.kind {
2166 TypesKind::Module(_) => 0,
2167 TypesKind::Component(component) => component.instances.len(),
2168 }
2169 }
2170
2171 pub fn value_at(&self, index: u32) -> ComponentValType {
2178 self.as_ref().value_at(index)
2179 }
2180
2181 pub fn value_count(&self) -> usize {
2183 match &self.kind {
2184 TypesKind::Module(_) => 0,
2185 TypesKind::Component(component) => component.values.len(),
2186 }
2187 }
2188
2189 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
2191 self.as_ref().component_entity_type_of_import(name)
2192 }
2193
2194 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
2196 self.as_ref().component_entity_type_of_export(name)
2197 }
2198
2199 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2203 where
2204 T: Aliasable,
2205 {
2206 self.list.peel_alias(ty)
2207 }
2208}
2209
2210#[derive(Debug, Default)]
2212pub(crate) struct ComponentTypeList {
2213 alias_mappings: Map<u32, u32>,
2215 alias_counter: u32,
2217 alias_snapshots: Vec<TypeListAliasSnapshot>,
2219
2220 components: SnapshotList<ComponentType>,
2222 component_defined_types: SnapshotList<ComponentDefinedType>,
2223 component_values: SnapshotList<ComponentValType>,
2224 component_instances: SnapshotList<ComponentInstanceType>,
2225 component_funcs: SnapshotList<ComponentFuncType>,
2226 core_modules: SnapshotList<ModuleType>,
2227 core_instances: SnapshotList<InstanceType>,
2228}
2229
2230#[derive(Clone, Debug)]
2231struct TypeListAliasSnapshot {
2232 alias_counter: u32,
2234
2235 alias_mappings: Map<u32, u32>,
2237}
2238
2239struct TypeListCheckpoint {
2240 core_types: usize,
2241 components: usize,
2242 component_defined_types: usize,
2243 component_values: usize,
2244 component_instances: usize,
2245 component_funcs: usize,
2246 core_modules: usize,
2247 core_instances: usize,
2248 core_type_to_rec_group: usize,
2249 core_type_to_supertype: usize,
2250 core_type_to_depth: usize,
2251 rec_group_elements: usize,
2252 canonical_rec_groups: usize,
2253}
2254
2255impl TypeList {
2256 fn checkpoint(&self) -> TypeListCheckpoint {
2257 let TypeList {
2258 component:
2259 ComponentTypeList {
2260 alias_mappings: _,
2261 alias_counter: _,
2262 alias_snapshots: _,
2263 components,
2264 component_defined_types,
2265 component_values,
2266 component_instances,
2267 component_funcs,
2268 core_modules,
2269 core_instances,
2270 },
2271 core_types,
2272 core_type_to_rec_group,
2273 core_type_to_supertype,
2274 core_type_to_depth,
2275 rec_group_elements,
2276 canonical_rec_groups,
2277 } = self;
2278
2279 TypeListCheckpoint {
2280 core_types: core_types.len(),
2281 components: components.len(),
2282 component_defined_types: component_defined_types.len(),
2283 component_values: component_values.len(),
2284 component_instances: component_instances.len(),
2285 component_funcs: component_funcs.len(),
2286 core_modules: core_modules.len(),
2287 core_instances: core_instances.len(),
2288 core_type_to_rec_group: core_type_to_rec_group.len(),
2289 core_type_to_supertype: core_type_to_supertype.len(),
2290 core_type_to_depth: core_type_to_depth.as_ref().map(|m| m.len()).unwrap_or(0),
2291 rec_group_elements: rec_group_elements.len(),
2292 canonical_rec_groups: canonical_rec_groups.as_ref().map(|m| m.len()).unwrap_or(0),
2293 }
2294 }
2295
2296 fn reset_to_checkpoint(&mut self, checkpoint: TypeListCheckpoint) {
2297 let TypeList {
2298 component:
2299 ComponentTypeList {
2300 alias_mappings: _,
2301 alias_counter: _,
2302 alias_snapshots: _,
2303 components,
2304 component_defined_types,
2305 component_values,
2306 component_instances,
2307 component_funcs,
2308 core_modules,
2309 core_instances,
2310 },
2311 core_types,
2312 core_type_to_rec_group,
2313 core_type_to_supertype,
2314 core_type_to_depth,
2315 rec_group_elements,
2316 canonical_rec_groups,
2317 } = self;
2318
2319 core_types.truncate(checkpoint.core_types);
2320 components.truncate(checkpoint.components);
2321 component_defined_types.truncate(checkpoint.component_defined_types);
2322 component_values.truncate(checkpoint.component_values);
2323 component_instances.truncate(checkpoint.component_instances);
2324 component_funcs.truncate(checkpoint.component_funcs);
2325 core_modules.truncate(checkpoint.core_modules);
2326 core_instances.truncate(checkpoint.core_instances);
2327 core_type_to_rec_group.truncate(checkpoint.core_type_to_rec_group);
2328 core_type_to_supertype.truncate(checkpoint.core_type_to_supertype);
2329 rec_group_elements.truncate(checkpoint.rec_group_elements);
2330
2331 if let Some(core_type_to_depth) = core_type_to_depth {
2332 assert_eq!(
2333 core_type_to_depth.len(),
2334 checkpoint.core_type_to_depth,
2335 "checkpointing does not support resetting `core_type_to_depth` (it would require a \
2336 proper immutable and persistent hash map) so adding new groups is disallowed"
2337 );
2338 }
2339 if let Some(canonical_rec_groups) = canonical_rec_groups {
2340 assert_eq!(
2341 canonical_rec_groups.len(),
2342 checkpoint.canonical_rec_groups,
2343 "checkpointing does not support resetting `canonical_rec_groups` (it would require a \
2344 proper immutable and persistent hash map) so adding new groups is disallowed"
2345 );
2346 }
2347 }
2348
2349 pub fn with_unique<T>(&mut self, mut ty: T) -> T
2351 where
2352 T: Aliasable,
2353 {
2354 self.component
2355 .alias_mappings
2356 .insert(self.component.alias_counter, ty.alias_id());
2357 ty.set_alias_id(self.component.alias_counter);
2358 self.component.alias_counter += 1;
2359 ty
2360 }
2361
2362 pub fn peel_alias<T>(&self, mut ty: T) -> Option<T>
2366 where
2367 T: Aliasable,
2368 {
2369 let alias_id = ty.alias_id();
2370
2371 let i = match self
2378 .component
2379 .alias_snapshots
2380 .binary_search_by_key(&alias_id, |snapshot| snapshot.alias_counter)
2381 {
2382 Ok(_) => unreachable!(),
2383 Err(i) => i,
2384 };
2385
2386 ty.set_alias_id(match self.component.alias_snapshots.get(i) {
2390 Some(snapshot) => *snapshot.alias_mappings.get(&alias_id)?,
2391 None => *self.component.alias_mappings.get(&alias_id)?,
2392 });
2393 Some(ty)
2394 }
2395}
2396
2397impl ComponentTypeList {
2398 pub fn commit(&mut self) -> ComponentTypeList {
2399 let alias_counter = self.alias_counter;
2403 self.alias_counter += 1;
2404
2405 self.alias_snapshots.push(TypeListAliasSnapshot {
2406 alias_counter,
2407 alias_mappings: mem::take(&mut self.alias_mappings),
2408 });
2409
2410 ComponentTypeList {
2411 alias_mappings: Map::default(),
2412 alias_counter: self.alias_counter,
2413 alias_snapshots: self.alias_snapshots.clone(),
2414 components: self.components.commit(),
2415 component_defined_types: self.component_defined_types.commit(),
2416 component_values: self.component_values.commit(),
2417 component_instances: self.component_instances.commit(),
2418 component_funcs: self.component_funcs.commit(),
2419 core_modules: self.core_modules.commit(),
2420 core_instances: self.core_instances.commit(),
2421 }
2422 }
2423}
2424
2425pub(crate) struct ComponentTypeAlloc {
2426 globally_unique_id: usize,
2429
2430 next_resource_id: u32,
2433}
2434
2435impl Default for ComponentTypeAlloc {
2436 fn default() -> ComponentTypeAlloc {
2437 static NEXT_GLOBAL_ID: AtomicUsize = AtomicUsize::new(0);
2438 ComponentTypeAlloc {
2439 globally_unique_id: {
2440 let id = NEXT_GLOBAL_ID.fetch_add(1, Ordering::Relaxed);
2441 if id > usize::MAX - 10_000 {
2442 NEXT_GLOBAL_ID.store(usize::MAX - 10_000, Ordering::Relaxed);
2443 panic!("overflow on the global id counter");
2444 }
2445 id
2446 },
2447 next_resource_id: 0,
2448 }
2449 }
2450}
2451
2452impl TypeAlloc {
2453 pub fn alloc_resource_id(&mut self) -> AliasableResourceId {
2457 let contextually_unique_id = self.component_alloc.next_resource_id;
2458 self.component_alloc.next_resource_id = self
2459 .component_alloc
2460 .next_resource_id
2461 .checked_add(1)
2462 .unwrap();
2463 AliasableResourceId {
2464 id: ResourceId {
2465 globally_unique_id: self.component_alloc.globally_unique_id,
2466 contextually_unique_id,
2467 },
2468 alias_id: NO_ALIAS,
2469 }
2470 }
2471
2472 pub fn free_variables_any_type_id(
2479 &self,
2480 id: ComponentAnyTypeId,
2481 set: &mut IndexSet<ResourceId>,
2482 ) {
2483 match id {
2484 ComponentAnyTypeId::Resource(r) => {
2485 set.insert(r.resource());
2486 }
2487 ComponentAnyTypeId::Defined(id) => {
2488 self.free_variables_component_defined_type_id(id, set)
2489 }
2490 ComponentAnyTypeId::Func(id) => self.free_variables_component_func_type_id(id, set),
2491 ComponentAnyTypeId::Instance(id) => {
2492 self.free_variables_component_instance_type_id(id, set)
2493 }
2494 ComponentAnyTypeId::Component(id) => self.free_variables_component_type_id(id, set),
2495 }
2496 }
2497
2498 pub fn free_variables_component_defined_type_id(
2499 &self,
2500 id: ComponentDefinedTypeId,
2501 set: &mut IndexSet<ResourceId>,
2502 ) {
2503 match &self[id] {
2504 ComponentDefinedType::Primitive(_)
2505 | ComponentDefinedType::Flags(_)
2506 | ComponentDefinedType::Enum(_) => {}
2507 ComponentDefinedType::Record(r) => {
2508 for ty in r.fields.values() {
2509 self.free_variables_valtype(ty, set);
2510 }
2511 }
2512 ComponentDefinedType::Tuple(r) => {
2513 for ty in r.types.iter() {
2514 self.free_variables_valtype(ty, set);
2515 }
2516 }
2517 ComponentDefinedType::Variant(r) => {
2518 for ty in r.cases.values() {
2519 if let Some(ty) = &ty.ty {
2520 self.free_variables_valtype(ty, set);
2521 }
2522 }
2523 }
2524 ComponentDefinedType::List(ty)
2525 | ComponentDefinedType::FixedLengthList(ty, _)
2526 | ComponentDefinedType::Option(ty) => {
2527 self.free_variables_valtype(ty, set);
2528 }
2529 ComponentDefinedType::Map(k, v) => {
2530 self.free_variables_valtype(k, set);
2531 self.free_variables_valtype(v, set);
2532 }
2533 ComponentDefinedType::Result { ok, err } => {
2534 if let Some(ok) = ok {
2535 self.free_variables_valtype(ok, set);
2536 }
2537 if let Some(err) = err {
2538 self.free_variables_valtype(err, set);
2539 }
2540 }
2541 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2542 set.insert(id.resource());
2543 }
2544 ComponentDefinedType::Future(ty) => {
2545 if let Some(ty) = ty {
2546 self.free_variables_valtype(ty, set);
2547 }
2548 }
2549 ComponentDefinedType::Stream(ty) => {
2550 if let Some(ty) = ty {
2551 self.free_variables_valtype(ty, set);
2552 }
2553 }
2554 }
2555 }
2556
2557 pub fn free_variables_component_type_id(
2558 &self,
2559 id: ComponentTypeId,
2560 set: &mut IndexSet<ResourceId>,
2561 ) {
2562 let i = &self[id];
2563 for ty in i.imports.values().chain(i.exports.values()) {
2574 self.free_variables_component_entity(ty, set);
2575 }
2576 for (id, _path) in i.imported_resources.iter().chain(&i.defined_resources) {
2577 set.swap_remove(id);
2578 }
2579 }
2580
2581 pub fn free_variables_component_instance_type_id(
2582 &self,
2583 id: ComponentInstanceTypeId,
2584 set: &mut IndexSet<ResourceId>,
2585 ) {
2586 let i = &self[id];
2587 for ty in i.exports.values() {
2591 self.free_variables_component_entity(ty, set);
2592 }
2593 for id in i.defined_resources.iter() {
2594 set.swap_remove(id);
2595 }
2596 }
2597
2598 pub fn free_variables_component_func_type_id(
2599 &self,
2600 id: ComponentFuncTypeId,
2601 set: &mut IndexSet<ResourceId>,
2602 ) {
2603 let i = &self[id];
2604 for ty in i.params.iter().map(|(_, ty)| ty).chain(&i.result) {
2605 self.free_variables_valtype(ty, set);
2606 }
2607 }
2608
2609 pub fn free_variables_component_entity(
2611 &self,
2612 ty: &ComponentEntityType,
2613 set: &mut IndexSet<ResourceId>,
2614 ) {
2615 match ty {
2616 ComponentEntityType::Module(_) => {}
2617 ComponentEntityType::Func(id) => self.free_variables_component_func_type_id(*id, set),
2618 ComponentEntityType::Instance(id) => {
2619 self.free_variables_component_instance_type_id(*id, set)
2620 }
2621 ComponentEntityType::Component(id) => self.free_variables_component_type_id(*id, set),
2622 ComponentEntityType::Type { created, .. } => {
2623 self.free_variables_any_type_id(*created, set);
2624 }
2625 ComponentEntityType::Value(ty) => self.free_variables_valtype(ty, set),
2626 }
2627 }
2628
2629 fn free_variables_valtype(&self, ty: &ComponentValType, set: &mut IndexSet<ResourceId>) {
2631 match ty {
2632 ComponentValType::Primitive(_) => {}
2633 ComponentValType::Type(id) => self.free_variables_component_defined_type_id(*id, set),
2634 }
2635 }
2636
2637 pub(crate) fn type_named_type_id(
2642 &self,
2643 id: ComponentDefinedTypeId,
2644 set: &Set<ComponentAnyTypeId>,
2645 ) -> bool {
2646 let ty = &self[id];
2647 match ty {
2648 ComponentDefinedType::Primitive(_) => true,
2650
2651 ComponentDefinedType::Flags(_)
2654 | ComponentDefinedType::Enum(_)
2655 | ComponentDefinedType::Record(_)
2656 | ComponentDefinedType::Variant(_) => set.contains(&ComponentAnyTypeId::from(id)),
2657
2658 ComponentDefinedType::Tuple(r) => {
2661 r.types.iter().all(|t| self.type_named_valtype(t, set))
2662 }
2663 ComponentDefinedType::Result { ok, err } => {
2664 ok.as_ref()
2665 .map(|t| self.type_named_valtype(t, set))
2666 .unwrap_or(true)
2667 && err
2668 .as_ref()
2669 .map(|t| self.type_named_valtype(t, set))
2670 .unwrap_or(true)
2671 }
2672 ComponentDefinedType::List(ty)
2673 | ComponentDefinedType::FixedLengthList(ty, _)
2674 | ComponentDefinedType::Option(ty) => self.type_named_valtype(ty, set),
2675 ComponentDefinedType::Map(k, v) => {
2676 self.type_named_valtype(k, set) && self.type_named_valtype(v, set)
2677 }
2678
2679 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2682 set.contains(&ComponentAnyTypeId::from(*id))
2683 }
2684
2685 ComponentDefinedType::Future(ty) => ty
2686 .as_ref()
2687 .map(|ty| self.type_named_valtype(ty, set))
2688 .unwrap_or(true),
2689
2690 ComponentDefinedType::Stream(ty) => ty
2691 .as_ref()
2692 .map(|ty| self.type_named_valtype(ty, set))
2693 .unwrap_or(true),
2694 }
2695 }
2696
2697 pub(crate) fn type_named_valtype(
2698 &self,
2699 ty: &ComponentValType,
2700 set: &Set<ComponentAnyTypeId>,
2701 ) -> bool {
2702 match ty {
2703 ComponentValType::Primitive(_) => true,
2704 ComponentValType::Type(id) => self.type_named_type_id(*id, set),
2705 }
2706 }
2707}
2708
2709pub trait Remap
2715where
2716 Self: Index<ComponentTypeId, Output = ComponentType>,
2717 Self: Index<ComponentDefinedTypeId, Output = ComponentDefinedType>,
2718 Self: Index<ComponentInstanceTypeId, Output = ComponentInstanceType>,
2719 Self: Index<ComponentFuncTypeId, Output = ComponentFuncType>,
2720{
2721 #[doc(hidden)]
2726 fn push_ty<T>(&mut self, ty: T) -> T::Id
2727 where
2728 T: TypeData;
2729
2730 fn map_map(
2733 tmp: &mut IndexMap<ResourceId, Vec<usize>>,
2734 any_changed: &mut bool,
2735 map: &Remapping,
2736 ) {
2737 for (id, path) in mem::take(tmp) {
2738 let id = match map.resources.get(&id) {
2739 Some(id) => {
2740 *any_changed = true;
2741 *id
2742 }
2743 None => id,
2744 };
2745 tmp.insert(id, path);
2746 }
2747 }
2748
2749 fn insert_if_any_changed<T>(
2753 &mut self,
2754 map: &mut Remapping,
2755 any_changed: bool,
2756 id: &mut T::Id,
2757 ty: T,
2758 ) -> bool
2759 where
2760 T: TypeData,
2761 T::Id: Into<ComponentAnyTypeId>,
2762 {
2763 let new = if any_changed { self.push_ty(ty) } else { *id };
2764 map.types.insert((*id).into(), new.into());
2765 let changed = *id != new;
2766 *id = new;
2767 changed
2768 }
2769
2770 fn remap_component_any_type_id(
2774 &mut self,
2775 id: &mut ComponentAnyTypeId,
2776 map: &mut Remapping,
2777 ) -> bool {
2778 match id {
2779 ComponentAnyTypeId::Resource(id) => self.remap_resource_id(id, map),
2780 ComponentAnyTypeId::Defined(id) => self.remap_component_defined_type_id(id, map),
2781 ComponentAnyTypeId::Func(id) => self.remap_component_func_type_id(id, map),
2782 ComponentAnyTypeId::Instance(id) => self.remap_component_instance_type_id(id, map),
2783 ComponentAnyTypeId::Component(id) => self.remap_component_type_id(id, map),
2784 }
2785 }
2786
2787 fn remap_resource_id(&mut self, id: &mut AliasableResourceId, map: &Remapping) -> bool {
2790 if let Some(changed) = map.remap_id(id) {
2791 return changed;
2792 }
2793
2794 match map.resources.get(&id.resource()) {
2795 None => false,
2796 Some(new_id) => {
2797 *id.resource_mut() = *new_id;
2798 true
2799 }
2800 }
2801 }
2802
2803 fn remap_component_type_id(&mut self, id: &mut ComponentTypeId, map: &mut Remapping) -> bool {
2807 if let Some(changed) = map.remap_id(id) {
2808 return changed;
2809 }
2810
2811 let mut any_changed = false;
2812 let mut ty = self[*id].clone();
2813 for ty in ty.imports.values_mut().chain(ty.exports.values_mut()) {
2814 any_changed |= self.remap_component_entity(ty, map);
2815 }
2816 for (id, _) in ty
2817 .imported_resources
2818 .iter_mut()
2819 .chain(&mut ty.defined_resources)
2820 {
2821 if let Some(new) = map.resources.get(id) {
2822 *id = *new;
2823 any_changed = true;
2824 }
2825 }
2826 Self::map_map(&mut ty.explicit_resources, &mut any_changed, map);
2827 self.insert_if_any_changed(map, any_changed, id, ty)
2828 }
2829
2830 fn remap_component_defined_type_id(
2834 &mut self,
2835 id: &mut ComponentDefinedTypeId,
2836 map: &mut Remapping,
2837 ) -> bool {
2838 if let Some(changed) = map.remap_id(id) {
2839 return changed;
2840 }
2841
2842 let mut any_changed = false;
2843 let mut tmp = self[*id].clone();
2844 match &mut tmp {
2845 ComponentDefinedType::Primitive(_)
2846 | ComponentDefinedType::Flags(_)
2847 | ComponentDefinedType::Enum(_) => {}
2848 ComponentDefinedType::Record(r) => {
2849 for ty in r.fields.values_mut() {
2850 any_changed |= self.remap_valtype(ty, map);
2851 }
2852 }
2853 ComponentDefinedType::Tuple(r) => {
2854 for ty in r.types.iter_mut() {
2855 any_changed |= self.remap_valtype(ty, map);
2856 }
2857 }
2858 ComponentDefinedType::Variant(r) => {
2859 for ty in r.cases.values_mut() {
2860 if let Some(ty) = &mut ty.ty {
2861 any_changed |= self.remap_valtype(ty, map);
2862 }
2863 }
2864 }
2865 ComponentDefinedType::List(ty)
2866 | ComponentDefinedType::FixedLengthList(ty, _)
2867 | ComponentDefinedType::Option(ty) => {
2868 any_changed |= self.remap_valtype(ty, map);
2869 }
2870 ComponentDefinedType::Map(k, v) => {
2871 any_changed |= self.remap_valtype(k, map);
2872 any_changed |= self.remap_valtype(v, map);
2873 }
2874 ComponentDefinedType::Result { ok, err } => {
2875 if let Some(ok) = ok {
2876 any_changed |= self.remap_valtype(ok, map);
2877 }
2878 if let Some(err) = err {
2879 any_changed |= self.remap_valtype(err, map);
2880 }
2881 }
2882 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2883 any_changed |= self.remap_resource_id(id, map);
2884 }
2885 ComponentDefinedType::Future(ty) | ComponentDefinedType::Stream(ty) => {
2886 if let Some(ty) = ty {
2887 any_changed |= self.remap_valtype(ty, map);
2888 }
2889 }
2890 }
2891 self.insert_if_any_changed(map, any_changed, id, tmp)
2892 }
2893
2894 fn remap_component_instance_type_id(
2898 &mut self,
2899 id: &mut ComponentInstanceTypeId,
2900 map: &mut Remapping,
2901 ) -> bool {
2902 if let Some(changed) = map.remap_id(id) {
2903 return changed;
2904 }
2905
2906 let mut any_changed = false;
2907 let mut tmp = self[*id].clone();
2908 for ty in tmp.exports.values_mut() {
2909 any_changed |= self.remap_component_entity(ty, map);
2910 }
2911 for id in tmp.defined_resources.iter_mut() {
2912 if let Some(new) = map.resources.get(id) {
2913 *id = *new;
2914 any_changed = true;
2915 }
2916 }
2917 Self::map_map(&mut tmp.explicit_resources, &mut any_changed, map);
2918 self.insert_if_any_changed(map, any_changed, id, tmp)
2919 }
2920
2921 fn remap_component_func_type_id(
2925 &mut self,
2926 id: &mut ComponentFuncTypeId,
2927 map: &mut Remapping,
2928 ) -> bool {
2929 if let Some(changed) = map.remap_id(id) {
2930 return changed;
2931 }
2932
2933 let mut any_changed = false;
2934 let mut tmp = self[*id].clone();
2935 for ty in tmp
2936 .params
2937 .iter_mut()
2938 .map(|(_, ty)| ty)
2939 .chain(&mut tmp.result)
2940 {
2941 any_changed |= self.remap_valtype(ty, map);
2942 }
2943 self.insert_if_any_changed(map, any_changed, id, tmp)
2944 }
2945
2946 fn remap_component_entity(
2948 &mut self,
2949 ty: &mut ComponentEntityType,
2950 map: &mut Remapping,
2951 ) -> bool {
2952 match ty {
2953 ComponentEntityType::Module(_) => {
2954 false
2956 }
2957 ComponentEntityType::Func(id) => self.remap_component_func_type_id(id, map),
2958 ComponentEntityType::Instance(id) => self.remap_component_instance_type_id(id, map),
2959 ComponentEntityType::Component(id) => self.remap_component_type_id(id, map),
2960 ComponentEntityType::Type {
2961 referenced,
2962 created,
2963 } => {
2964 let mut changed = self.remap_component_any_type_id(referenced, map);
2965 if *referenced == *created {
2966 *created = *referenced;
2967 } else {
2968 changed |= self.remap_component_any_type_id(created, map);
2969 }
2970 changed
2971 }
2972 ComponentEntityType::Value(ty) => self.remap_valtype(ty, map),
2973 }
2974 }
2975
2976 fn remap_valtype(&mut self, ty: &mut ComponentValType, map: &mut Remapping) -> bool {
2978 match ty {
2979 ComponentValType::Primitive(_) => false,
2980 ComponentValType::Type(id) => self.remap_component_defined_type_id(id, map),
2981 }
2982 }
2983}
2984
2985#[derive(Debug, Default)]
2988pub struct Remapping {
2989 pub(crate) resources: Map<ResourceId, ResourceId>,
2991
2992 types: Map<ComponentAnyTypeId, ComponentAnyTypeId>,
2996}
2997
2998impl Remap for TypeAlloc {
2999 fn push_ty<T>(&mut self, ty: T) -> T::Id
3000 where
3001 T: TypeData,
3002 {
3003 <TypeList>::push(self, ty)
3004 }
3005}
3006
3007impl Remapping {
3008 pub fn add(&mut self, old: ResourceId, new: ResourceId) {
3010 self.resources.insert(old, new);
3011 }
3012
3013 pub fn reset_type_cache(&mut self) {
3015 self.types.clear()
3016 }
3017
3018 fn remap_id<T>(&self, id: &mut T) -> Option<bool>
3019 where
3020 T: Copy + Into<ComponentAnyTypeId> + TryFrom<ComponentAnyTypeId>,
3021 T::Error: core::fmt::Debug,
3022 {
3023 let old: ComponentAnyTypeId = (*id).into();
3024 let new = self.types.get(&old)?;
3025 if *new == old {
3026 Some(false)
3027 } else {
3028 *id = T::try_from(*new).expect("should never remap across different kinds");
3029 Some(true)
3030 }
3031 }
3032}
3033
3034pub struct SubtypeCx<'a> {
3053 pub a: SubtypeArena<'a>,
3055 pub b: SubtypeArena<'a>,
3057}
3058
3059macro_rules! limits_match {
3060 ($a:expr, $b:expr) => {{
3061 let a = $a;
3062 let b = $b;
3063 a.initial >= b.initial
3064 && match b.maximum {
3065 Some(b_max) => match a.maximum {
3066 Some(a_max) => a_max <= b_max,
3067 None => false,
3068 },
3069 None => true,
3070 }
3071 }};
3072}
3073
3074impl<'a> SubtypeCx<'a> {
3075 pub fn new_with_refs(a: TypesRef<'a>, b: TypesRef<'a>) -> SubtypeCx<'a> {
3082 assert_eq!(a.id(), b.id());
3083 Self::new(a.list, b.list)
3084 }
3085
3086 pub(crate) fn new(a: &'a TypeList, b: &'a TypeList) -> SubtypeCx<'a> {
3087 SubtypeCx {
3088 a: SubtypeArena::new(a),
3089 b: SubtypeArena::new(b),
3090 }
3091 }
3092
3093 pub fn swap(&mut self) {
3095 mem::swap(&mut self.a, &mut self.b);
3096 }
3097
3098 fn with_checkpoint<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
3104 let a = self.a.list.checkpoint();
3105 let b = self.b.list.checkpoint();
3106 let result = f(self);
3107 self.a.list.reset_to_checkpoint(a);
3108 self.b.list.reset_to_checkpoint(b);
3109 result
3110 }
3111
3112 pub fn component_entity_type(
3116 &mut self,
3117 a: &ComponentEntityType,
3118 b: &ComponentEntityType,
3119 offset: usize,
3120 ) -> Result<()> {
3121 use ComponentEntityType::*;
3122
3123 match (a, b) {
3124 (Module(a), Module(b)) => self.module_type(*a, *b, offset),
3125 (Module(_), b) => bail!(offset, "expected {}, found module", b.desc()),
3126
3127 (Func(a), Func(b)) => self.component_func_type(*a, *b, offset),
3128 (Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3129
3130 (Value(a), Value(b)) => self.component_val_type(a, b, offset),
3131 (Value(_), b) => bail!(offset, "expected {}, found value", b.desc()),
3132
3133 (Type { referenced: a, .. }, Type { referenced: b, .. }) => {
3134 self.component_any_type_id(*a, *b, offset)
3135 }
3136 (Type { .. }, b) => bail!(offset, "expected {}, found type", b.desc()),
3137
3138 (Instance(a), Instance(b)) => self.component_instance_type(*a, *b, offset),
3139 (Instance(_), b) => bail!(offset, "expected {}, found instance", b.desc()),
3140
3141 (Component(a), Component(b)) => self.component_type(*a, *b, offset),
3142 (Component(_), b) => bail!(offset, "expected {}, found component", b.desc()),
3143 }
3144 }
3145
3146 pub fn component_type(
3150 &mut self,
3151 a: ComponentTypeId,
3152 b: ComponentTypeId,
3153 offset: usize,
3154 ) -> Result<()> {
3155 let b_imports = self.b[b]
3209 .imports
3210 .iter()
3211 .map(|(name, ty)| (name.clone(), *ty))
3212 .collect();
3213 self.swap();
3214 let mut import_mapping =
3215 self.open_instance_type(&b_imports, a, ExternKind::Import, offset)?;
3216 self.swap();
3217 self.with_checkpoint(|this| {
3218 let mut a_exports = this.a[a]
3219 .exports
3220 .iter()
3221 .map(|(name, ty)| (name.clone(), *ty))
3222 .collect::<IndexMap<_, _>>();
3223 for ty in a_exports.values_mut() {
3224 this.a.remap_component_entity(ty, &mut import_mapping);
3225 }
3226 this.open_instance_type(&a_exports, b, ExternKind::Export, offset)?;
3227 Ok(())
3228 })
3229 }
3230
3231 pub fn component_instance_type(
3235 &mut self,
3236 a_id: ComponentInstanceTypeId,
3237 b_id: ComponentInstanceTypeId,
3238 offset: usize,
3239 ) -> Result<()> {
3240 let a = &self.a[a_id];
3245 let b = &self.b[b_id];
3246
3247 let mut exports = Vec::with_capacity(b.exports.len());
3248 for (k, b) in b.exports.iter() {
3249 match a.exports.get(k) {
3250 Some(a) => exports.push((*a, *b)),
3251 None => bail!(offset, "missing expected export `{k}`"),
3252 }
3253 }
3254 for (i, (a, b)) in exports.iter().enumerate() {
3255 let err = match self.component_entity_type(a, b, offset) {
3256 Ok(()) => continue,
3257 Err(e) => e,
3258 };
3259 let (name, _) = self.b[b_id].exports.get_index(i).unwrap();
3262 return Err(err.with_context(|| format!("type mismatch in instance export `{name}`")));
3263 }
3264 Ok(())
3265 }
3266
3267 pub fn component_func_type(
3271 &mut self,
3272 a: ComponentFuncTypeId,
3273 b: ComponentFuncTypeId,
3274 offset: usize,
3275 ) -> Result<()> {
3276 let a = &self.a[a];
3277 let b = &self.b[b];
3278
3279 if a.async_ != b.async_ {
3280 let a_desc = if a.async_ { "async" } else { "sync" };
3281 let b_desc = if b.async_ { "async" } else { "sync" };
3282 bail!(
3283 offset,
3284 "expected {a_desc} function, found {b_desc} function",
3285 );
3286 }
3287
3288 if a.params.len() != b.params.len() {
3319 bail!(
3320 offset,
3321 "expected {} parameters, found {}",
3322 b.params.len(),
3323 a.params.len(),
3324 );
3325 }
3326 for ((an, a), (bn, b)) in a.params.iter().zip(b.params.iter()) {
3327 if an != bn {
3328 bail!(offset, "expected parameter named `{bn}`, found `{an}`");
3329 }
3330 self.component_val_type(a, b, offset)
3331 .with_context(|| format!("type mismatch in function parameter `{an}`"))?;
3332 }
3333
3334 match (&a.result, &b.result) {
3335 (Some(a), Some(b)) => self
3336 .component_val_type(a, b, offset)
3337 .with_context(|| "type mismatch with result type")?,
3338 (None, None) => {}
3339
3340 (Some(_), None) => bail!(offset, "expected a result, found none"),
3341 (None, Some(_)) => bail!(offset, "expected no result, found one"),
3342 }
3343 Ok(())
3344 }
3345
3346 pub fn module_type(
3350 &mut self,
3351 a: ComponentCoreModuleTypeId,
3352 b: ComponentCoreModuleTypeId,
3353 offset: usize,
3354 ) -> Result<()> {
3355 self.swap();
3361 let a_imports = &self.b[a].imports;
3362 let b_imports = &self.a[b].imports;
3363 for (k, a) in a_imports {
3364 match b_imports.get(k) {
3365 Some(b) => self
3366 .entity_type(b, a, offset)
3367 .with_context(|| format!("type mismatch in import `{}::{}`", k.0, k.1))?,
3368 None => bail!(offset, "missing expected import `{}::{}`", k.0, k.1),
3369 }
3370 }
3371 self.swap();
3372 let a = &self.a[a];
3373 let b = &self.b[b];
3374 for (k, b) in b.exports.iter() {
3375 match a.exports.get(k) {
3376 Some(a) => self
3377 .entity_type(a, b, offset)
3378 .with_context(|| format!("type mismatch in export `{k}`"))?,
3379 None => bail!(offset, "missing expected export `{k}`"),
3380 }
3381 }
3382 Ok(())
3383 }
3384
3385 pub fn component_any_type_id(
3389 &mut self,
3390 a: ComponentAnyTypeId,
3391 b: ComponentAnyTypeId,
3392 offset: usize,
3393 ) -> Result<()> {
3394 match (a, b) {
3395 (ComponentAnyTypeId::Resource(a), ComponentAnyTypeId::Resource(b)) => {
3396 if a.resource() == b.resource() {
3397 Ok(())
3398 } else {
3399 bail!(
3400 offset,
3401 "resource types are not the same ({:?} vs. {:?})",
3402 a.resource(),
3403 b.resource()
3404 )
3405 }
3406 }
3407 (ComponentAnyTypeId::Resource(_), b) => {
3408 bail!(offset, "expected {}, found resource", b.desc())
3409 }
3410 (ComponentAnyTypeId::Defined(a), ComponentAnyTypeId::Defined(b)) => {
3411 self.component_defined_type(a, b, offset)
3412 }
3413 (ComponentAnyTypeId::Defined(_), b) => {
3414 bail!(offset, "expected {}, found defined type", b.desc())
3415 }
3416
3417 (ComponentAnyTypeId::Func(a), ComponentAnyTypeId::Func(b)) => {
3418 self.component_func_type(a, b, offset)
3419 }
3420 (ComponentAnyTypeId::Func(_), b) => {
3421 bail!(offset, "expected {}, found func type", b.desc())
3422 }
3423
3424 (ComponentAnyTypeId::Instance(a), ComponentAnyTypeId::Instance(b)) => {
3425 self.component_instance_type(a, b, offset)
3426 }
3427 (ComponentAnyTypeId::Instance(_), b) => {
3428 bail!(offset, "expected {}, found instance type", b.desc())
3429 }
3430
3431 (ComponentAnyTypeId::Component(a), ComponentAnyTypeId::Component(b)) => {
3432 self.component_type(a, b, offset)
3433 }
3434 (ComponentAnyTypeId::Component(_), b) => {
3435 bail!(offset, "expected {}, found component type", b.desc())
3436 }
3437 }
3438 }
3439
3440 pub fn open_instance_type(
3464 &mut self,
3465 a: &IndexMap<String, ComponentEntityType>,
3466 b: ComponentTypeId,
3467 kind: ExternKind,
3468 offset: usize,
3469 ) -> Result<Remapping> {
3470 let component_type = &self.b[b];
3500 let entities = match kind {
3501 ExternKind::Import => &component_type.imports,
3502 ExternKind::Export => &component_type.exports,
3503 };
3504 let resources = match kind {
3505 ExternKind::Import => &component_type.imported_resources,
3506 ExternKind::Export => &component_type.defined_resources,
3507 };
3508 let mut mapping = Remapping::default();
3509 'outer: for (resource, path) in resources.iter() {
3510 let (name, ty) = entities.get_index(path[0]).unwrap();
3513 let mut ty = *ty;
3514 let mut arg = a.get(name);
3515
3516 for i in path.iter().skip(1).copied() {
3520 let id = match ty {
3521 ComponentEntityType::Instance(id) => id,
3522 _ => unreachable!(),
3523 };
3524 let (name, next_ty) = self.b[id].exports.get_index(i).unwrap();
3525 ty = *next_ty;
3526 arg = match arg {
3527 Some(ComponentEntityType::Instance(id)) => self.a[*id].exports.get(name),
3528 _ => continue 'outer,
3529 };
3530 }
3531
3532 if cfg!(debug_assertions) {
3535 let id = match ty {
3536 ComponentEntityType::Type { created, .. } => match created {
3537 ComponentAnyTypeId::Resource(id) => id.resource(),
3538 _ => unreachable!(),
3539 },
3540 _ => unreachable!(),
3541 };
3542 assert_eq!(id, *resource);
3543 }
3544
3545 if let Some(ComponentEntityType::Type { created, .. }) = arg {
3549 if let ComponentAnyTypeId::Resource(r) = created {
3550 mapping.resources.insert(*resource, r.resource());
3551 }
3552 }
3553 }
3554
3555 let mut to_typecheck = Vec::new();
3567 for (name, expected) in entities.iter() {
3568 match a.get(name) {
3569 Some(arg) => to_typecheck.push((*arg, *expected)),
3570 None => bail!(offset, "missing {} named `{name}`", kind.desc()),
3571 }
3572 }
3573 let mut type_map = Map::default();
3574 for (i, (actual, expected)) in to_typecheck.into_iter().enumerate() {
3575 let result = self.with_checkpoint(|this| {
3576 let mut expected = expected;
3577 this.b.remap_component_entity(&mut expected, &mut mapping);
3578 mapping.types.clear();
3579 this.component_entity_type(&actual, &expected, offset)
3580 });
3581 let err = match result {
3582 Ok(()) => {
3583 self.register_type_renamings(actual, expected, &mut type_map);
3589 continue;
3590 }
3591 Err(e) => e,
3592 };
3593
3594 let component_type = &self.b[b];
3597 let entities = match kind {
3598 ExternKind::Import => &component_type.imports,
3599 ExternKind::Export => &component_type.exports,
3600 };
3601 let (name, _) = entities.get_index(i).unwrap();
3602 return Err(err.with_context(|| format!("type mismatch for {} `{name}`", kind.desc())));
3603 }
3604 mapping.types = type_map;
3605 Ok(mapping)
3606 }
3607
3608 pub(crate) fn entity_type(&self, a: &EntityType, b: &EntityType, offset: usize) -> Result<()> {
3609 match (a, b) {
3610 (EntityType::Func(a), EntityType::Func(b))
3611 | (EntityType::FuncExact(a), EntityType::Func(b)) => {
3612 self.core_func_type(*a, *b, offset)
3613 }
3614 (EntityType::Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3615 (EntityType::FuncExact(a), EntityType::FuncExact(b)) => {
3616 self.core_func_type(*b, *a, offset)?;
3617 self.core_func_type(*a, *b, offset)
3618 }
3619 (EntityType::FuncExact(_), b) => {
3620 bail!(offset, "expected {}, found func_exact", b.desc())
3621 }
3622 (EntityType::Table(a), EntityType::Table(b)) => Self::table_type(a, b, offset),
3623 (EntityType::Table(_), b) => bail!(offset, "expected {}, found table", b.desc()),
3624 (EntityType::Memory(a), EntityType::Memory(b)) => Self::memory_type(a, b, offset),
3625 (EntityType::Memory(_), b) => bail!(offset, "expected {}, found memory", b.desc()),
3626 (EntityType::Global(a), EntityType::Global(b)) => {
3627 if a.mutable != b.mutable {
3628 bail!(offset, "global types differ in mutability")
3629 }
3630 if a.content_type == b.content_type {
3631 Ok(())
3632 } else {
3633 bail!(
3634 offset,
3635 "expected global type {}, found {}",
3636 b.content_type,
3637 a.content_type,
3638 )
3639 }
3640 }
3641 (EntityType::Global(_), b) => bail!(offset, "expected {}, found global", b.desc()),
3642 (EntityType::Tag(a), EntityType::Tag(b)) => self.core_func_type(*a, *b, offset),
3643 (EntityType::Tag(_), b) => bail!(offset, "expected {}, found tag", b.desc()),
3644 }
3645 }
3646
3647 pub(crate) fn table_type(a: &TableType, b: &TableType, offset: usize) -> Result<()> {
3648 if a.element_type != b.element_type {
3649 bail!(
3650 offset,
3651 "expected table element type {}, found {}",
3652 b.element_type,
3653 a.element_type,
3654 )
3655 }
3656 if a.shared != b.shared {
3657 bail!(offset, "mismatch in the shared flag for tables")
3658 }
3659 if limits_match!(a, b) {
3660 Ok(())
3661 } else {
3662 bail!(offset, "mismatch in table limits")
3663 }
3664 }
3665
3666 pub(crate) fn memory_type(a: &MemoryType, b: &MemoryType, offset: usize) -> Result<()> {
3667 if a.shared != b.shared {
3668 bail!(offset, "mismatch in the shared flag for memories")
3669 }
3670 if a.memory64 != b.memory64 {
3671 bail!(offset, "mismatch in index type used for memories")
3672 }
3673 if limits_match!(a, b) {
3674 Ok(())
3675 } else {
3676 bail!(offset, "mismatch in memory limits")
3677 }
3678 }
3679
3680 fn core_func_type(&self, a: CoreTypeId, b: CoreTypeId, offset: usize) -> Result<()> {
3681 debug_assert!(self.a.get(a).is_some());
3682 debug_assert!(self.b.get(b).is_some());
3683 if self.a.id_is_subtype(a, b) {
3684 debug_assert!(self.a.get(b).is_some());
3685 debug_assert!(self.b.get(a).is_some());
3686 Ok(())
3687 } else {
3688 bail!(
3689 offset,
3690 "expected: {}\n\
3691 found: {}",
3692 self.b[b],
3693 self.a[a],
3694 )
3695 }
3696 }
3697
3698 pub(crate) fn component_val_type(
3699 &self,
3700 a: &ComponentValType,
3701 b: &ComponentValType,
3702 offset: usize,
3703 ) -> Result<()> {
3704 match (a, b) {
3705 (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
3706 self.primitive_val_type(*a, *b, offset)
3707 }
3708 (ComponentValType::Type(a), ComponentValType::Type(b)) => {
3709 self.component_defined_type(*a, *b, offset)
3710 }
3711 (ComponentValType::Primitive(a), ComponentValType::Type(b)) => match &self.b[*b] {
3712 ComponentDefinedType::Primitive(b) => self.primitive_val_type(*a, *b, offset),
3713 b => bail!(offset, "expected {}, found {a}", b.desc()),
3714 },
3715 (ComponentValType::Type(a), ComponentValType::Primitive(b)) => match &self.a[*a] {
3716 ComponentDefinedType::Primitive(a) => self.primitive_val_type(*a, *b, offset),
3717 a => bail!(offset, "expected {b}, found {}", a.desc()),
3718 },
3719 }
3720 }
3721
3722 fn component_defined_type(
3723 &self,
3724 a: ComponentDefinedTypeId,
3725 b: ComponentDefinedTypeId,
3726 offset: usize,
3727 ) -> Result<()> {
3728 use ComponentDefinedType::*;
3729
3730 match (&self.a[a], &self.b[b]) {
3734 (Primitive(a), Primitive(b)) => self.primitive_val_type(*a, *b, offset),
3735 (Primitive(a), b) => bail!(offset, "expected {}, found {a}", b.desc()),
3736 (Record(a), Record(b)) => {
3737 if a.fields.len() != b.fields.len() {
3738 bail!(
3739 offset,
3740 "expected {} fields, found {}",
3741 b.fields.len(),
3742 a.fields.len(),
3743 );
3744 }
3745
3746 for ((aname, a), (bname, b)) in a.fields.iter().zip(b.fields.iter()) {
3747 if aname != bname {
3748 bail!(offset, "expected field name `{bname}`, found `{aname}`");
3749 }
3750 self.component_val_type(a, b, offset)
3751 .with_context(|| format!("type mismatch in record field `{aname}`"))?;
3752 }
3753 Ok(())
3754 }
3755 (Record(_), b) => bail!(offset, "expected {}, found record", b.desc()),
3756 (Variant(a), Variant(b)) => {
3757 if a.cases.len() != b.cases.len() {
3758 bail!(
3759 offset,
3760 "expected {} cases, found {}",
3761 b.cases.len(),
3762 a.cases.len(),
3763 );
3764 }
3765 for ((aname, a), (bname, b)) in a.cases.iter().zip(b.cases.iter()) {
3766 if aname != bname {
3767 bail!(offset, "expected case named `{bname}`, found `{aname}`");
3768 }
3769 match (&a.ty, &b.ty) {
3770 (Some(a), Some(b)) => self
3771 .component_val_type(a, b, offset)
3772 .with_context(|| format!("type mismatch in variant case `{aname}`"))?,
3773 (None, None) => {}
3774 (None, Some(_)) => {
3775 bail!(offset, "expected case `{aname}` to have a type, found none")
3776 }
3777 (Some(_), None) => bail!(offset, "expected case `{aname}` to have no type"),
3778 }
3779 }
3780 Ok(())
3781 }
3782 (Variant(_), b) => bail!(offset, "expected {}, found variant", b.desc()),
3783 (List(a), List(b)) | (Option(a), Option(b)) => self.component_val_type(a, b, offset),
3784 (List(_), b) => bail!(offset, "expected {}, found list", b.desc()),
3785 (Map(ak, av), Map(bk, bv)) => {
3786 self.component_val_type(ak, bk, offset)
3787 .with_context(|| "type mismatch in map key")?;
3788 self.component_val_type(av, bv, offset)
3789 .with_context(|| "type mismatch in map value")
3790 }
3791 (Map(_, _), b) => bail!(offset, "expected {}, found map", b.desc()),
3792 (FixedLengthList(a, asize), FixedLengthList(b, bsize)) => {
3793 if asize != bsize {
3794 bail!(offset, "expected fixed-length {bsize}, found size {asize}")
3795 } else {
3796 self.component_val_type(a, b, offset)
3797 }
3798 }
3799 (FixedLengthList(_, _), b) => bail!(offset, "expected {}, found list", b.desc()),
3800 (Option(_), b) => bail!(offset, "expected {}, found option", b.desc()),
3801 (Tuple(a), Tuple(b)) => {
3802 if a.types.len() != b.types.len() {
3803 bail!(
3804 offset,
3805 "expected {} types, found {}",
3806 b.types.len(),
3807 a.types.len(),
3808 );
3809 }
3810 for (i, (a, b)) in a.types.iter().zip(b.types.iter()).enumerate() {
3811 self.component_val_type(a, b, offset)
3812 .with_context(|| format!("type mismatch in tuple field {i}"))?;
3813 }
3814 Ok(())
3815 }
3816 (Tuple(_), b) => bail!(offset, "expected {}, found tuple", b.desc()),
3817 (at @ Flags(a), Flags(b)) | (at @ Enum(a), Enum(b)) => {
3818 let desc = match at {
3819 Flags(_) => "flags",
3820 _ => "enum",
3821 };
3822 if a.len() == b.len() && a.iter().eq(b.iter()) {
3823 Ok(())
3824 } else {
3825 bail!(offset, "mismatch in {desc} elements")
3826 }
3827 }
3828 (Flags(_), b) => bail!(offset, "expected {}, found flags", b.desc()),
3829 (Enum(_), b) => bail!(offset, "expected {}, found enum", b.desc()),
3830 (Result { ok: ao, err: ae }, Result { ok: bo, err: be }) => {
3831 match (ao, bo) {
3832 (None, None) => {}
3833 (Some(a), Some(b)) => self
3834 .component_val_type(a, b, offset)
3835 .with_context(|| "type mismatch in ok variant")?,
3836 (None, Some(_)) => bail!(offset, "expected ok type, but found none"),
3837 (Some(_), None) => bail!(offset, "expected ok type to not be present"),
3838 }
3839 match (ae, be) {
3840 (None, None) => {}
3841 (Some(a), Some(b)) => self
3842 .component_val_type(a, b, offset)
3843 .with_context(|| "type mismatch in err variant")?,
3844 (None, Some(_)) => bail!(offset, "expected err type, but found none"),
3845 (Some(_), None) => bail!(offset, "expected err type to not be present"),
3846 }
3847 Ok(())
3848 }
3849 (Result { .. }, b) => bail!(offset, "expected {}, found result", b.desc()),
3850 (Own(a), Own(b)) | (Borrow(a), Borrow(b)) => {
3851 if a.resource() == b.resource() {
3852 Ok(())
3853 } else {
3854 bail!(offset, "resource types are not the same")
3855 }
3856 }
3857 (Own(_), b) => bail!(offset, "expected {}, found own", b.desc()),
3858 (Borrow(_), b) => bail!(offset, "expected {}, found borrow", b.desc()),
3859 (Future(a), Future(b)) => match (a, b) {
3860 (None, None) => Ok(()),
3861 (Some(a), Some(b)) => self
3862 .component_val_type(a, b, offset)
3863 .with_context(|| "type mismatch in future"),
3864 (None, Some(_)) => bail!(offset, "expected future type, but found none"),
3865 (Some(_), None) => bail!(offset, "expected future type to not be present"),
3866 },
3867 (Future(_), b) => bail!(offset, "expected {}, found future", b.desc()),
3868 (Stream(a), Stream(b)) => match (a, b) {
3869 (None, None) => Ok(()),
3870 (Some(a), Some(b)) => self
3871 .component_val_type(a, b, offset)
3872 .with_context(|| "type mismatch in stream"),
3873 (None, Some(_)) => bail!(offset, "expected stream type, but found none"),
3874 (Some(_), None) => bail!(offset, "expected stream type to not be present"),
3875 },
3876 (Stream(_), b) => bail!(offset, "expected {}, found stream", b.desc()),
3877 }
3878 }
3879
3880 fn primitive_val_type(
3881 &self,
3882 a: PrimitiveValType,
3883 b: PrimitiveValType,
3884 offset: usize,
3885 ) -> Result<()> {
3886 if a == b {
3893 Ok(())
3894 } else {
3895 bail!(offset, "expected primitive `{b}` found primitive `{a}`")
3896 }
3897 }
3898
3899 fn register_type_renamings(
3900 &self,
3901 actual: ComponentEntityType,
3902 expected: ComponentEntityType,
3903 type_map: &mut Map<ComponentAnyTypeId, ComponentAnyTypeId>,
3904 ) {
3905 match (expected, actual) {
3906 (
3907 ComponentEntityType::Type {
3908 created: expected, ..
3909 },
3910 ComponentEntityType::Type {
3911 created: actual, ..
3912 },
3913 ) => {
3914 let prev = type_map.insert(expected, actual);
3915 assert!(prev.is_none());
3916 }
3917 (ComponentEntityType::Instance(expected), ComponentEntityType::Instance(actual)) => {
3918 let actual = &self.a[actual];
3919 for (name, expected) in self.b[expected].exports.iter() {
3920 let actual = actual.exports[name];
3921 self.register_type_renamings(actual, *expected, type_map);
3922 }
3923 }
3924 _ => {}
3925 }
3926 }
3927}
3928
3929pub struct SubtypeArena<'a> {
3939 types: &'a TypeList,
3940 list: TypeList,
3941}
3942
3943impl<'a> SubtypeArena<'a> {
3944 fn new(types: &'a TypeList) -> SubtypeArena<'a> {
3945 SubtypeArena {
3946 types,
3947 list: TypeList::default(),
3948 }
3949 }
3950
3951 fn get<T>(&self, id: T) -> Option<&T::Data>
3952 where
3953 T: TypeIdentifier,
3954 {
3955 let index = id.index();
3956 if index < T::list(self.types).len() {
3957 self.types.get(id)
3958 } else {
3959 let temp_index = index - T::list(self.types).len();
3960 let temp_index = u32::try_from(temp_index).unwrap();
3961 let temp_id = T::from_index(temp_index);
3962 self.list.get(temp_id)
3963 }
3964 }
3965
3966 fn id_is_subtype(&self, a: CoreTypeId, b: CoreTypeId) -> bool {
3969 self.get(a).is_some() && self.get(b).is_some() && {
3970 debug_assert!(a.index() < CoreTypeId::list(self.types).len());
3973 debug_assert!(b.index() < CoreTypeId::list(self.types).len());
3974 self.types.id_is_subtype(a, b)
3975 }
3976 }
3977}
3978
3979impl<T> Index<T> for SubtypeArena<'_>
3980where
3981 T: TypeIdentifier,
3982{
3983 type Output = T::Data;
3984
3985 fn index(&self, id: T) -> &T::Data {
3986 self.get(id).unwrap()
3987 }
3988}
3989
3990impl Remap for SubtypeArena<'_> {
3991 fn push_ty<T>(&mut self, ty: T) -> T::Id
3992 where
3993 T: TypeData,
3994 {
3995 assert!(
3996 !T::IS_CORE_SUB_TYPE,
3997 "cannot push core sub types into `SubtypeArena`s, that would break type canonicalization"
3998 );
3999 let index = T::Id::list(&self.list).len() + T::Id::list(self.types).len();
4000 let index = u32::try_from(index).unwrap();
4001 self.list.push(ty);
4002 T::Id::from_index(index)
4003 }
4004}
4005
4006pub(crate) trait Context {
4009 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
4010 where
4011 S: Into<String>;
4012}
4013
4014impl<T> Context for Result<T> {
4015 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
4016 where
4017 S: Into<String>,
4018 {
4019 match self {
4020 Ok(val) => Ok(val),
4021 Err(e) => Err(e.with_context(context)),
4022 }
4023 }
4024}
4025
4026impl Context for BinaryReaderError {
4027 fn with_context<S>(mut self, context: impl FnOnce() -> S) -> Self
4028 where
4029 S: Into<String>,
4030 {
4031 self.add_context(context().into());
4032 self
4033 }
4034}