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 pub refines: Option<KebabString>,
1351}
1352
1353#[derive(Debug, Clone)]
1355pub struct RecordType {
1356 pub(crate) info: TypeInfo,
1358 pub fields: IndexMap<KebabString, ComponentValType>,
1360}
1361
1362impl RecordType {
1363 fn lower_gc(
1364 &self,
1365 types: &TypeList,
1366 abi: Abi,
1367 options: &CanonicalOptions,
1368 offset: usize,
1369 core: ArgOrField,
1370 ) -> Result<()> {
1371 lower_gc_product_type(
1372 self.fields.values(),
1373 types,
1374 abi,
1375 options,
1376 offset,
1377 core,
1378 "record",
1379 )
1380 }
1381}
1382
1383#[derive(Debug, Clone)]
1385pub struct VariantType {
1386 pub(crate) info: TypeInfo,
1388 pub cases: IndexMap<KebabString, VariantCase>,
1390}
1391
1392impl VariantType {
1393 fn lower_gc(
1394 &self,
1395 types: &TypeList,
1396 abi: Abi,
1397 options: &CanonicalOptions,
1398 offset: usize,
1399 core: ArgOrField,
1400 ) -> Result<()> {
1401 lower_gc_sum_type(types, abi, options, offset, core, "variant")
1402 }
1403}
1404
1405fn lower_gc_sum_type(
1408 types: &TypeList,
1409 _abi: Abi,
1410 _options: &CanonicalOptions,
1411 offset: usize,
1412 core: ArgOrField,
1413 kind: &str,
1414) -> Result<()> {
1415 if let Some(id) = core.as_concrete_ref() {
1416 if let CompositeInnerType::Struct(ty) = &types[id].composite_type.inner {
1417 if ty.fields.is_empty() {
1418 return Ok(());
1419 }
1420 }
1421 }
1422
1423 bail!(
1424 offset,
1425 "expected to lower component `{kind}` type to core `(ref null? (struct))`, \
1426 but found `{core}`",
1427 )
1428}
1429
1430#[derive(Debug, Clone)]
1432pub struct TupleType {
1433 pub(crate) info: TypeInfo,
1435 pub types: Box<[ComponentValType]>,
1437}
1438
1439impl TupleType {
1440 fn lower_gc(
1441 &self,
1442 types: &TypeList,
1443 abi: Abi,
1444 options: &CanonicalOptions,
1445 offset: usize,
1446 core: ArgOrField,
1447 ) -> Result<()> {
1448 lower_gc_product_type(
1449 self.types.iter(),
1450 types,
1451 abi,
1452 options,
1453 offset,
1454 core,
1455 "tuple",
1456 )
1457 }
1458}
1459
1460#[derive(Debug, Clone)]
1462pub enum ComponentDefinedType {
1463 Primitive(PrimitiveValType),
1465 Record(RecordType),
1467 Variant(VariantType),
1469 List(ComponentValType),
1471 FixedSizeList(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::FixedSizeList(ty, _) | Self::Option(ty) => ty.info(types),
1514 Self::Result { ok, err } => {
1515 let default = TypeInfo::new();
1516 let mut info = ok.map(|ty| ty.type_info(types)).unwrap_or(default);
1517 info.combine(err.map(|ty| ty.type_info(types)).unwrap_or(default), 0)
1518 .unwrap();
1519 info
1520 }
1521 }
1522 }
1523}
1524
1525impl ComponentDefinedType {
1526 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
1527 match self {
1528 Self::Primitive(ty) => ty.contains_ptr(),
1529 Self::Record(r) => r.fields.values().any(|ty| ty.contains_ptr(types)),
1530 Self::Variant(v) => v
1531 .cases
1532 .values()
1533 .any(|case| case.ty.map(|ty| ty.contains_ptr(types)).unwrap_or(false)),
1534 Self::List(_) => true,
1535 Self::Tuple(t) => t.types.iter().any(|ty| ty.contains_ptr(types)),
1536 Self::Flags(_)
1537 | Self::Enum(_)
1538 | Self::Own(_)
1539 | Self::Borrow(_)
1540 | Self::Future(_)
1541 | Self::Stream(_) => false,
1542 Self::Option(ty) | Self::FixedSizeList(ty, _) => ty.contains_ptr(types),
1543 Self::Result { ok, err } => {
1544 ok.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1545 || err.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1546 }
1547 }
1548 }
1549
1550 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1551 match self {
1552 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1553 Self::Record(r) => r
1554 .fields
1555 .iter()
1556 .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1557 Self::Variant(v) => Self::push_variant_wasm_types(
1558 v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1559 types,
1560 lowered_types,
1561 ),
1562 Self::List(_) => {
1563 lowered_types.try_push(ValType::I32) && lowered_types.try_push(ValType::I32)
1564 }
1565 Self::FixedSizeList(ty, length) => {
1566 (0..*length).all(|_n| ty.push_wasm_types(types, lowered_types))
1567 }
1568 Self::Tuple(t) => t
1569 .types
1570 .iter()
1571 .all(|ty| ty.push_wasm_types(types, lowered_types)),
1572 Self::Flags(names) => {
1573 (0..(names.len() + 31) / 32).all(|_| lowered_types.try_push(ValType::I32))
1574 }
1575 Self::Enum(_) | Self::Own(_) | Self::Borrow(_) | Self::Future(_) | Self::Stream(_) => {
1576 lowered_types.try_push(ValType::I32)
1577 }
1578 Self::Option(ty) => {
1579 Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1580 }
1581 Self::Result { ok, err } => {
1582 Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1583 }
1584 }
1585 }
1586
1587 fn push_variant_wasm_types<'a>(
1588 cases: impl Iterator<Item = &'a ComponentValType>,
1589 types: &TypeList,
1590 lowered_types: &mut LoweredTypes,
1591 ) -> bool {
1592 if !lowered_types.try_push(ValType::I32) {
1594 return false;
1595 }
1596
1597 let start = lowered_types.len();
1598
1599 for ty in cases {
1600 let mut temp = LoweredTypes::new(lowered_types.max);
1601
1602 if !ty.push_wasm_types(types, &mut temp) {
1603 return false;
1604 }
1605
1606 for (i, ty) in temp.iter().enumerate() {
1607 match lowered_types.get_mut(start + i) {
1608 Some(prev) => *prev = Self::join_types(*prev, ty),
1609 None => {
1610 if !lowered_types.try_push(ty) {
1611 return false;
1612 }
1613 }
1614 }
1615 }
1616 }
1617
1618 true
1619 }
1620
1621 fn join_types(a: ValType, b: ValType) -> ValType {
1622 use ValType::*;
1623
1624 match (a, b) {
1625 (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1626 (I32, F32) | (F32, I32) => I32,
1627 (_, I64 | F64) | (I64 | F64, _) => I64,
1628 _ => panic!("unexpected wasm type for canonical ABI"),
1629 }
1630 }
1631
1632 fn desc(&self) -> &'static str {
1633 match self {
1634 ComponentDefinedType::Record(_) => "record",
1635 ComponentDefinedType::Primitive(_) => "primitive",
1636 ComponentDefinedType::Variant(_) => "variant",
1637 ComponentDefinedType::Tuple(_) => "tuple",
1638 ComponentDefinedType::Enum(_) => "enum",
1639 ComponentDefinedType::Flags(_) => "flags",
1640 ComponentDefinedType::Option(_) => "option",
1641 ComponentDefinedType::List(_) => "list",
1642 ComponentDefinedType::FixedSizeList(_, _) => "fixed size list",
1643 ComponentDefinedType::Result { .. } => "result",
1644 ComponentDefinedType::Own(_) => "own",
1645 ComponentDefinedType::Borrow(_) => "borrow",
1646 ComponentDefinedType::Future(_) => "future",
1647 ComponentDefinedType::Stream(_) => "stream",
1648 }
1649 }
1650
1651 fn lower_gc(
1652 &self,
1653 types: &TypeList,
1654 abi: Abi,
1655 options: &CanonicalOptions,
1656 offset: usize,
1657 core: ArgOrField,
1658 ) -> Result<()> {
1659 match self {
1660 ComponentDefinedType::Primitive(ty) => ty.lower_gc(types, abi, options, offset, core),
1661
1662 ComponentDefinedType::Record(ty) => ty.lower_gc(types, abi, options, offset, core),
1663
1664 ComponentDefinedType::Variant(ty) => ty.lower_gc(types, abi, options, offset, core),
1665
1666 ComponentDefinedType::List(ty) | ComponentDefinedType::FixedSizeList(ty, _) => {
1667 let id = match core.as_concrete_ref() {
1668 Some(id) => id,
1669 None => bail!(
1670 offset,
1671 "expected to lower component `list` type into `(ref null? (array ...))`, but \
1672 found `{core}`",
1673 ),
1674 };
1675 let array_ty = match types[id].composite_type.inner {
1676 CompositeInnerType::Array(ty) => ty,
1677 _ => bail!(
1678 offset,
1679 "expected to lower component `list` type into `(ref null? (array ...))`, but \
1680 found `{core}`",
1681 ),
1682 };
1683 ty.lower_gc(types, abi, options, offset, array_ty.0.element_type.into())
1684 }
1685
1686 ComponentDefinedType::Tuple(ty) => ty.lower_gc(types, abi, options, offset, core),
1687
1688 ComponentDefinedType::Flags(flags) => {
1689 assert!(flags.len() <= 32, "required by validation");
1690 if core.as_val_type() == Some(ValType::I32) {
1691 Ok(())
1692 } else {
1693 bail!(
1694 offset,
1695 "expected to lower component `flags` type into core `i32` type, but \
1696 found `{core}`",
1697 )
1698 }
1699 }
1700
1701 ComponentDefinedType::Enum(_) => {
1702 if core.as_val_type() == Some(ValType::I32) {
1703 Ok(())
1704 } else {
1705 bail!(
1706 offset,
1707 "expected to lower component `enum` type into core `i32` type, but \
1708 found `{core}`",
1709 )
1710 }
1711 }
1712
1713 ComponentDefinedType::Option(_) => {
1714 lower_gc_sum_type(types, abi, options, offset, core, "option")
1715 }
1716
1717 ComponentDefinedType::Result { .. } => {
1718 lower_gc_sum_type(types, abi, options, offset, core, "result")
1719 }
1720
1721 ComponentDefinedType::Own(_)
1722 | ComponentDefinedType::Borrow(_)
1723 | ComponentDefinedType::Future(_)
1724 | ComponentDefinedType::Stream(_) => {
1725 if let Some(r) = core.as_ref_type() {
1726 if let HeapType::Abstract {
1727 shared: _,
1728 ty: AbstractHeapType::Extern,
1729 } = r.heap_type()
1730 {
1731 return Ok(());
1732 }
1733 }
1734 bail!(
1735 offset,
1736 "expected to lower component `{}` type into core `(ref null? extern)` type, but \
1737 found `{core}`",
1738 self.desc()
1739 )
1740 }
1741 }
1742 }
1743}
1744
1745fn lower_gc_product_type<'a, I>(
1748 fields: I,
1749 types: &TypeList,
1750 abi: Abi,
1751 options: &CanonicalOptions,
1752 offset: usize,
1753 core: ArgOrField,
1754 kind: &str,
1755) -> core::result::Result<(), BinaryReaderError>
1756where
1757 I: IntoIterator<Item = &'a ComponentValType>,
1758 I::IntoIter: ExactSizeIterator,
1759{
1760 let fields = fields.into_iter();
1761 let fields_len = fields.len();
1762
1763 if let Some(id) = core.as_concrete_ref() {
1764 if let CompositeInnerType::Struct(ty) = &types[id].composite_type.inner {
1765 ensure!(
1766 ty.fields.len() == fields_len,
1767 offset,
1768 "core `struct` has {} fields, but component `{kind}` has {fields_len} fields",
1769 ty.fields.len(),
1770 );
1771 for (core, comp) in ty.fields.iter().zip(fields) {
1772 comp.lower_gc(types, abi, options, offset, core.element_type.into())?;
1773 }
1774 return Ok(());
1775 }
1776 }
1777
1778 bail!(
1779 offset,
1780 "expected to lower component `{kind}` type to core `(ref null? (struct ...))`, \
1781 but found `{core}`",
1782 )
1783}
1784
1785#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
1788#[repr(packed(4))] pub struct ResourceId {
1790 globally_unique_id: usize,
1800
1801 contextually_unique_id: u32,
1810}
1811
1812impl<'a> TypesRef<'a> {
1813 pub fn core_type_at_in_component(&self, index: u32) -> ComponentCoreTypeId {
1824 match &self.kind {
1825 TypesRefKind::Module(_) => panic!("use `component_type_at_in_module` instead"),
1826 TypesRefKind::Component(component) => component.core_types[index as usize],
1827 }
1828 }
1829
1830 pub fn core_type_count_in_component(&self) -> u32 {
1835 match &self.kind {
1836 TypesRefKind::Module(_) => 0,
1837 TypesRefKind::Component(component) => component.core_types.len() as u32,
1838 }
1839 }
1840
1841 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1848 match &self.kind {
1849 TypesRefKind::Module(_) => panic!("not a component"),
1850 TypesRefKind::Component(component) => component.types[index as usize],
1851 }
1852 }
1853
1854 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1861 match self.component_any_type_at(index) {
1862 ComponentAnyTypeId::Component(id) => id,
1863 _ => panic!("not a component type"),
1864 }
1865 }
1866
1867 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1874 match self.component_any_type_at(index) {
1875 ComponentAnyTypeId::Defined(id) => id,
1876 _ => panic!("not a defined type"),
1877 }
1878 }
1879
1880 pub fn component_type_count(&self) -> u32 {
1882 match &self.kind {
1883 TypesRefKind::Module(_module) => 0,
1884 TypesRefKind::Component(component) => component.types.len() as u32,
1885 }
1886 }
1887
1888 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
1895 match &self.kind {
1896 TypesRefKind::Module(_) => panic!("not a component"),
1897 TypesRefKind::Component(component) => component.funcs[index as usize],
1898 }
1899 }
1900
1901 pub fn component_function_count(&self) -> u32 {
1903 match &self.kind {
1904 TypesRefKind::Module(_module) => 0,
1905 TypesRefKind::Component(component) => component.funcs.len() as u32,
1906 }
1907 }
1908
1909 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
1916 match &self.kind {
1917 TypesRefKind::Module(_) => panic!("not a component"),
1918 TypesRefKind::Component(component) => component.core_modules[index as usize],
1919 }
1920 }
1921
1922 pub fn module_count(&self) -> u32 {
1924 match &self.kind {
1925 TypesRefKind::Module(_module) => 0,
1926 TypesRefKind::Component(component) => component.core_modules.len() as u32,
1927 }
1928 }
1929
1930 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
1937 match &self.kind {
1938 TypesRefKind::Module(_) => panic!("not a component"),
1939 TypesRefKind::Component(component) => component.core_instances[index as usize],
1940 }
1941 }
1942
1943 pub fn core_instance_count(&self) -> u32 {
1945 match &self.kind {
1946 TypesRefKind::Module(_module) => 0,
1947 TypesRefKind::Component(component) => component.core_instances.len() as u32,
1948 }
1949 }
1950
1951 pub fn component_at(&self, index: u32) -> ComponentTypeId {
1958 match &self.kind {
1959 TypesRefKind::Module(_) => panic!("not a component"),
1960 TypesRefKind::Component(component) => component.components[index as usize],
1961 }
1962 }
1963
1964 pub fn component_count(&self) -> u32 {
1966 match &self.kind {
1967 TypesRefKind::Module(_module) => 0,
1968 TypesRefKind::Component(component) => component.components.len() as u32,
1969 }
1970 }
1971
1972 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
1979 match &self.kind {
1980 TypesRefKind::Module(_) => panic!("not a component"),
1981 TypesRefKind::Component(component) => component.instances[index as usize],
1982 }
1983 }
1984
1985 pub fn component_instance_count(&self) -> u32 {
1987 match &self.kind {
1988 TypesRefKind::Module(_module) => 0,
1989 TypesRefKind::Component(component) => component.instances.len() as u32,
1990 }
1991 }
1992
1993 pub fn value_at(&self, index: u32) -> ComponentValType {
2000 match &self.kind {
2001 TypesRefKind::Module(_) => panic!("not a component"),
2002 TypesRefKind::Component(component) => component.values[index as usize].0,
2003 }
2004 }
2005
2006 pub fn value_count(&self) -> u32 {
2008 match &self.kind {
2009 TypesRefKind::Module(_module) => 0,
2010 TypesRefKind::Component(component) => component.values.len() as u32,
2011 }
2012 }
2013
2014 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
2016 match &self.kind {
2017 TypesRefKind::Module(_) => None,
2018 TypesRefKind::Component(component) => Some(*component.imports.get(name)?),
2019 }
2020 }
2021
2022 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
2024 match &self.kind {
2025 TypesRefKind::Module(_) => None,
2026 TypesRefKind::Component(component) => Some(*component.exports.get(name)?),
2027 }
2028 }
2029
2030 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2034 where
2035 T: Aliasable,
2036 {
2037 self.list.peel_alias(ty)
2038 }
2039}
2040
2041impl Types {
2042 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
2051 self.as_ref().component_any_type_at(index)
2052 }
2053
2054 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
2060 self.as_ref().component_type_at(index)
2061 }
2062
2063 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
2070 self.as_ref().component_defined_type_at(index)
2071 }
2072
2073 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
2080 self.as_ref().component_function_at(index)
2081 }
2082
2083 pub fn component_function_count(&self) -> u32 {
2085 self.as_ref().component_function_count()
2086 }
2087
2088 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
2095 self.as_ref().module_at(index)
2096 }
2097
2098 pub fn module_count(&self) -> usize {
2100 match &self.kind {
2101 TypesKind::Module(_) => 0,
2102 TypesKind::Component(component) => component.core_modules.len(),
2103 }
2104 }
2105
2106 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
2113 self.as_ref().core_instance_at(index)
2114 }
2115
2116 pub fn core_instance_count(&self) -> usize {
2118 match &self.kind {
2119 TypesKind::Module(_) => 0,
2120 TypesKind::Component(component) => component.core_instances.len(),
2121 }
2122 }
2123
2124 pub fn component_at(&self, index: u32) -> ComponentTypeId {
2131 self.as_ref().component_at(index)
2132 }
2133
2134 pub fn component_count(&self) -> usize {
2136 match &self.kind {
2137 TypesKind::Module(_) => 0,
2138 TypesKind::Component(component) => component.components.len(),
2139 }
2140 }
2141
2142 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
2149 self.as_ref().component_instance_at(index)
2150 }
2151
2152 pub fn component_instance_count(&self) -> usize {
2154 match &self.kind {
2155 TypesKind::Module(_) => 0,
2156 TypesKind::Component(component) => component.instances.len(),
2157 }
2158 }
2159
2160 pub fn value_at(&self, index: u32) -> ComponentValType {
2167 self.as_ref().value_at(index)
2168 }
2169
2170 pub fn value_count(&self) -> usize {
2172 match &self.kind {
2173 TypesKind::Module(_) => 0,
2174 TypesKind::Component(component) => component.values.len(),
2175 }
2176 }
2177
2178 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
2180 self.as_ref().component_entity_type_of_import(name)
2181 }
2182
2183 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
2185 self.as_ref().component_entity_type_of_export(name)
2186 }
2187
2188 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2192 where
2193 T: Aliasable,
2194 {
2195 self.list.peel_alias(ty)
2196 }
2197}
2198
2199#[derive(Debug, Default)]
2201pub(crate) struct ComponentTypeList {
2202 alias_mappings: Map<u32, u32>,
2204 alias_counter: u32,
2206 alias_snapshots: Vec<TypeListAliasSnapshot>,
2208
2209 components: SnapshotList<ComponentType>,
2211 component_defined_types: SnapshotList<ComponentDefinedType>,
2212 component_values: SnapshotList<ComponentValType>,
2213 component_instances: SnapshotList<ComponentInstanceType>,
2214 component_funcs: SnapshotList<ComponentFuncType>,
2215 core_modules: SnapshotList<ModuleType>,
2216 core_instances: SnapshotList<InstanceType>,
2217}
2218
2219#[derive(Clone, Debug)]
2220struct TypeListAliasSnapshot {
2221 alias_counter: u32,
2223
2224 alias_mappings: Map<u32, u32>,
2226}
2227
2228struct TypeListCheckpoint {
2229 core_types: usize,
2230 components: usize,
2231 component_defined_types: usize,
2232 component_values: usize,
2233 component_instances: usize,
2234 component_funcs: usize,
2235 core_modules: usize,
2236 core_instances: usize,
2237 core_type_to_rec_group: usize,
2238 core_type_to_supertype: usize,
2239 core_type_to_depth: usize,
2240 rec_group_elements: usize,
2241 canonical_rec_groups: usize,
2242}
2243
2244impl TypeList {
2245 fn checkpoint(&self) -> TypeListCheckpoint {
2246 let TypeList {
2247 component:
2248 ComponentTypeList {
2249 alias_mappings: _,
2250 alias_counter: _,
2251 alias_snapshots: _,
2252 components,
2253 component_defined_types,
2254 component_values,
2255 component_instances,
2256 component_funcs,
2257 core_modules,
2258 core_instances,
2259 },
2260 core_types,
2261 core_type_to_rec_group,
2262 core_type_to_supertype,
2263 core_type_to_depth,
2264 rec_group_elements,
2265 canonical_rec_groups,
2266 } = self;
2267
2268 TypeListCheckpoint {
2269 core_types: core_types.len(),
2270 components: components.len(),
2271 component_defined_types: component_defined_types.len(),
2272 component_values: component_values.len(),
2273 component_instances: component_instances.len(),
2274 component_funcs: component_funcs.len(),
2275 core_modules: core_modules.len(),
2276 core_instances: core_instances.len(),
2277 core_type_to_rec_group: core_type_to_rec_group.len(),
2278 core_type_to_supertype: core_type_to_supertype.len(),
2279 core_type_to_depth: core_type_to_depth.as_ref().map(|m| m.len()).unwrap_or(0),
2280 rec_group_elements: rec_group_elements.len(),
2281 canonical_rec_groups: canonical_rec_groups.as_ref().map(|m| m.len()).unwrap_or(0),
2282 }
2283 }
2284
2285 fn reset_to_checkpoint(&mut self, checkpoint: TypeListCheckpoint) {
2286 let TypeList {
2287 component:
2288 ComponentTypeList {
2289 alias_mappings: _,
2290 alias_counter: _,
2291 alias_snapshots: _,
2292 components,
2293 component_defined_types,
2294 component_values,
2295 component_instances,
2296 component_funcs,
2297 core_modules,
2298 core_instances,
2299 },
2300 core_types,
2301 core_type_to_rec_group,
2302 core_type_to_supertype,
2303 core_type_to_depth,
2304 rec_group_elements,
2305 canonical_rec_groups,
2306 } = self;
2307
2308 core_types.truncate(checkpoint.core_types);
2309 components.truncate(checkpoint.components);
2310 component_defined_types.truncate(checkpoint.component_defined_types);
2311 component_values.truncate(checkpoint.component_values);
2312 component_instances.truncate(checkpoint.component_instances);
2313 component_funcs.truncate(checkpoint.component_funcs);
2314 core_modules.truncate(checkpoint.core_modules);
2315 core_instances.truncate(checkpoint.core_instances);
2316 core_type_to_rec_group.truncate(checkpoint.core_type_to_rec_group);
2317 core_type_to_supertype.truncate(checkpoint.core_type_to_supertype);
2318 rec_group_elements.truncate(checkpoint.rec_group_elements);
2319
2320 if let Some(core_type_to_depth) = core_type_to_depth {
2321 assert_eq!(
2322 core_type_to_depth.len(),
2323 checkpoint.core_type_to_depth,
2324 "checkpointing does not support resetting `core_type_to_depth` (it would require a \
2325 proper immutable and persistent hash map) so adding new groups is disallowed"
2326 );
2327 }
2328 if let Some(canonical_rec_groups) = canonical_rec_groups {
2329 assert_eq!(
2330 canonical_rec_groups.len(),
2331 checkpoint.canonical_rec_groups,
2332 "checkpointing does not support resetting `canonical_rec_groups` (it would require a \
2333 proper immutable and persistent hash map) so adding new groups is disallowed"
2334 );
2335 }
2336 }
2337
2338 pub fn with_unique<T>(&mut self, mut ty: T) -> T
2340 where
2341 T: Aliasable,
2342 {
2343 self.component
2344 .alias_mappings
2345 .insert(self.component.alias_counter, ty.alias_id());
2346 ty.set_alias_id(self.component.alias_counter);
2347 self.component.alias_counter += 1;
2348 ty
2349 }
2350
2351 pub fn peel_alias<T>(&self, mut ty: T) -> Option<T>
2355 where
2356 T: Aliasable,
2357 {
2358 let alias_id = ty.alias_id();
2359
2360 let i = match self
2367 .component
2368 .alias_snapshots
2369 .binary_search_by_key(&alias_id, |snapshot| snapshot.alias_counter)
2370 {
2371 Ok(_) => unreachable!(),
2372 Err(i) => i,
2373 };
2374
2375 ty.set_alias_id(match self.component.alias_snapshots.get(i) {
2379 Some(snapshot) => *snapshot.alias_mappings.get(&alias_id)?,
2380 None => *self.component.alias_mappings.get(&alias_id)?,
2381 });
2382 Some(ty)
2383 }
2384}
2385
2386impl ComponentTypeList {
2387 pub fn commit(&mut self) -> ComponentTypeList {
2388 let alias_counter = self.alias_counter;
2392 self.alias_counter += 1;
2393
2394 self.alias_snapshots.push(TypeListAliasSnapshot {
2395 alias_counter,
2396 alias_mappings: mem::take(&mut self.alias_mappings),
2397 });
2398
2399 ComponentTypeList {
2400 alias_mappings: Map::default(),
2401 alias_counter: self.alias_counter,
2402 alias_snapshots: self.alias_snapshots.clone(),
2403 components: self.components.commit(),
2404 component_defined_types: self.component_defined_types.commit(),
2405 component_values: self.component_values.commit(),
2406 component_instances: self.component_instances.commit(),
2407 component_funcs: self.component_funcs.commit(),
2408 core_modules: self.core_modules.commit(),
2409 core_instances: self.core_instances.commit(),
2410 }
2411 }
2412}
2413
2414pub(crate) struct ComponentTypeAlloc {
2415 globally_unique_id: usize,
2418
2419 next_resource_id: u32,
2422}
2423
2424impl Default for ComponentTypeAlloc {
2425 fn default() -> ComponentTypeAlloc {
2426 static NEXT_GLOBAL_ID: AtomicUsize = AtomicUsize::new(0);
2427 ComponentTypeAlloc {
2428 globally_unique_id: {
2429 let id = NEXT_GLOBAL_ID.fetch_add(1, Ordering::Relaxed);
2430 if id > usize::MAX - 10_000 {
2431 NEXT_GLOBAL_ID.store(usize::MAX - 10_000, Ordering::Relaxed);
2432 panic!("overflow on the global id counter");
2433 }
2434 id
2435 },
2436 next_resource_id: 0,
2437 }
2438 }
2439}
2440
2441impl TypeAlloc {
2442 pub fn alloc_resource_id(&mut self) -> AliasableResourceId {
2446 let contextually_unique_id = self.component_alloc.next_resource_id;
2447 self.component_alloc.next_resource_id = self
2448 .component_alloc
2449 .next_resource_id
2450 .checked_add(1)
2451 .unwrap();
2452 AliasableResourceId {
2453 id: ResourceId {
2454 globally_unique_id: self.component_alloc.globally_unique_id,
2455 contextually_unique_id,
2456 },
2457 alias_id: NO_ALIAS,
2458 }
2459 }
2460
2461 pub fn free_variables_any_type_id(
2468 &self,
2469 id: ComponentAnyTypeId,
2470 set: &mut IndexSet<ResourceId>,
2471 ) {
2472 match id {
2473 ComponentAnyTypeId::Resource(r) => {
2474 set.insert(r.resource());
2475 }
2476 ComponentAnyTypeId::Defined(id) => {
2477 self.free_variables_component_defined_type_id(id, set)
2478 }
2479 ComponentAnyTypeId::Func(id) => self.free_variables_component_func_type_id(id, set),
2480 ComponentAnyTypeId::Instance(id) => {
2481 self.free_variables_component_instance_type_id(id, set)
2482 }
2483 ComponentAnyTypeId::Component(id) => self.free_variables_component_type_id(id, set),
2484 }
2485 }
2486
2487 pub fn free_variables_component_defined_type_id(
2488 &self,
2489 id: ComponentDefinedTypeId,
2490 set: &mut IndexSet<ResourceId>,
2491 ) {
2492 match &self[id] {
2493 ComponentDefinedType::Primitive(_)
2494 | ComponentDefinedType::Flags(_)
2495 | ComponentDefinedType::Enum(_) => {}
2496 ComponentDefinedType::Record(r) => {
2497 for ty in r.fields.values() {
2498 self.free_variables_valtype(ty, set);
2499 }
2500 }
2501 ComponentDefinedType::Tuple(r) => {
2502 for ty in r.types.iter() {
2503 self.free_variables_valtype(ty, set);
2504 }
2505 }
2506 ComponentDefinedType::Variant(r) => {
2507 for ty in r.cases.values() {
2508 if let Some(ty) = &ty.ty {
2509 self.free_variables_valtype(ty, set);
2510 }
2511 }
2512 }
2513 ComponentDefinedType::List(ty)
2514 | ComponentDefinedType::FixedSizeList(ty, _)
2515 | ComponentDefinedType::Option(ty) => {
2516 self.free_variables_valtype(ty, set);
2517 }
2518 ComponentDefinedType::Result { ok, err } => {
2519 if let Some(ok) = ok {
2520 self.free_variables_valtype(ok, set);
2521 }
2522 if let Some(err) = err {
2523 self.free_variables_valtype(err, set);
2524 }
2525 }
2526 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2527 set.insert(id.resource());
2528 }
2529 ComponentDefinedType::Future(ty) => {
2530 if let Some(ty) = ty {
2531 self.free_variables_valtype(ty, set);
2532 }
2533 }
2534 ComponentDefinedType::Stream(ty) => {
2535 if let Some(ty) = ty {
2536 self.free_variables_valtype(ty, set);
2537 }
2538 }
2539 }
2540 }
2541
2542 pub fn free_variables_component_type_id(
2543 &self,
2544 id: ComponentTypeId,
2545 set: &mut IndexSet<ResourceId>,
2546 ) {
2547 let i = &self[id];
2548 for ty in i.imports.values().chain(i.exports.values()) {
2559 self.free_variables_component_entity(ty, set);
2560 }
2561 for (id, _path) in i.imported_resources.iter().chain(&i.defined_resources) {
2562 set.swap_remove(id);
2563 }
2564 }
2565
2566 pub fn free_variables_component_instance_type_id(
2567 &self,
2568 id: ComponentInstanceTypeId,
2569 set: &mut IndexSet<ResourceId>,
2570 ) {
2571 let i = &self[id];
2572 for ty in i.exports.values() {
2576 self.free_variables_component_entity(ty, set);
2577 }
2578 for id in i.defined_resources.iter() {
2579 set.swap_remove(id);
2580 }
2581 }
2582
2583 pub fn free_variables_component_func_type_id(
2584 &self,
2585 id: ComponentFuncTypeId,
2586 set: &mut IndexSet<ResourceId>,
2587 ) {
2588 let i = &self[id];
2589 for ty in i.params.iter().map(|(_, ty)| ty).chain(&i.result) {
2590 self.free_variables_valtype(ty, set);
2591 }
2592 }
2593
2594 pub fn free_variables_component_entity(
2596 &self,
2597 ty: &ComponentEntityType,
2598 set: &mut IndexSet<ResourceId>,
2599 ) {
2600 match ty {
2601 ComponentEntityType::Module(_) => {}
2602 ComponentEntityType::Func(id) => self.free_variables_component_func_type_id(*id, set),
2603 ComponentEntityType::Instance(id) => {
2604 self.free_variables_component_instance_type_id(*id, set)
2605 }
2606 ComponentEntityType::Component(id) => self.free_variables_component_type_id(*id, set),
2607 ComponentEntityType::Type { created, .. } => {
2608 self.free_variables_any_type_id(*created, set);
2609 }
2610 ComponentEntityType::Value(ty) => self.free_variables_valtype(ty, set),
2611 }
2612 }
2613
2614 fn free_variables_valtype(&self, ty: &ComponentValType, set: &mut IndexSet<ResourceId>) {
2616 match ty {
2617 ComponentValType::Primitive(_) => {}
2618 ComponentValType::Type(id) => self.free_variables_component_defined_type_id(*id, set),
2619 }
2620 }
2621
2622 pub(crate) fn type_named_type_id(
2627 &self,
2628 id: ComponentDefinedTypeId,
2629 set: &Set<ComponentAnyTypeId>,
2630 ) -> bool {
2631 let ty = &self[id];
2632 match ty {
2633 ComponentDefinedType::Primitive(_) => true,
2635
2636 ComponentDefinedType::Flags(_)
2639 | ComponentDefinedType::Enum(_)
2640 | ComponentDefinedType::Record(_)
2641 | ComponentDefinedType::Variant(_) => set.contains(&ComponentAnyTypeId::from(id)),
2642
2643 ComponentDefinedType::Tuple(r) => {
2646 r.types.iter().all(|t| self.type_named_valtype(t, set))
2647 }
2648 ComponentDefinedType::Result { ok, err } => {
2649 ok.as_ref()
2650 .map(|t| self.type_named_valtype(t, set))
2651 .unwrap_or(true)
2652 && err
2653 .as_ref()
2654 .map(|t| self.type_named_valtype(t, set))
2655 .unwrap_or(true)
2656 }
2657 ComponentDefinedType::List(ty)
2658 | ComponentDefinedType::FixedSizeList(ty, _)
2659 | ComponentDefinedType::Option(ty) => self.type_named_valtype(ty, set),
2660
2661 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2664 set.contains(&ComponentAnyTypeId::from(*id))
2665 }
2666
2667 ComponentDefinedType::Future(ty) => ty
2668 .as_ref()
2669 .map(|ty| self.type_named_valtype(ty, set))
2670 .unwrap_or(true),
2671
2672 ComponentDefinedType::Stream(ty) => ty
2673 .as_ref()
2674 .map(|ty| self.type_named_valtype(ty, set))
2675 .unwrap_or(true),
2676 }
2677 }
2678
2679 pub(crate) fn type_named_valtype(
2680 &self,
2681 ty: &ComponentValType,
2682 set: &Set<ComponentAnyTypeId>,
2683 ) -> bool {
2684 match ty {
2685 ComponentValType::Primitive(_) => true,
2686 ComponentValType::Type(id) => self.type_named_type_id(*id, set),
2687 }
2688 }
2689}
2690
2691pub trait Remap
2697where
2698 Self: Index<ComponentTypeId, Output = ComponentType>,
2699 Self: Index<ComponentDefinedTypeId, Output = ComponentDefinedType>,
2700 Self: Index<ComponentInstanceTypeId, Output = ComponentInstanceType>,
2701 Self: Index<ComponentFuncTypeId, Output = ComponentFuncType>,
2702{
2703 #[doc(hidden)]
2708 fn push_ty<T>(&mut self, ty: T) -> T::Id
2709 where
2710 T: TypeData;
2711
2712 fn map_map(
2715 tmp: &mut IndexMap<ResourceId, Vec<usize>>,
2716 any_changed: &mut bool,
2717 map: &Remapping,
2718 ) {
2719 for (id, path) in mem::take(tmp) {
2720 let id = match map.resources.get(&id) {
2721 Some(id) => {
2722 *any_changed = true;
2723 *id
2724 }
2725 None => id,
2726 };
2727 tmp.insert(id, path);
2728 }
2729 }
2730
2731 fn insert_if_any_changed<T>(
2735 &mut self,
2736 map: &mut Remapping,
2737 any_changed: bool,
2738 id: &mut T::Id,
2739 ty: T,
2740 ) -> bool
2741 where
2742 T: TypeData,
2743 T::Id: Into<ComponentAnyTypeId>,
2744 {
2745 let new = if any_changed { self.push_ty(ty) } else { *id };
2746 map.types.insert((*id).into(), new.into());
2747 let changed = *id != new;
2748 *id = new;
2749 changed
2750 }
2751
2752 fn remap_component_any_type_id(
2756 &mut self,
2757 id: &mut ComponentAnyTypeId,
2758 map: &mut Remapping,
2759 ) -> bool {
2760 match id {
2761 ComponentAnyTypeId::Resource(id) => self.remap_resource_id(id, map),
2762 ComponentAnyTypeId::Defined(id) => self.remap_component_defined_type_id(id, map),
2763 ComponentAnyTypeId::Func(id) => self.remap_component_func_type_id(id, map),
2764 ComponentAnyTypeId::Instance(id) => self.remap_component_instance_type_id(id, map),
2765 ComponentAnyTypeId::Component(id) => self.remap_component_type_id(id, map),
2766 }
2767 }
2768
2769 fn remap_resource_id(&mut self, id: &mut AliasableResourceId, map: &Remapping) -> bool {
2772 if let Some(changed) = map.remap_id(id) {
2773 return changed;
2774 }
2775
2776 match map.resources.get(&id.resource()) {
2777 None => false,
2778 Some(new_id) => {
2779 *id.resource_mut() = *new_id;
2780 true
2781 }
2782 }
2783 }
2784
2785 fn remap_component_type_id(&mut self, id: &mut ComponentTypeId, map: &mut Remapping) -> bool {
2789 if let Some(changed) = map.remap_id(id) {
2790 return changed;
2791 }
2792
2793 let mut any_changed = false;
2794 let mut ty = self[*id].clone();
2795 for ty in ty.imports.values_mut().chain(ty.exports.values_mut()) {
2796 any_changed |= self.remap_component_entity(ty, map);
2797 }
2798 for (id, _) in ty
2799 .imported_resources
2800 .iter_mut()
2801 .chain(&mut ty.defined_resources)
2802 {
2803 if let Some(new) = map.resources.get(id) {
2804 *id = *new;
2805 any_changed = true;
2806 }
2807 }
2808 Self::map_map(&mut ty.explicit_resources, &mut any_changed, map);
2809 self.insert_if_any_changed(map, any_changed, id, ty)
2810 }
2811
2812 fn remap_component_defined_type_id(
2816 &mut self,
2817 id: &mut ComponentDefinedTypeId,
2818 map: &mut Remapping,
2819 ) -> bool {
2820 if let Some(changed) = map.remap_id(id) {
2821 return changed;
2822 }
2823
2824 let mut any_changed = false;
2825 let mut tmp = self[*id].clone();
2826 match &mut tmp {
2827 ComponentDefinedType::Primitive(_)
2828 | ComponentDefinedType::Flags(_)
2829 | ComponentDefinedType::Enum(_) => {}
2830 ComponentDefinedType::Record(r) => {
2831 for ty in r.fields.values_mut() {
2832 any_changed |= self.remap_valtype(ty, map);
2833 }
2834 }
2835 ComponentDefinedType::Tuple(r) => {
2836 for ty in r.types.iter_mut() {
2837 any_changed |= self.remap_valtype(ty, map);
2838 }
2839 }
2840 ComponentDefinedType::Variant(r) => {
2841 for ty in r.cases.values_mut() {
2842 if let Some(ty) = &mut ty.ty {
2843 any_changed |= self.remap_valtype(ty, map);
2844 }
2845 }
2846 }
2847 ComponentDefinedType::List(ty)
2848 | ComponentDefinedType::FixedSizeList(ty, _)
2849 | ComponentDefinedType::Option(ty) => {
2850 any_changed |= self.remap_valtype(ty, map);
2851 }
2852 ComponentDefinedType::Result { ok, err } => {
2853 if let Some(ok) = ok {
2854 any_changed |= self.remap_valtype(ok, map);
2855 }
2856 if let Some(err) = err {
2857 any_changed |= self.remap_valtype(err, map);
2858 }
2859 }
2860 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2861 any_changed |= self.remap_resource_id(id, map);
2862 }
2863 ComponentDefinedType::Future(ty) | ComponentDefinedType::Stream(ty) => {
2864 if let Some(ty) = ty {
2865 any_changed |= self.remap_valtype(ty, map);
2866 }
2867 }
2868 }
2869 self.insert_if_any_changed(map, any_changed, id, tmp)
2870 }
2871
2872 fn remap_component_instance_type_id(
2876 &mut self,
2877 id: &mut ComponentInstanceTypeId,
2878 map: &mut Remapping,
2879 ) -> bool {
2880 if let Some(changed) = map.remap_id(id) {
2881 return changed;
2882 }
2883
2884 let mut any_changed = false;
2885 let mut tmp = self[*id].clone();
2886 for ty in tmp.exports.values_mut() {
2887 any_changed |= self.remap_component_entity(ty, map);
2888 }
2889 for id in tmp.defined_resources.iter_mut() {
2890 if let Some(new) = map.resources.get(id) {
2891 *id = *new;
2892 any_changed = true;
2893 }
2894 }
2895 Self::map_map(&mut tmp.explicit_resources, &mut any_changed, map);
2896 self.insert_if_any_changed(map, any_changed, id, tmp)
2897 }
2898
2899 fn remap_component_func_type_id(
2903 &mut self,
2904 id: &mut ComponentFuncTypeId,
2905 map: &mut Remapping,
2906 ) -> bool {
2907 if let Some(changed) = map.remap_id(id) {
2908 return changed;
2909 }
2910
2911 let mut any_changed = false;
2912 let mut tmp = self[*id].clone();
2913 for ty in tmp
2914 .params
2915 .iter_mut()
2916 .map(|(_, ty)| ty)
2917 .chain(&mut tmp.result)
2918 {
2919 any_changed |= self.remap_valtype(ty, map);
2920 }
2921 self.insert_if_any_changed(map, any_changed, id, tmp)
2922 }
2923
2924 fn remap_component_entity(
2926 &mut self,
2927 ty: &mut ComponentEntityType,
2928 map: &mut Remapping,
2929 ) -> bool {
2930 match ty {
2931 ComponentEntityType::Module(_) => {
2932 false
2934 }
2935 ComponentEntityType::Func(id) => self.remap_component_func_type_id(id, map),
2936 ComponentEntityType::Instance(id) => self.remap_component_instance_type_id(id, map),
2937 ComponentEntityType::Component(id) => self.remap_component_type_id(id, map),
2938 ComponentEntityType::Type {
2939 referenced,
2940 created,
2941 } => {
2942 let mut changed = self.remap_component_any_type_id(referenced, map);
2943 if *referenced == *created {
2944 *created = *referenced;
2945 } else {
2946 changed |= self.remap_component_any_type_id(created, map);
2947 }
2948 changed
2949 }
2950 ComponentEntityType::Value(ty) => self.remap_valtype(ty, map),
2951 }
2952 }
2953
2954 fn remap_valtype(&mut self, ty: &mut ComponentValType, map: &mut Remapping) -> bool {
2956 match ty {
2957 ComponentValType::Primitive(_) => false,
2958 ComponentValType::Type(id) => self.remap_component_defined_type_id(id, map),
2959 }
2960 }
2961}
2962
2963#[derive(Debug, Default)]
2966pub struct Remapping {
2967 pub(crate) resources: Map<ResourceId, ResourceId>,
2969
2970 types: Map<ComponentAnyTypeId, ComponentAnyTypeId>,
2974}
2975
2976impl Remap for TypeAlloc {
2977 fn push_ty<T>(&mut self, ty: T) -> T::Id
2978 where
2979 T: TypeData,
2980 {
2981 <TypeList>::push(self, ty)
2982 }
2983}
2984
2985impl Remapping {
2986 pub fn add(&mut self, old: ResourceId, new: ResourceId) {
2988 self.resources.insert(old, new);
2989 }
2990
2991 pub fn reset_type_cache(&mut self) {
2993 self.types.clear()
2994 }
2995
2996 fn remap_id<T>(&self, id: &mut T) -> Option<bool>
2997 where
2998 T: Copy + Into<ComponentAnyTypeId> + TryFrom<ComponentAnyTypeId>,
2999 T::Error: core::fmt::Debug,
3000 {
3001 let old: ComponentAnyTypeId = (*id).into();
3002 let new = self.types.get(&old)?;
3003 if *new == old {
3004 Some(false)
3005 } else {
3006 *id = T::try_from(*new).expect("should never remap across different kinds");
3007 Some(true)
3008 }
3009 }
3010}
3011
3012pub struct SubtypeCx<'a> {
3031 pub a: SubtypeArena<'a>,
3033 pub b: SubtypeArena<'a>,
3035}
3036
3037macro_rules! limits_match {
3038 ($a:expr, $b:expr) => {{
3039 let a = $a;
3040 let b = $b;
3041 a.initial >= b.initial
3042 && match b.maximum {
3043 Some(b_max) => match a.maximum {
3044 Some(a_max) => a_max <= b_max,
3045 None => false,
3046 },
3047 None => true,
3048 }
3049 }};
3050}
3051
3052impl<'a> SubtypeCx<'a> {
3053 pub fn new_with_refs(a: TypesRef<'a>, b: TypesRef<'a>) -> SubtypeCx<'a> {
3060 assert_eq!(a.id(), b.id());
3061 Self::new(a.list, b.list)
3062 }
3063
3064 pub(crate) fn new(a: &'a TypeList, b: &'a TypeList) -> SubtypeCx<'a> {
3065 SubtypeCx {
3066 a: SubtypeArena::new(a),
3067 b: SubtypeArena::new(b),
3068 }
3069 }
3070
3071 pub fn swap(&mut self) {
3073 mem::swap(&mut self.a, &mut self.b);
3074 }
3075
3076 fn with_checkpoint<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
3082 let a = self.a.list.checkpoint();
3083 let b = self.b.list.checkpoint();
3084 let result = f(self);
3085 self.a.list.reset_to_checkpoint(a);
3086 self.b.list.reset_to_checkpoint(b);
3087 result
3088 }
3089
3090 pub fn component_entity_type(
3094 &mut self,
3095 a: &ComponentEntityType,
3096 b: &ComponentEntityType,
3097 offset: usize,
3098 ) -> Result<()> {
3099 use ComponentEntityType::*;
3100
3101 match (a, b) {
3102 (Module(a), Module(b)) => self.module_type(*a, *b, offset),
3103 (Module(_), b) => bail!(offset, "expected {}, found module", b.desc()),
3104
3105 (Func(a), Func(b)) => self.component_func_type(*a, *b, offset),
3106 (Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3107
3108 (Value(a), Value(b)) => self.component_val_type(a, b, offset),
3109 (Value(_), b) => bail!(offset, "expected {}, found value", b.desc()),
3110
3111 (Type { referenced: a, .. }, Type { referenced: b, .. }) => {
3112 self.component_any_type_id(*a, *b, offset)
3113 }
3114 (Type { .. }, b) => bail!(offset, "expected {}, found type", b.desc()),
3115
3116 (Instance(a), Instance(b)) => self.component_instance_type(*a, *b, offset),
3117 (Instance(_), b) => bail!(offset, "expected {}, found instance", b.desc()),
3118
3119 (Component(a), Component(b)) => self.component_type(*a, *b, offset),
3120 (Component(_), b) => bail!(offset, "expected {}, found component", b.desc()),
3121 }
3122 }
3123
3124 pub fn component_type(
3128 &mut self,
3129 a: ComponentTypeId,
3130 b: ComponentTypeId,
3131 offset: usize,
3132 ) -> Result<()> {
3133 let b_imports = self.b[b]
3187 .imports
3188 .iter()
3189 .map(|(name, ty)| (name.clone(), *ty))
3190 .collect();
3191 self.swap();
3192 let mut import_mapping =
3193 self.open_instance_type(&b_imports, a, ExternKind::Import, offset)?;
3194 self.swap();
3195 self.with_checkpoint(|this| {
3196 let mut a_exports = this.a[a]
3197 .exports
3198 .iter()
3199 .map(|(name, ty)| (name.clone(), *ty))
3200 .collect::<IndexMap<_, _>>();
3201 for ty in a_exports.values_mut() {
3202 this.a.remap_component_entity(ty, &mut import_mapping);
3203 }
3204 this.open_instance_type(&a_exports, b, ExternKind::Export, offset)?;
3205 Ok(())
3206 })
3207 }
3208
3209 pub fn component_instance_type(
3213 &mut self,
3214 a_id: ComponentInstanceTypeId,
3215 b_id: ComponentInstanceTypeId,
3216 offset: usize,
3217 ) -> Result<()> {
3218 let a = &self.a[a_id];
3223 let b = &self.b[b_id];
3224
3225 let mut exports = Vec::with_capacity(b.exports.len());
3226 for (k, b) in b.exports.iter() {
3227 match a.exports.get(k) {
3228 Some(a) => exports.push((*a, *b)),
3229 None => bail!(offset, "missing expected export `{k}`"),
3230 }
3231 }
3232 for (i, (a, b)) in exports.iter().enumerate() {
3233 let err = match self.component_entity_type(a, b, offset) {
3234 Ok(()) => continue,
3235 Err(e) => e,
3236 };
3237 let (name, _) = self.b[b_id].exports.get_index(i).unwrap();
3240 return Err(err.with_context(|| format!("type mismatch in instance export `{name}`")));
3241 }
3242 Ok(())
3243 }
3244
3245 pub fn component_func_type(
3249 &mut self,
3250 a: ComponentFuncTypeId,
3251 b: ComponentFuncTypeId,
3252 offset: usize,
3253 ) -> Result<()> {
3254 let a = &self.a[a];
3255 let b = &self.b[b];
3256
3257 if a.async_ != b.async_ {
3258 let a_desc = if a.async_ { "async" } else { "sync" };
3259 let b_desc = if b.async_ { "async" } else { "sync" };
3260 bail!(
3261 offset,
3262 "expected {a_desc} function, found {b_desc} function",
3263 );
3264 }
3265
3266 if a.params.len() != b.params.len() {
3297 bail!(
3298 offset,
3299 "expected {} parameters, found {}",
3300 b.params.len(),
3301 a.params.len(),
3302 );
3303 }
3304 for ((an, a), (bn, b)) in a.params.iter().zip(b.params.iter()) {
3305 if an != bn {
3306 bail!(offset, "expected parameter named `{bn}`, found `{an}`");
3307 }
3308 self.component_val_type(a, b, offset)
3309 .with_context(|| format!("type mismatch in function parameter `{an}`"))?;
3310 }
3311
3312 match (&a.result, &b.result) {
3313 (Some(a), Some(b)) => self
3314 .component_val_type(a, b, offset)
3315 .with_context(|| "type mismatch with result type")?,
3316 (None, None) => {}
3317
3318 (Some(_), None) => bail!(offset, "expected a result, found none"),
3319 (None, Some(_)) => bail!(offset, "expected no result, found one"),
3320 }
3321 Ok(())
3322 }
3323
3324 pub fn module_type(
3328 &mut self,
3329 a: ComponentCoreModuleTypeId,
3330 b: ComponentCoreModuleTypeId,
3331 offset: usize,
3332 ) -> Result<()> {
3333 self.swap();
3339 let a_imports = &self.b[a].imports;
3340 let b_imports = &self.a[b].imports;
3341 for (k, a) in a_imports {
3342 match b_imports.get(k) {
3343 Some(b) => self
3344 .entity_type(b, a, offset)
3345 .with_context(|| format!("type mismatch in import `{}::{}`", k.0, k.1))?,
3346 None => bail!(offset, "missing expected import `{}::{}`", k.0, k.1),
3347 }
3348 }
3349 self.swap();
3350 let a = &self.a[a];
3351 let b = &self.b[b];
3352 for (k, b) in b.exports.iter() {
3353 match a.exports.get(k) {
3354 Some(a) => self
3355 .entity_type(a, b, offset)
3356 .with_context(|| format!("type mismatch in export `{k}`"))?,
3357 None => bail!(offset, "missing expected export `{k}`"),
3358 }
3359 }
3360 Ok(())
3361 }
3362
3363 pub fn component_any_type_id(
3367 &mut self,
3368 a: ComponentAnyTypeId,
3369 b: ComponentAnyTypeId,
3370 offset: usize,
3371 ) -> Result<()> {
3372 match (a, b) {
3373 (ComponentAnyTypeId::Resource(a), ComponentAnyTypeId::Resource(b)) => {
3374 if a.resource() == b.resource() {
3375 Ok(())
3376 } else {
3377 bail!(
3378 offset,
3379 "resource types are not the same ({:?} vs. {:?})",
3380 a.resource(),
3381 b.resource()
3382 )
3383 }
3384 }
3385 (ComponentAnyTypeId::Resource(_), b) => {
3386 bail!(offset, "expected {}, found resource", b.desc())
3387 }
3388 (ComponentAnyTypeId::Defined(a), ComponentAnyTypeId::Defined(b)) => {
3389 self.component_defined_type(a, b, offset)
3390 }
3391 (ComponentAnyTypeId::Defined(_), b) => {
3392 bail!(offset, "expected {}, found defined type", b.desc())
3393 }
3394
3395 (ComponentAnyTypeId::Func(a), ComponentAnyTypeId::Func(b)) => {
3396 self.component_func_type(a, b, offset)
3397 }
3398 (ComponentAnyTypeId::Func(_), b) => {
3399 bail!(offset, "expected {}, found func type", b.desc())
3400 }
3401
3402 (ComponentAnyTypeId::Instance(a), ComponentAnyTypeId::Instance(b)) => {
3403 self.component_instance_type(a, b, offset)
3404 }
3405 (ComponentAnyTypeId::Instance(_), b) => {
3406 bail!(offset, "expected {}, found instance type", b.desc())
3407 }
3408
3409 (ComponentAnyTypeId::Component(a), ComponentAnyTypeId::Component(b)) => {
3410 self.component_type(a, b, offset)
3411 }
3412 (ComponentAnyTypeId::Component(_), b) => {
3413 bail!(offset, "expected {}, found component type", b.desc())
3414 }
3415 }
3416 }
3417
3418 pub fn open_instance_type(
3442 &mut self,
3443 a: &IndexMap<String, ComponentEntityType>,
3444 b: ComponentTypeId,
3445 kind: ExternKind,
3446 offset: usize,
3447 ) -> Result<Remapping> {
3448 let component_type = &self.b[b];
3478 let entities = match kind {
3479 ExternKind::Import => &component_type.imports,
3480 ExternKind::Export => &component_type.exports,
3481 };
3482 let resources = match kind {
3483 ExternKind::Import => &component_type.imported_resources,
3484 ExternKind::Export => &component_type.defined_resources,
3485 };
3486 let mut mapping = Remapping::default();
3487 'outer: for (resource, path) in resources.iter() {
3488 let (name, ty) = entities.get_index(path[0]).unwrap();
3491 let mut ty = *ty;
3492 let mut arg = a.get(name);
3493
3494 for i in path.iter().skip(1).copied() {
3498 let id = match ty {
3499 ComponentEntityType::Instance(id) => id,
3500 _ => unreachable!(),
3501 };
3502 let (name, next_ty) = self.b[id].exports.get_index(i).unwrap();
3503 ty = *next_ty;
3504 arg = match arg {
3505 Some(ComponentEntityType::Instance(id)) => self.a[*id].exports.get(name),
3506 _ => continue 'outer,
3507 };
3508 }
3509
3510 if cfg!(debug_assertions) {
3513 let id = match ty {
3514 ComponentEntityType::Type { created, .. } => match created {
3515 ComponentAnyTypeId::Resource(id) => id.resource(),
3516 _ => unreachable!(),
3517 },
3518 _ => unreachable!(),
3519 };
3520 assert_eq!(id, *resource);
3521 }
3522
3523 if let Some(ComponentEntityType::Type { created, .. }) = arg {
3527 if let ComponentAnyTypeId::Resource(r) = created {
3528 mapping.resources.insert(*resource, r.resource());
3529 }
3530 }
3531 }
3532
3533 let mut to_typecheck = Vec::new();
3545 for (name, expected) in entities.iter() {
3546 match a.get(name) {
3547 Some(arg) => to_typecheck.push((*arg, *expected)),
3548 None => bail!(offset, "missing {} named `{name}`", kind.desc()),
3549 }
3550 }
3551 let mut type_map = Map::default();
3552 for (i, (actual, expected)) in to_typecheck.into_iter().enumerate() {
3553 let result = self.with_checkpoint(|this| {
3554 let mut expected = expected;
3555 this.b.remap_component_entity(&mut expected, &mut mapping);
3556 mapping.types.clear();
3557 this.component_entity_type(&actual, &expected, offset)
3558 });
3559 let err = match result {
3560 Ok(()) => {
3561 self.register_type_renamings(actual, expected, &mut type_map);
3567 continue;
3568 }
3569 Err(e) => e,
3570 };
3571
3572 let component_type = &self.b[b];
3575 let entities = match kind {
3576 ExternKind::Import => &component_type.imports,
3577 ExternKind::Export => &component_type.exports,
3578 };
3579 let (name, _) = entities.get_index(i).unwrap();
3580 return Err(err.with_context(|| format!("type mismatch for {} `{name}`", kind.desc())));
3581 }
3582 mapping.types = type_map;
3583 Ok(mapping)
3584 }
3585
3586 pub(crate) fn entity_type(&self, a: &EntityType, b: &EntityType, offset: usize) -> Result<()> {
3587 match (a, b) {
3588 (EntityType::Func(a), EntityType::Func(b))
3589 | (EntityType::FuncExact(a), EntityType::Func(b)) => {
3590 self.core_func_type(*a, *b, offset)
3591 }
3592 (EntityType::Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3593 (EntityType::FuncExact(a), EntityType::FuncExact(b)) => {
3594 self.core_func_type(*b, *a, offset)?;
3595 self.core_func_type(*a, *b, offset)
3596 }
3597 (EntityType::FuncExact(_), b) => {
3598 bail!(offset, "expected {}, found func_exact", b.desc())
3599 }
3600 (EntityType::Table(a), EntityType::Table(b)) => Self::table_type(a, b, offset),
3601 (EntityType::Table(_), b) => bail!(offset, "expected {}, found table", b.desc()),
3602 (EntityType::Memory(a), EntityType::Memory(b)) => Self::memory_type(a, b, offset),
3603 (EntityType::Memory(_), b) => bail!(offset, "expected {}, found memory", b.desc()),
3604 (EntityType::Global(a), EntityType::Global(b)) => {
3605 if a.mutable != b.mutable {
3606 bail!(offset, "global types differ in mutability")
3607 }
3608 if a.content_type == b.content_type {
3609 Ok(())
3610 } else {
3611 bail!(
3612 offset,
3613 "expected global type {}, found {}",
3614 b.content_type,
3615 a.content_type,
3616 )
3617 }
3618 }
3619 (EntityType::Global(_), b) => bail!(offset, "expected {}, found global", b.desc()),
3620 (EntityType::Tag(a), EntityType::Tag(b)) => self.core_func_type(*a, *b, offset),
3621 (EntityType::Tag(_), b) => bail!(offset, "expected {}, found tag", b.desc()),
3622 }
3623 }
3624
3625 pub(crate) fn table_type(a: &TableType, b: &TableType, offset: usize) -> Result<()> {
3626 if a.element_type != b.element_type {
3627 bail!(
3628 offset,
3629 "expected table element type {}, found {}",
3630 b.element_type,
3631 a.element_type,
3632 )
3633 }
3634 if a.shared != b.shared {
3635 bail!(offset, "mismatch in the shared flag for tables")
3636 }
3637 if limits_match!(a, b) {
3638 Ok(())
3639 } else {
3640 bail!(offset, "mismatch in table limits")
3641 }
3642 }
3643
3644 pub(crate) fn memory_type(a: &MemoryType, b: &MemoryType, offset: usize) -> Result<()> {
3645 if a.shared != b.shared {
3646 bail!(offset, "mismatch in the shared flag for memories")
3647 }
3648 if a.memory64 != b.memory64 {
3649 bail!(offset, "mismatch in index type used for memories")
3650 }
3651 if limits_match!(a, b) {
3652 Ok(())
3653 } else {
3654 bail!(offset, "mismatch in memory limits")
3655 }
3656 }
3657
3658 fn core_func_type(&self, a: CoreTypeId, b: CoreTypeId, offset: usize) -> Result<()> {
3659 debug_assert!(self.a.get(a).is_some());
3660 debug_assert!(self.b.get(b).is_some());
3661 if self.a.id_is_subtype(a, b) {
3662 debug_assert!(self.a.get(b).is_some());
3663 debug_assert!(self.b.get(a).is_some());
3664 Ok(())
3665 } else {
3666 bail!(
3667 offset,
3668 "expected: {}\n\
3669 found: {}",
3670 self.b[b],
3671 self.a[a],
3672 )
3673 }
3674 }
3675
3676 pub(crate) fn component_val_type(
3677 &self,
3678 a: &ComponentValType,
3679 b: &ComponentValType,
3680 offset: usize,
3681 ) -> Result<()> {
3682 match (a, b) {
3683 (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
3684 self.primitive_val_type(*a, *b, offset)
3685 }
3686 (ComponentValType::Type(a), ComponentValType::Type(b)) => {
3687 self.component_defined_type(*a, *b, offset)
3688 }
3689 (ComponentValType::Primitive(a), ComponentValType::Type(b)) => match &self.b[*b] {
3690 ComponentDefinedType::Primitive(b) => self.primitive_val_type(*a, *b, offset),
3691 b => bail!(offset, "expected {}, found {a}", b.desc()),
3692 },
3693 (ComponentValType::Type(a), ComponentValType::Primitive(b)) => match &self.a[*a] {
3694 ComponentDefinedType::Primitive(a) => self.primitive_val_type(*a, *b, offset),
3695 a => bail!(offset, "expected {b}, found {}", a.desc()),
3696 },
3697 }
3698 }
3699
3700 fn component_defined_type(
3701 &self,
3702 a: ComponentDefinedTypeId,
3703 b: ComponentDefinedTypeId,
3704 offset: usize,
3705 ) -> Result<()> {
3706 use ComponentDefinedType::*;
3707
3708 match (&self.a[a], &self.b[b]) {
3712 (Primitive(a), Primitive(b)) => self.primitive_val_type(*a, *b, offset),
3713 (Primitive(a), b) => bail!(offset, "expected {}, found {a}", b.desc()),
3714 (Record(a), Record(b)) => {
3715 if a.fields.len() != b.fields.len() {
3716 bail!(
3717 offset,
3718 "expected {} fields, found {}",
3719 b.fields.len(),
3720 a.fields.len(),
3721 );
3722 }
3723
3724 for ((aname, a), (bname, b)) in a.fields.iter().zip(b.fields.iter()) {
3725 if aname != bname {
3726 bail!(offset, "expected field name `{bname}`, found `{aname}`");
3727 }
3728 self.component_val_type(a, b, offset)
3729 .with_context(|| format!("type mismatch in record field `{aname}`"))?;
3730 }
3731 Ok(())
3732 }
3733 (Record(_), b) => bail!(offset, "expected {}, found record", b.desc()),
3734 (Variant(a), Variant(b)) => {
3735 if a.cases.len() != b.cases.len() {
3736 bail!(
3737 offset,
3738 "expected {} cases, found {}",
3739 b.cases.len(),
3740 a.cases.len(),
3741 );
3742 }
3743 for ((aname, a), (bname, b)) in a.cases.iter().zip(b.cases.iter()) {
3744 if aname != bname {
3745 bail!(offset, "expected case named `{bname}`, found `{aname}`");
3746 }
3747 match (&a.ty, &b.ty) {
3748 (Some(a), Some(b)) => self
3749 .component_val_type(a, b, offset)
3750 .with_context(|| format!("type mismatch in variant case `{aname}`"))?,
3751 (None, None) => {}
3752 (None, Some(_)) => {
3753 bail!(offset, "expected case `{aname}` to have a type, found none")
3754 }
3755 (Some(_), None) => bail!(offset, "expected case `{aname}` to have no type"),
3756 }
3757 }
3758 Ok(())
3759 }
3760 (Variant(_), b) => bail!(offset, "expected {}, found variant", b.desc()),
3761 (List(a), List(b)) | (Option(a), Option(b)) => self.component_val_type(a, b, offset),
3762 (List(_), b) => bail!(offset, "expected {}, found list", b.desc()),
3763 (FixedSizeList(a, asize), FixedSizeList(b, bsize)) => {
3764 if asize != bsize {
3765 bail!(offset, "expected fixed size {bsize}, found size {asize}")
3766 } else {
3767 self.component_val_type(a, b, offset)
3768 }
3769 }
3770 (FixedSizeList(_, _), b) => bail!(offset, "expected {}, found list", b.desc()),
3771 (Option(_), b) => bail!(offset, "expected {}, found option", b.desc()),
3772 (Tuple(a), Tuple(b)) => {
3773 if a.types.len() != b.types.len() {
3774 bail!(
3775 offset,
3776 "expected {} types, found {}",
3777 b.types.len(),
3778 a.types.len(),
3779 );
3780 }
3781 for (i, (a, b)) in a.types.iter().zip(b.types.iter()).enumerate() {
3782 self.component_val_type(a, b, offset)
3783 .with_context(|| format!("type mismatch in tuple field {i}"))?;
3784 }
3785 Ok(())
3786 }
3787 (Tuple(_), b) => bail!(offset, "expected {}, found tuple", b.desc()),
3788 (at @ Flags(a), Flags(b)) | (at @ Enum(a), Enum(b)) => {
3789 let desc = match at {
3790 Flags(_) => "flags",
3791 _ => "enum",
3792 };
3793 if a.len() == b.len() && a.iter().eq(b.iter()) {
3794 Ok(())
3795 } else {
3796 bail!(offset, "mismatch in {desc} elements")
3797 }
3798 }
3799 (Flags(_), b) => bail!(offset, "expected {}, found flags", b.desc()),
3800 (Enum(_), b) => bail!(offset, "expected {}, found enum", b.desc()),
3801 (Result { ok: ao, err: ae }, Result { ok: bo, err: be }) => {
3802 match (ao, bo) {
3803 (None, None) => {}
3804 (Some(a), Some(b)) => self
3805 .component_val_type(a, b, offset)
3806 .with_context(|| "type mismatch in ok variant")?,
3807 (None, Some(_)) => bail!(offset, "expected ok type, but found none"),
3808 (Some(_), None) => bail!(offset, "expected ok type to not be present"),
3809 }
3810 match (ae, be) {
3811 (None, None) => {}
3812 (Some(a), Some(b)) => self
3813 .component_val_type(a, b, offset)
3814 .with_context(|| "type mismatch in err variant")?,
3815 (None, Some(_)) => bail!(offset, "expected err type, but found none"),
3816 (Some(_), None) => bail!(offset, "expected err type to not be present"),
3817 }
3818 Ok(())
3819 }
3820 (Result { .. }, b) => bail!(offset, "expected {}, found result", b.desc()),
3821 (Own(a), Own(b)) | (Borrow(a), Borrow(b)) => {
3822 if a.resource() == b.resource() {
3823 Ok(())
3824 } else {
3825 bail!(offset, "resource types are not the same")
3826 }
3827 }
3828 (Own(_), b) => bail!(offset, "expected {}, found own", b.desc()),
3829 (Borrow(_), b) => bail!(offset, "expected {}, found borrow", b.desc()),
3830 (Future(a), Future(b)) => match (a, b) {
3831 (None, None) => Ok(()),
3832 (Some(a), Some(b)) => self
3833 .component_val_type(a, b, offset)
3834 .with_context(|| "type mismatch in future"),
3835 (None, Some(_)) => bail!(offset, "expected future type, but found none"),
3836 (Some(_), None) => bail!(offset, "expected future type to not be present"),
3837 },
3838 (Future(_), b) => bail!(offset, "expected {}, found future", b.desc()),
3839 (Stream(a), Stream(b)) => match (a, b) {
3840 (None, None) => Ok(()),
3841 (Some(a), Some(b)) => self
3842 .component_val_type(a, b, offset)
3843 .with_context(|| "type mismatch in stream"),
3844 (None, Some(_)) => bail!(offset, "expected stream type, but found none"),
3845 (Some(_), None) => bail!(offset, "expected stream type to not be present"),
3846 },
3847 (Stream(_), b) => bail!(offset, "expected {}, found stream", b.desc()),
3848 }
3849 }
3850
3851 fn primitive_val_type(
3852 &self,
3853 a: PrimitiveValType,
3854 b: PrimitiveValType,
3855 offset: usize,
3856 ) -> Result<()> {
3857 if a == b {
3864 Ok(())
3865 } else {
3866 bail!(offset, "expected primitive `{b}` found primitive `{a}`")
3867 }
3868 }
3869
3870 fn register_type_renamings(
3871 &self,
3872 actual: ComponentEntityType,
3873 expected: ComponentEntityType,
3874 type_map: &mut Map<ComponentAnyTypeId, ComponentAnyTypeId>,
3875 ) {
3876 match (expected, actual) {
3877 (
3878 ComponentEntityType::Type {
3879 created: expected, ..
3880 },
3881 ComponentEntityType::Type {
3882 created: actual, ..
3883 },
3884 ) => {
3885 let prev = type_map.insert(expected, actual);
3886 assert!(prev.is_none());
3887 }
3888 (ComponentEntityType::Instance(expected), ComponentEntityType::Instance(actual)) => {
3889 let actual = &self.a[actual];
3890 for (name, expected) in self.b[expected].exports.iter() {
3891 let actual = actual.exports[name];
3892 self.register_type_renamings(actual, *expected, type_map);
3893 }
3894 }
3895 _ => {}
3896 }
3897 }
3898}
3899
3900pub struct SubtypeArena<'a> {
3910 types: &'a TypeList,
3911 list: TypeList,
3912}
3913
3914impl<'a> SubtypeArena<'a> {
3915 fn new(types: &'a TypeList) -> SubtypeArena<'a> {
3916 SubtypeArena {
3917 types,
3918 list: TypeList::default(),
3919 }
3920 }
3921
3922 fn get<T>(&self, id: T) -> Option<&T::Data>
3923 where
3924 T: TypeIdentifier,
3925 {
3926 let index = id.index();
3927 if index < T::list(self.types).len() {
3928 self.types.get(id)
3929 } else {
3930 let temp_index = index - T::list(self.types).len();
3931 let temp_index = u32::try_from(temp_index).unwrap();
3932 let temp_id = T::from_index(temp_index);
3933 self.list.get(temp_id)
3934 }
3935 }
3936
3937 fn id_is_subtype(&self, a: CoreTypeId, b: CoreTypeId) -> bool {
3940 self.get(a).is_some() && self.get(b).is_some() && {
3941 debug_assert!(a.index() < CoreTypeId::list(self.types).len());
3944 debug_assert!(b.index() < CoreTypeId::list(self.types).len());
3945 self.types.id_is_subtype(a, b)
3946 }
3947 }
3948}
3949
3950impl<T> Index<T> for SubtypeArena<'_>
3951where
3952 T: TypeIdentifier,
3953{
3954 type Output = T::Data;
3955
3956 fn index(&self, id: T) -> &T::Data {
3957 self.get(id).unwrap()
3958 }
3959}
3960
3961impl Remap for SubtypeArena<'_> {
3962 fn push_ty<T>(&mut self, ty: T) -> T::Id
3963 where
3964 T: TypeData,
3965 {
3966 assert!(
3967 !T::IS_CORE_SUB_TYPE,
3968 "cannot push core sub types into `SubtypeArena`s, that would break type canonicalization"
3969 );
3970 let index = T::Id::list(&self.list).len() + T::Id::list(self.types).len();
3971 let index = u32::try_from(index).unwrap();
3972 self.list.push(ty);
3973 T::Id::from_index(index)
3974 }
3975}
3976
3977pub(crate) trait Context {
3980 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
3981 where
3982 S: Into<String>;
3983}
3984
3985impl<T> Context for Result<T> {
3986 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
3987 where
3988 S: Into<String>,
3989 {
3990 match self {
3991 Ok(val) => Ok(val),
3992 Err(e) => Err(e.with_context(context)),
3993 }
3994 }
3995}
3996
3997impl Context for BinaryReaderError {
3998 fn with_context<S>(mut self, context: impl FnOnce() -> S) -> Self
3999 where
4000 S: Into<String>,
4001 {
4002 self.add_context(context().into());
4003 self
4004 }
4005}