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, ComponentItem>,
973
974 pub exports: IndexMap<String, ComponentItem>,
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
1018#[derive(Debug, Clone)]
1021pub struct ComponentItem {
1022 pub ty: ComponentEntityType,
1024 pub implements: Option<String>,
1026}
1027
1028impl TypeData for ComponentType {
1029 type Id = ComponentTypeId;
1030 const IS_CORE_SUB_TYPE: bool = false;
1031 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1032 self.info
1033 }
1034}
1035
1036#[derive(Debug, Clone)]
1038pub struct ComponentInstanceType {
1039 pub(crate) info: TypeInfo,
1041
1042 pub exports: IndexMap<String, ComponentItem>,
1046
1047 pub defined_resources: Vec<ResourceId>,
1080
1081 pub explicit_resources: IndexMap<ResourceId, Vec<usize>>,
1084}
1085
1086impl TypeData for ComponentInstanceType {
1087 type Id = ComponentInstanceTypeId;
1088 const IS_CORE_SUB_TYPE: bool = false;
1089 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1090 self.info
1091 }
1092}
1093
1094#[derive(Debug, Clone)]
1096pub struct ComponentFuncType {
1097 pub(crate) info: TypeInfo,
1099 pub async_: bool,
1101 pub params: Box<[(KebabString, ComponentValType)]>,
1103 pub result: Option<ComponentValType>,
1105}
1106
1107impl TypeData for ComponentFuncType {
1108 type Id = ComponentFuncTypeId;
1109 const IS_CORE_SUB_TYPE: bool = false;
1110 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1111 self.info
1112 }
1113}
1114
1115#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1116pub(crate) enum Abi {
1117 Lift,
1118 Lower,
1119}
1120
1121impl Abi {
1122 fn invert(&self) -> Self {
1123 match self {
1124 Abi::Lift => Abi::Lower,
1125 Abi::Lower => Abi::Lift,
1126 }
1127 }
1128}
1129
1130#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1131pub(crate) enum ArgOrField {
1132 Arg(ValType),
1134 Field(StorageType),
1136}
1137
1138impl From<ValType> for ArgOrField {
1139 fn from(v: ValType) -> Self {
1140 Self::Arg(v)
1141 }
1142}
1143
1144impl From<StorageType> for ArgOrField {
1145 fn from(v: StorageType) -> Self {
1146 Self::Field(v)
1147 }
1148}
1149
1150impl core::fmt::Display for ArgOrField {
1151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1152 match self {
1153 ArgOrField::Arg(ty) => core::fmt::Display::fmt(ty, f),
1154 ArgOrField::Field(ty) => core::fmt::Display::fmt(ty, f),
1155 }
1156 }
1157}
1158
1159impl ArgOrField {
1160 pub(crate) fn as_val_type(self) -> Option<ValType> {
1161 match self {
1162 ArgOrField::Arg(ty) | ArgOrField::Field(StorageType::Val(ty)) => Some(ty),
1163 _ => None,
1164 }
1165 }
1166
1167 pub(crate) fn as_ref_type(self) -> Option<RefType> {
1168 self.as_val_type()?.as_reference_type()
1169 }
1170
1171 pub(crate) fn as_concrete_ref(self) -> Option<CoreTypeId> {
1172 match self.as_ref_type()?.heap_type() {
1173 HeapType::Abstract { .. } => None,
1174 HeapType::Concrete(idx) | HeapType::Exact(idx) => {
1175 let id = idx
1176 .as_core_type_id()
1177 .expect("validation only sees core type ids");
1178 Some(id)
1179 }
1180 }
1181 }
1182}
1183
1184pub(crate) enum LoweredFuncType {
1185 New(FuncType),
1186 Existing(CoreTypeId),
1187}
1188
1189impl LoweredFuncType {
1190 pub(crate) fn intern(self, types: &mut TypeAlloc, offset: usize) -> CoreTypeId {
1191 match self {
1192 LoweredFuncType::New(ty) => types.intern_func_type(ty, offset),
1193 LoweredFuncType::Existing(id) => id,
1194 }
1195 }
1196}
1197
1198impl ComponentFuncType {
1199 pub(crate) fn lower(
1202 &self,
1203 types: &TypeList,
1204 options: &CanonicalOptions,
1205 abi: Abi,
1206 offset: usize,
1207 ) -> Result<LoweredFuncType> {
1208 let mut sig = LoweredSignature::default();
1209
1210 if options.gc {
1211 return self.lower_gc(types, abi, options, offset);
1212 }
1213
1214 if abi == Abi::Lower && options.concurrency.is_async() {
1215 sig.params.max = MAX_FLAT_ASYNC_PARAMS;
1216 }
1217
1218 for (_, ty) in self.params.iter() {
1219 match abi {
1226 Abi::Lower => {
1227 options.require_memory_if(offset, || ty.contains_ptr(types))?;
1228 }
1229 Abi::Lift => {
1230 options.require_realloc_if(offset, || ty.contains_ptr(types))?;
1231 }
1232 }
1233
1234 if !ty.push_wasm_types(types, &mut sig.params) {
1235 sig.params.clear();
1239 assert!(sig.params.try_push(ValType::I32));
1240 options.require_memory(offset)?;
1241
1242 if let Abi::Lift = abi {
1244 options.require_realloc(offset)?;
1245 }
1246 break;
1247 }
1248 }
1249
1250 match (abi, options.concurrency) {
1251 (Abi::Lower | Abi::Lift, Concurrency::Sync) => {
1252 if let Some(ty) = &self.result {
1253 options.require_realloc_if(offset, || {
1258 abi == Abi::Lower && ty.contains_ptr(types)
1259 })?;
1260
1261 if !ty.push_wasm_types(types, &mut sig.results) {
1262 sig.results.clear();
1266 options.require_memory(offset)?;
1267 match abi {
1268 Abi::Lower => {
1269 sig.params.max = MAX_LOWERED_TYPES;
1270 assert!(sig.params.try_push(ValType::I32));
1271 }
1272 Abi::Lift => {
1273 assert!(sig.results.try_push(ValType::I32));
1274 }
1275 }
1276 }
1277 }
1278 }
1279 (Abi::Lower, Concurrency::Async { callback: _ }) => {
1280 if self.result.is_some() {
1281 sig.params.max = MAX_LOWERED_TYPES;
1282 sig.params.assert_push(ValType::I32);
1283 options.require_memory(offset)?;
1284 }
1285 sig.results.assert_push(ValType::I32);
1286 }
1287 (Abi::Lift, Concurrency::Async { callback }) => {
1288 if let Some(ty) = &self.result {
1289 let overflow =
1299 !ty.push_wasm_types(types, &mut LoweredTypes::new(MAX_FLAT_FUNC_PARAMS));
1300
1301 options.require_memory_if(offset, || overflow || ty.contains_ptr(types))?;
1302 }
1303 if callback.is_some() {
1304 sig.results.assert_push(ValType::I32);
1305 }
1306 }
1307 }
1308
1309 Ok(LoweredFuncType::New(sig.into_func_type()))
1310 }
1311
1312 fn lower_gc(
1313 &self,
1314 types: &TypeList,
1315 abi: Abi,
1316 options: &CanonicalOptions,
1317 offset: usize,
1318 ) -> Result<LoweredFuncType> {
1319 let core_type_id = options.core_type.unwrap();
1320 let core_func_ty = types[core_type_id].unwrap_func();
1321
1322 ensure!(
1323 core_func_ty.params().len() == self.params.len(),
1324 offset,
1325 "declared `core-type` has {} parameters, but component function has {} parameters",
1326 core_func_ty.params().len(),
1327 self.params.len(),
1328 );
1329 for (core, (_name, comp)) in core_func_ty.params().iter().zip(self.params.iter()) {
1330 comp.lower_gc(types, abi.invert(), options, offset, (*core).into())?;
1331 }
1332
1333 ensure!(
1334 core_func_ty.results().len() == usize::from(self.result.is_some()),
1335 offset,
1336 "declared `core-type` has {} results, but component function has {} results",
1337 core_func_ty.results().len(),
1338 usize::from(self.result.is_some()),
1339 );
1340 if let Some(result) = self.result {
1341 result.lower_gc(
1342 types,
1343 abi,
1344 options,
1345 offset,
1346 core_func_ty.results()[0].into(),
1347 )?;
1348 }
1349
1350 Ok(LoweredFuncType::Existing(core_type_id))
1351 }
1352}
1353
1354#[derive(Debug, Clone)]
1356pub struct VariantCase {
1357 pub ty: Option<ComponentValType>,
1359}
1360
1361#[derive(Debug, Clone)]
1363pub struct RecordType {
1364 pub(crate) info: TypeInfo,
1366 pub fields: IndexMap<KebabString, ComponentValType>,
1368}
1369
1370impl RecordType {
1371 fn lower_gc(
1372 &self,
1373 types: &TypeList,
1374 abi: Abi,
1375 options: &CanonicalOptions,
1376 offset: usize,
1377 core: ArgOrField,
1378 ) -> Result<()> {
1379 lower_gc_product_type(
1380 self.fields.values(),
1381 types,
1382 abi,
1383 options,
1384 offset,
1385 core,
1386 "record",
1387 )
1388 }
1389}
1390
1391#[derive(Debug, Clone)]
1393pub struct VariantType {
1394 pub(crate) info: TypeInfo,
1396 pub cases: IndexMap<KebabString, VariantCase>,
1398}
1399
1400impl VariantType {
1401 fn lower_gc(
1402 &self,
1403 types: &TypeList,
1404 abi: Abi,
1405 options: &CanonicalOptions,
1406 offset: usize,
1407 core: ArgOrField,
1408 ) -> Result<()> {
1409 lower_gc_sum_type(types, abi, options, offset, core, "variant")
1410 }
1411}
1412
1413fn lower_gc_sum_type(
1416 types: &TypeList,
1417 _abi: Abi,
1418 _options: &CanonicalOptions,
1419 offset: usize,
1420 core: ArgOrField,
1421 kind: &str,
1422) -> Result<()> {
1423 if let Some(id) = core.as_concrete_ref() {
1424 if let CompositeInnerType::Struct(ty) = &types[id].composite_type.inner {
1425 if ty.fields.is_empty() {
1426 return Ok(());
1427 }
1428 }
1429 }
1430
1431 bail!(
1432 offset,
1433 "expected to lower component `{kind}` type to core `(ref null? (struct))`, \
1434 but found `{core}`",
1435 )
1436}
1437
1438#[derive(Debug, Clone)]
1440pub struct TupleType {
1441 pub(crate) info: TypeInfo,
1443 pub types: Box<[ComponentValType]>,
1445}
1446
1447impl TupleType {
1448 fn lower_gc(
1449 &self,
1450 types: &TypeList,
1451 abi: Abi,
1452 options: &CanonicalOptions,
1453 offset: usize,
1454 core: ArgOrField,
1455 ) -> Result<()> {
1456 lower_gc_product_type(
1457 self.types.iter(),
1458 types,
1459 abi,
1460 options,
1461 offset,
1462 core,
1463 "tuple",
1464 )
1465 }
1466}
1467
1468#[derive(Debug, Clone)]
1470pub enum ComponentDefinedType {
1471 Primitive(PrimitiveValType),
1473 Record(RecordType),
1475 Variant(VariantType),
1477 List(ComponentValType),
1479 Map(ComponentValType, ComponentValType),
1481 FixedLengthList(ComponentValType, u32),
1483 Tuple(TupleType),
1485 Flags(IndexSet<KebabString>),
1487 Enum(IndexSet<KebabString>),
1489 Option(ComponentValType),
1491 Result {
1493 ok: Option<ComponentValType>,
1495 err: Option<ComponentValType>,
1497 },
1498 Own(AliasableResourceId),
1500 Borrow(AliasableResourceId),
1502 Future(Option<ComponentValType>),
1504 Stream(Option<ComponentValType>),
1506}
1507
1508impl TypeData for ComponentDefinedType {
1509 type Id = ComponentDefinedTypeId;
1510 const IS_CORE_SUB_TYPE: bool = false;
1511 fn type_info(&self, types: &TypeList) -> TypeInfo {
1512 match self {
1513 Self::Primitive(_)
1514 | Self::Flags(_)
1515 | Self::Enum(_)
1516 | Self::Own(_)
1517 | Self::Future(_)
1518 | Self::Stream(_) => TypeInfo::new(),
1519 Self::Borrow(_) => TypeInfo::borrow(),
1520 Self::Record(r) => r.info,
1521 Self::Variant(v) => v.info,
1522 Self::Tuple(t) => t.info,
1523 Self::List(ty) | Self::FixedLengthList(ty, _) | Self::Option(ty) => ty.info(types),
1524 Self::Map(k, v) => {
1525 let mut info = k.info(types);
1526 info.combine(v.info(types), 0).unwrap();
1527 info
1528 }
1529 Self::Result { ok, err } => {
1530 let default = TypeInfo::new();
1531 let mut info = ok.map(|ty| ty.type_info(types)).unwrap_or(default);
1532 info.combine(err.map(|ty| ty.type_info(types)).unwrap_or(default), 0)
1533 .unwrap();
1534 info
1535 }
1536 }
1537 }
1538}
1539
1540impl ComponentDefinedType {
1541 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
1542 match self {
1543 Self::Primitive(ty) => ty.contains_ptr(),
1544 Self::Record(r) => r.fields.values().any(|ty| ty.contains_ptr(types)),
1545 Self::Variant(v) => v
1546 .cases
1547 .values()
1548 .any(|case| case.ty.map(|ty| ty.contains_ptr(types)).unwrap_or(false)),
1549 Self::List(_) | Self::Map(_, _) => true,
1550 Self::Tuple(t) => t.types.iter().any(|ty| ty.contains_ptr(types)),
1551 Self::Flags(_)
1552 | Self::Enum(_)
1553 | Self::Own(_)
1554 | Self::Borrow(_)
1555 | Self::Future(_)
1556 | Self::Stream(_) => false,
1557 Self::Option(ty) | Self::FixedLengthList(ty, _) => ty.contains_ptr(types),
1558 Self::Result { ok, err } => {
1559 ok.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1560 || err.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1561 }
1562 }
1563 }
1564
1565 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1566 match self {
1567 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1568 Self::Record(r) => r
1569 .fields
1570 .iter()
1571 .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1572 Self::Variant(v) => Self::push_variant_wasm_types(
1573 v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1574 types,
1575 lowered_types,
1576 ),
1577 Self::List(_) | Self::Map(_, _) => {
1578 lowered_types.try_push(ValType::I32) && lowered_types.try_push(ValType::I32)
1579 }
1580 Self::FixedLengthList(ty, length) => {
1581 (0..*length).all(|_n| ty.push_wasm_types(types, lowered_types))
1582 }
1583 Self::Tuple(t) => t
1584 .types
1585 .iter()
1586 .all(|ty| ty.push_wasm_types(types, lowered_types)),
1587 Self::Flags(names) => {
1588 (0..(names.len() + 31) / 32).all(|_| lowered_types.try_push(ValType::I32))
1589 }
1590 Self::Enum(_) | Self::Own(_) | Self::Borrow(_) | Self::Future(_) | Self::Stream(_) => {
1591 lowered_types.try_push(ValType::I32)
1592 }
1593 Self::Option(ty) => {
1594 Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1595 }
1596 Self::Result { ok, err } => {
1597 Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1598 }
1599 }
1600 }
1601
1602 fn push_variant_wasm_types<'a>(
1603 cases: impl Iterator<Item = &'a ComponentValType>,
1604 types: &TypeList,
1605 lowered_types: &mut LoweredTypes,
1606 ) -> bool {
1607 if !lowered_types.try_push(ValType::I32) {
1609 return false;
1610 }
1611
1612 let start = lowered_types.len();
1613
1614 for ty in cases {
1615 let mut temp = LoweredTypes::new(lowered_types.max);
1616
1617 if !ty.push_wasm_types(types, &mut temp) {
1618 return false;
1619 }
1620
1621 for (i, ty) in temp.iter().enumerate() {
1622 match lowered_types.get_mut(start + i) {
1623 Some(prev) => *prev = Self::join_types(*prev, ty),
1624 None => {
1625 if !lowered_types.try_push(ty) {
1626 return false;
1627 }
1628 }
1629 }
1630 }
1631 }
1632
1633 true
1634 }
1635
1636 fn join_types(a: ValType, b: ValType) -> ValType {
1637 use ValType::*;
1638
1639 match (a, b) {
1640 (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1641 (I32, F32) | (F32, I32) => I32,
1642 (_, I64 | F64) | (I64 | F64, _) => I64,
1643 _ => panic!("unexpected wasm type for canonical ABI"),
1644 }
1645 }
1646
1647 fn desc(&self) -> &'static str {
1648 match self {
1649 ComponentDefinedType::Record(_) => "record",
1650 ComponentDefinedType::Primitive(_) => "primitive",
1651 ComponentDefinedType::Variant(_) => "variant",
1652 ComponentDefinedType::Tuple(_) => "tuple",
1653 ComponentDefinedType::Enum(_) => "enum",
1654 ComponentDefinedType::Flags(_) => "flags",
1655 ComponentDefinedType::Option(_) => "option",
1656 ComponentDefinedType::List(_) => "list",
1657 ComponentDefinedType::Map(_, _) => "map",
1658 ComponentDefinedType::FixedLengthList(_, _) => "fixed-length list",
1659 ComponentDefinedType::Result { .. } => "result",
1660 ComponentDefinedType::Own(_) => "own",
1661 ComponentDefinedType::Borrow(_) => "borrow",
1662 ComponentDefinedType::Future(_) => "future",
1663 ComponentDefinedType::Stream(_) => "stream",
1664 }
1665 }
1666
1667 fn lower_gc(
1668 &self,
1669 types: &TypeList,
1670 abi: Abi,
1671 options: &CanonicalOptions,
1672 offset: usize,
1673 core: ArgOrField,
1674 ) -> Result<()> {
1675 match self {
1676 ComponentDefinedType::Primitive(ty) => ty.lower_gc(types, abi, options, offset, core),
1677
1678 ComponentDefinedType::Record(ty) => ty.lower_gc(types, abi, options, offset, core),
1679
1680 ComponentDefinedType::Variant(ty) => ty.lower_gc(types, abi, options, offset, core),
1681
1682 ComponentDefinedType::List(ty) | ComponentDefinedType::FixedLengthList(ty, _) => {
1683 let id = match core.as_concrete_ref() {
1684 Some(id) => id,
1685 None => bail!(
1686 offset,
1687 "expected to lower component `list` type into `(ref null? (array ...))`, but \
1688 found `{core}`",
1689 ),
1690 };
1691 let array_ty = match types[id].composite_type.inner {
1692 CompositeInnerType::Array(ty) => ty,
1693 _ => bail!(
1694 offset,
1695 "expected to lower component `list` type into `(ref null? (array ...))`, but \
1696 found `{core}`",
1697 ),
1698 };
1699 ty.lower_gc(types, abi, options, offset, array_ty.0.element_type.into())
1700 }
1701
1702 ComponentDefinedType::Map(_, _) => bail!(
1703 offset,
1704 "GC lowering for component `map` type is not yet implemented"
1705 ),
1706
1707 ComponentDefinedType::Tuple(ty) => ty.lower_gc(types, abi, options, offset, core),
1708
1709 ComponentDefinedType::Flags(flags) => {
1710 assert!(flags.len() <= 32, "required by validation");
1711 if core.as_val_type() == Some(ValType::I32) {
1712 Ok(())
1713 } else {
1714 bail!(
1715 offset,
1716 "expected to lower component `flags` type into core `i32` type, but \
1717 found `{core}`",
1718 )
1719 }
1720 }
1721
1722 ComponentDefinedType::Enum(_) => {
1723 if core.as_val_type() == Some(ValType::I32) {
1724 Ok(())
1725 } else {
1726 bail!(
1727 offset,
1728 "expected to lower component `enum` type into core `i32` type, but \
1729 found `{core}`",
1730 )
1731 }
1732 }
1733
1734 ComponentDefinedType::Option(_) => {
1735 lower_gc_sum_type(types, abi, options, offset, core, "option")
1736 }
1737
1738 ComponentDefinedType::Result { .. } => {
1739 lower_gc_sum_type(types, abi, options, offset, core, "result")
1740 }
1741
1742 ComponentDefinedType::Own(_)
1743 | ComponentDefinedType::Borrow(_)
1744 | ComponentDefinedType::Future(_)
1745 | ComponentDefinedType::Stream(_) => {
1746 if let Some(r) = core.as_ref_type() {
1747 if let HeapType::Abstract {
1748 shared: _,
1749 ty: AbstractHeapType::Extern,
1750 } = r.heap_type()
1751 {
1752 return Ok(());
1753 }
1754 }
1755 bail!(
1756 offset,
1757 "expected to lower component `{}` type into core `(ref null? extern)` type, but \
1758 found `{core}`",
1759 self.desc()
1760 )
1761 }
1762 }
1763 }
1764}
1765
1766fn lower_gc_product_type<'a, I>(
1769 fields: I,
1770 types: &TypeList,
1771 abi: Abi,
1772 options: &CanonicalOptions,
1773 offset: usize,
1774 core: ArgOrField,
1775 kind: &str,
1776) -> core::result::Result<(), BinaryReaderError>
1777where
1778 I: IntoIterator<Item = &'a ComponentValType>,
1779 I::IntoIter: ExactSizeIterator,
1780{
1781 let fields = fields.into_iter();
1782 let fields_len = fields.len();
1783
1784 if let Some(id) = core.as_concrete_ref() {
1785 if let CompositeInnerType::Struct(ty) = &types[id].composite_type.inner {
1786 ensure!(
1787 ty.fields.len() == fields_len,
1788 offset,
1789 "core `struct` has {} fields, but component `{kind}` has {fields_len} fields",
1790 ty.fields.len(),
1791 );
1792 for (core, comp) in ty.fields.iter().zip(fields) {
1793 comp.lower_gc(types, abi, options, offset, core.element_type.into())?;
1794 }
1795 return Ok(());
1796 }
1797 }
1798
1799 bail!(
1800 offset,
1801 "expected to lower component `{kind}` type to core `(ref null? (struct ...))`, \
1802 but found `{core}`",
1803 )
1804}
1805
1806#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
1809#[repr(packed(4))] pub struct ResourceId {
1811 globally_unique_id: usize,
1821
1822 contextually_unique_id: u32,
1831}
1832
1833impl<'a> TypesRef<'a> {
1834 pub fn core_type_at_in_component(&self, index: u32) -> ComponentCoreTypeId {
1845 match &self.kind {
1846 TypesRefKind::Module(_) => panic!("use `component_type_at_in_module` instead"),
1847 TypesRefKind::Component(component) => component.core_types[index as usize],
1848 }
1849 }
1850
1851 pub fn core_type_count_in_component(&self) -> u32 {
1856 match &self.kind {
1857 TypesRefKind::Module(_) => 0,
1858 TypesRefKind::Component(component) => component.core_types.len() as u32,
1859 }
1860 }
1861
1862 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1869 match &self.kind {
1870 TypesRefKind::Module(_) => panic!("not a component"),
1871 TypesRefKind::Component(component) => component.types[index as usize],
1872 }
1873 }
1874
1875 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1882 match self.component_any_type_at(index) {
1883 ComponentAnyTypeId::Component(id) => id,
1884 _ => panic!("not a component type"),
1885 }
1886 }
1887
1888 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1895 match self.component_any_type_at(index) {
1896 ComponentAnyTypeId::Defined(id) => id,
1897 _ => panic!("not a defined type"),
1898 }
1899 }
1900
1901 pub fn component_type_count(&self) -> u32 {
1903 match &self.kind {
1904 TypesRefKind::Module(_module) => 0,
1905 TypesRefKind::Component(component) => component.types.len() as u32,
1906 }
1907 }
1908
1909 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
1916 match &self.kind {
1917 TypesRefKind::Module(_) => panic!("not a component"),
1918 TypesRefKind::Component(component) => component.funcs[index as usize],
1919 }
1920 }
1921
1922 pub fn component_function_count(&self) -> u32 {
1924 match &self.kind {
1925 TypesRefKind::Module(_module) => 0,
1926 TypesRefKind::Component(component) => component.funcs.len() as u32,
1927 }
1928 }
1929
1930 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
1937 match &self.kind {
1938 TypesRefKind::Module(_) => panic!("not a component"),
1939 TypesRefKind::Component(component) => component.core_modules[index as usize],
1940 }
1941 }
1942
1943 pub fn module_count(&self) -> u32 {
1945 match &self.kind {
1946 TypesRefKind::Module(_module) => 0,
1947 TypesRefKind::Component(component) => component.core_modules.len() as u32,
1948 }
1949 }
1950
1951 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
1958 match &self.kind {
1959 TypesRefKind::Module(_) => panic!("not a component"),
1960 TypesRefKind::Component(component) => component.core_instances[index as usize],
1961 }
1962 }
1963
1964 pub fn core_instance_count(&self) -> u32 {
1966 match &self.kind {
1967 TypesRefKind::Module(_module) => 0,
1968 TypesRefKind::Component(component) => component.core_instances.len() as u32,
1969 }
1970 }
1971
1972 pub fn component_at(&self, index: u32) -> ComponentTypeId {
1979 match &self.kind {
1980 TypesRefKind::Module(_) => panic!("not a component"),
1981 TypesRefKind::Component(component) => component.components[index as usize],
1982 }
1983 }
1984
1985 pub fn component_count(&self) -> u32 {
1987 match &self.kind {
1988 TypesRefKind::Module(_module) => 0,
1989 TypesRefKind::Component(component) => component.components.len() as u32,
1990 }
1991 }
1992
1993 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
2000 match &self.kind {
2001 TypesRefKind::Module(_) => panic!("not a component"),
2002 TypesRefKind::Component(component) => component.instances[index as usize],
2003 }
2004 }
2005
2006 pub fn component_instance_count(&self) -> u32 {
2008 match &self.kind {
2009 TypesRefKind::Module(_module) => 0,
2010 TypesRefKind::Component(component) => component.instances.len() as u32,
2011 }
2012 }
2013
2014 pub fn value_at(&self, index: u32) -> ComponentValType {
2021 match &self.kind {
2022 TypesRefKind::Module(_) => panic!("not a component"),
2023 TypesRefKind::Component(component) => component.values[index as usize].0,
2024 }
2025 }
2026
2027 pub fn value_count(&self) -> u32 {
2029 match &self.kind {
2030 TypesRefKind::Module(_module) => 0,
2031 TypesRefKind::Component(component) => component.values.len() as u32,
2032 }
2033 }
2034
2035 pub fn component_item_for_import(&self, name: &str) -> Option<&'a ComponentItem> {
2037 match &self.kind {
2038 TypesRefKind::Module(_) => None,
2039 TypesRefKind::Component(component) => Some(component.imports.get(name)?),
2040 }
2041 }
2042
2043 pub fn component_item_for_export(&self, name: &str) -> Option<&'a ComponentItem> {
2045 match &self.kind {
2046 TypesRefKind::Module(_) => None,
2047 TypesRefKind::Component(component) => Some(component.exports.get(name)?),
2048 }
2049 }
2050
2051 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2055 where
2056 T: Aliasable,
2057 {
2058 self.list.peel_alias(ty)
2059 }
2060}
2061
2062impl Types {
2063 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
2072 self.as_ref().component_any_type_at(index)
2073 }
2074
2075 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
2081 self.as_ref().component_type_at(index)
2082 }
2083
2084 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
2091 self.as_ref().component_defined_type_at(index)
2092 }
2093
2094 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
2101 self.as_ref().component_function_at(index)
2102 }
2103
2104 pub fn component_function_count(&self) -> u32 {
2106 self.as_ref().component_function_count()
2107 }
2108
2109 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
2116 self.as_ref().module_at(index)
2117 }
2118
2119 pub fn module_count(&self) -> usize {
2121 match &self.kind {
2122 TypesKind::Module(_) => 0,
2123 TypesKind::Component(component) => component.core_modules.len(),
2124 }
2125 }
2126
2127 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
2134 self.as_ref().core_instance_at(index)
2135 }
2136
2137 pub fn core_instance_count(&self) -> usize {
2139 match &self.kind {
2140 TypesKind::Module(_) => 0,
2141 TypesKind::Component(component) => component.core_instances.len(),
2142 }
2143 }
2144
2145 pub fn component_at(&self, index: u32) -> ComponentTypeId {
2152 self.as_ref().component_at(index)
2153 }
2154
2155 pub fn component_count(&self) -> usize {
2157 match &self.kind {
2158 TypesKind::Module(_) => 0,
2159 TypesKind::Component(component) => component.components.len(),
2160 }
2161 }
2162
2163 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
2170 self.as_ref().component_instance_at(index)
2171 }
2172
2173 pub fn component_instance_count(&self) -> usize {
2175 match &self.kind {
2176 TypesKind::Module(_) => 0,
2177 TypesKind::Component(component) => component.instances.len(),
2178 }
2179 }
2180
2181 pub fn value_at(&self, index: u32) -> ComponentValType {
2188 self.as_ref().value_at(index)
2189 }
2190
2191 pub fn value_count(&self) -> usize {
2193 match &self.kind {
2194 TypesKind::Module(_) => 0,
2195 TypesKind::Component(component) => component.values.len(),
2196 }
2197 }
2198
2199 pub fn component_item_for_import(&self, name: &str) -> Option<&ComponentItem> {
2201 self.as_ref().component_item_for_import(name)
2202 }
2203
2204 pub fn component_item_for_export(&self, name: &str) -> Option<&ComponentItem> {
2206 self.as_ref().component_item_for_export(name)
2207 }
2208
2209 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2213 where
2214 T: Aliasable,
2215 {
2216 self.list.peel_alias(ty)
2217 }
2218}
2219
2220#[derive(Debug, Default)]
2222pub(crate) struct ComponentTypeList {
2223 alias_mappings: Map<u32, u32>,
2225 alias_counter: u32,
2227 alias_snapshots: Vec<TypeListAliasSnapshot>,
2229
2230 components: SnapshotList<ComponentType>,
2232 component_defined_types: SnapshotList<ComponentDefinedType>,
2233 component_values: SnapshotList<ComponentValType>,
2234 component_instances: SnapshotList<ComponentInstanceType>,
2235 component_funcs: SnapshotList<ComponentFuncType>,
2236 core_modules: SnapshotList<ModuleType>,
2237 core_instances: SnapshotList<InstanceType>,
2238}
2239
2240#[derive(Clone, Debug)]
2241struct TypeListAliasSnapshot {
2242 alias_counter: u32,
2244
2245 alias_mappings: Map<u32, u32>,
2247}
2248
2249struct TypeListCheckpoint {
2250 core_types: usize,
2251 components: usize,
2252 component_defined_types: usize,
2253 component_values: usize,
2254 component_instances: usize,
2255 component_funcs: usize,
2256 core_modules: usize,
2257 core_instances: usize,
2258 core_type_to_rec_group: usize,
2259 core_type_to_supertype: usize,
2260 core_type_to_depth: usize,
2261 rec_group_elements: usize,
2262 canonical_rec_groups: usize,
2263}
2264
2265impl TypeList {
2266 fn checkpoint(&self) -> TypeListCheckpoint {
2267 let TypeList {
2268 component:
2269 ComponentTypeList {
2270 alias_mappings: _,
2271 alias_counter: _,
2272 alias_snapshots: _,
2273 components,
2274 component_defined_types,
2275 component_values,
2276 component_instances,
2277 component_funcs,
2278 core_modules,
2279 core_instances,
2280 },
2281 core_types,
2282 core_type_to_rec_group,
2283 core_type_to_supertype,
2284 core_type_to_depth,
2285 rec_group_elements,
2286 canonical_rec_groups,
2287 } = self;
2288
2289 TypeListCheckpoint {
2290 core_types: core_types.len(),
2291 components: components.len(),
2292 component_defined_types: component_defined_types.len(),
2293 component_values: component_values.len(),
2294 component_instances: component_instances.len(),
2295 component_funcs: component_funcs.len(),
2296 core_modules: core_modules.len(),
2297 core_instances: core_instances.len(),
2298 core_type_to_rec_group: core_type_to_rec_group.len(),
2299 core_type_to_supertype: core_type_to_supertype.len(),
2300 core_type_to_depth: core_type_to_depth.as_ref().map(|m| m.len()).unwrap_or(0),
2301 rec_group_elements: rec_group_elements.len(),
2302 canonical_rec_groups: canonical_rec_groups.as_ref().map(|m| m.len()).unwrap_or(0),
2303 }
2304 }
2305
2306 fn reset_to_checkpoint(&mut self, checkpoint: TypeListCheckpoint) {
2307 let TypeList {
2308 component:
2309 ComponentTypeList {
2310 alias_mappings: _,
2311 alias_counter: _,
2312 alias_snapshots: _,
2313 components,
2314 component_defined_types,
2315 component_values,
2316 component_instances,
2317 component_funcs,
2318 core_modules,
2319 core_instances,
2320 },
2321 core_types,
2322 core_type_to_rec_group,
2323 core_type_to_supertype,
2324 core_type_to_depth,
2325 rec_group_elements,
2326 canonical_rec_groups,
2327 } = self;
2328
2329 core_types.truncate(checkpoint.core_types);
2330 components.truncate(checkpoint.components);
2331 component_defined_types.truncate(checkpoint.component_defined_types);
2332 component_values.truncate(checkpoint.component_values);
2333 component_instances.truncate(checkpoint.component_instances);
2334 component_funcs.truncate(checkpoint.component_funcs);
2335 core_modules.truncate(checkpoint.core_modules);
2336 core_instances.truncate(checkpoint.core_instances);
2337 core_type_to_rec_group.truncate(checkpoint.core_type_to_rec_group);
2338 core_type_to_supertype.truncate(checkpoint.core_type_to_supertype);
2339 rec_group_elements.truncate(checkpoint.rec_group_elements);
2340
2341 if let Some(core_type_to_depth) = core_type_to_depth {
2342 assert_eq!(
2343 core_type_to_depth.len(),
2344 checkpoint.core_type_to_depth,
2345 "checkpointing does not support resetting `core_type_to_depth` (it would require a \
2346 proper immutable and persistent hash map) so adding new groups is disallowed"
2347 );
2348 }
2349 if let Some(canonical_rec_groups) = canonical_rec_groups {
2350 assert_eq!(
2351 canonical_rec_groups.len(),
2352 checkpoint.canonical_rec_groups,
2353 "checkpointing does not support resetting `canonical_rec_groups` (it would require a \
2354 proper immutable and persistent hash map) so adding new groups is disallowed"
2355 );
2356 }
2357 }
2358
2359 pub fn with_unique<T>(&mut self, mut ty: T) -> T
2361 where
2362 T: Aliasable,
2363 {
2364 self.component
2365 .alias_mappings
2366 .insert(self.component.alias_counter, ty.alias_id());
2367 ty.set_alias_id(self.component.alias_counter);
2368 self.component.alias_counter += 1;
2369 ty
2370 }
2371
2372 pub fn peel_alias<T>(&self, mut ty: T) -> Option<T>
2376 where
2377 T: Aliasable,
2378 {
2379 let alias_id = ty.alias_id();
2380
2381 let i = match self
2388 .component
2389 .alias_snapshots
2390 .binary_search_by_key(&alias_id, |snapshot| snapshot.alias_counter)
2391 {
2392 Ok(_) => unreachable!(),
2393 Err(i) => i,
2394 };
2395
2396 ty.set_alias_id(match self.component.alias_snapshots.get(i) {
2400 Some(snapshot) => *snapshot.alias_mappings.get(&alias_id)?,
2401 None => *self.component.alias_mappings.get(&alias_id)?,
2402 });
2403 Some(ty)
2404 }
2405}
2406
2407impl ComponentTypeList {
2408 pub fn commit(&mut self) -> ComponentTypeList {
2409 let alias_counter = self.alias_counter;
2413 self.alias_counter += 1;
2414
2415 self.alias_snapshots.push(TypeListAliasSnapshot {
2416 alias_counter,
2417 alias_mappings: mem::take(&mut self.alias_mappings),
2418 });
2419
2420 ComponentTypeList {
2421 alias_mappings: Map::default(),
2422 alias_counter: self.alias_counter,
2423 alias_snapshots: self.alias_snapshots.clone(),
2424 components: self.components.commit(),
2425 component_defined_types: self.component_defined_types.commit(),
2426 component_values: self.component_values.commit(),
2427 component_instances: self.component_instances.commit(),
2428 component_funcs: self.component_funcs.commit(),
2429 core_modules: self.core_modules.commit(),
2430 core_instances: self.core_instances.commit(),
2431 }
2432 }
2433}
2434
2435pub(crate) struct ComponentTypeAlloc {
2436 globally_unique_id: usize,
2439
2440 next_resource_id: u32,
2443}
2444
2445impl Default for ComponentTypeAlloc {
2446 fn default() -> ComponentTypeAlloc {
2447 static NEXT_GLOBAL_ID: AtomicUsize = AtomicUsize::new(0);
2448 ComponentTypeAlloc {
2449 globally_unique_id: {
2450 let id = NEXT_GLOBAL_ID.fetch_add(1, Ordering::Relaxed);
2451 if id > usize::MAX - 10_000 {
2452 NEXT_GLOBAL_ID.store(usize::MAX - 10_000, Ordering::Relaxed);
2453 panic!("overflow on the global id counter");
2454 }
2455 id
2456 },
2457 next_resource_id: 0,
2458 }
2459 }
2460}
2461
2462impl TypeAlloc {
2463 pub fn alloc_resource_id(&mut self) -> AliasableResourceId {
2467 let contextually_unique_id = self.component_alloc.next_resource_id;
2468 self.component_alloc.next_resource_id = self
2469 .component_alloc
2470 .next_resource_id
2471 .checked_add(1)
2472 .unwrap();
2473 AliasableResourceId {
2474 id: ResourceId {
2475 globally_unique_id: self.component_alloc.globally_unique_id,
2476 contextually_unique_id,
2477 },
2478 alias_id: NO_ALIAS,
2479 }
2480 }
2481
2482 pub fn free_variables_any_type_id(
2489 &self,
2490 id: ComponentAnyTypeId,
2491 set: &mut IndexSet<ResourceId>,
2492 ) {
2493 match id {
2494 ComponentAnyTypeId::Resource(r) => {
2495 set.insert(r.resource());
2496 }
2497 ComponentAnyTypeId::Defined(id) => {
2498 self.free_variables_component_defined_type_id(id, set)
2499 }
2500 ComponentAnyTypeId::Func(id) => self.free_variables_component_func_type_id(id, set),
2501 ComponentAnyTypeId::Instance(id) => {
2502 self.free_variables_component_instance_type_id(id, set)
2503 }
2504 ComponentAnyTypeId::Component(id) => self.free_variables_component_type_id(id, set),
2505 }
2506 }
2507
2508 pub fn free_variables_component_defined_type_id(
2509 &self,
2510 id: ComponentDefinedTypeId,
2511 set: &mut IndexSet<ResourceId>,
2512 ) {
2513 match &self[id] {
2514 ComponentDefinedType::Primitive(_)
2515 | ComponentDefinedType::Flags(_)
2516 | ComponentDefinedType::Enum(_) => {}
2517 ComponentDefinedType::Record(r) => {
2518 for ty in r.fields.values() {
2519 self.free_variables_valtype(ty, set);
2520 }
2521 }
2522 ComponentDefinedType::Tuple(r) => {
2523 for ty in r.types.iter() {
2524 self.free_variables_valtype(ty, set);
2525 }
2526 }
2527 ComponentDefinedType::Variant(r) => {
2528 for ty in r.cases.values() {
2529 if let Some(ty) = &ty.ty {
2530 self.free_variables_valtype(ty, set);
2531 }
2532 }
2533 }
2534 ComponentDefinedType::List(ty)
2535 | ComponentDefinedType::FixedLengthList(ty, _)
2536 | ComponentDefinedType::Option(ty) => {
2537 self.free_variables_valtype(ty, set);
2538 }
2539 ComponentDefinedType::Map(k, v) => {
2540 self.free_variables_valtype(k, set);
2541 self.free_variables_valtype(v, set);
2542 }
2543 ComponentDefinedType::Result { ok, err } => {
2544 if let Some(ok) = ok {
2545 self.free_variables_valtype(ok, set);
2546 }
2547 if let Some(err) = err {
2548 self.free_variables_valtype(err, set);
2549 }
2550 }
2551 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2552 set.insert(id.resource());
2553 }
2554 ComponentDefinedType::Future(ty) => {
2555 if let Some(ty) = ty {
2556 self.free_variables_valtype(ty, set);
2557 }
2558 }
2559 ComponentDefinedType::Stream(ty) => {
2560 if let Some(ty) = ty {
2561 self.free_variables_valtype(ty, set);
2562 }
2563 }
2564 }
2565 }
2566
2567 pub fn free_variables_component_type_id(
2568 &self,
2569 id: ComponentTypeId,
2570 set: &mut IndexSet<ResourceId>,
2571 ) {
2572 let i = &self[id];
2573 for ty in i.imports.values().chain(i.exports.values()) {
2584 self.free_variables_component_entity(&ty.ty, set);
2585 }
2586 for (id, _path) in i.imported_resources.iter().chain(&i.defined_resources) {
2587 set.swap_remove(id);
2588 }
2589 }
2590
2591 pub fn free_variables_component_instance_type_id(
2592 &self,
2593 id: ComponentInstanceTypeId,
2594 set: &mut IndexSet<ResourceId>,
2595 ) {
2596 let i = &self[id];
2597 for ty in i.exports.values() {
2601 self.free_variables_component_entity(&ty.ty, set);
2602 }
2603 for id in i.defined_resources.iter() {
2604 set.swap_remove(id);
2605 }
2606 }
2607
2608 pub fn free_variables_component_func_type_id(
2609 &self,
2610 id: ComponentFuncTypeId,
2611 set: &mut IndexSet<ResourceId>,
2612 ) {
2613 let i = &self[id];
2614 for ty in i.params.iter().map(|(_, ty)| ty).chain(&i.result) {
2615 self.free_variables_valtype(ty, set);
2616 }
2617 }
2618
2619 pub fn free_variables_component_entity(
2621 &self,
2622 ty: &ComponentEntityType,
2623 set: &mut IndexSet<ResourceId>,
2624 ) {
2625 match ty {
2626 ComponentEntityType::Module(_) => {}
2627 ComponentEntityType::Func(id) => self.free_variables_component_func_type_id(*id, set),
2628 ComponentEntityType::Instance(id) => {
2629 self.free_variables_component_instance_type_id(*id, set)
2630 }
2631 ComponentEntityType::Component(id) => self.free_variables_component_type_id(*id, set),
2632 ComponentEntityType::Type { created, .. } => {
2633 self.free_variables_any_type_id(*created, set);
2634 }
2635 ComponentEntityType::Value(ty) => self.free_variables_valtype(ty, set),
2636 }
2637 }
2638
2639 fn free_variables_valtype(&self, ty: &ComponentValType, set: &mut IndexSet<ResourceId>) {
2641 match ty {
2642 ComponentValType::Primitive(_) => {}
2643 ComponentValType::Type(id) => self.free_variables_component_defined_type_id(*id, set),
2644 }
2645 }
2646
2647 pub(crate) fn type_named_type_id(
2652 &self,
2653 id: ComponentDefinedTypeId,
2654 set: &Set<ComponentAnyTypeId>,
2655 ) -> bool {
2656 let ty = &self[id];
2657 match ty {
2658 ComponentDefinedType::Primitive(_) => true,
2660
2661 ComponentDefinedType::Flags(_)
2664 | ComponentDefinedType::Enum(_)
2665 | ComponentDefinedType::Record(_)
2666 | ComponentDefinedType::Variant(_) => set.contains(&ComponentAnyTypeId::from(id)),
2667
2668 ComponentDefinedType::Tuple(r) => {
2671 r.types.iter().all(|t| self.type_named_valtype(t, set))
2672 }
2673 ComponentDefinedType::Result { ok, err } => {
2674 ok.as_ref()
2675 .map(|t| self.type_named_valtype(t, set))
2676 .unwrap_or(true)
2677 && err
2678 .as_ref()
2679 .map(|t| self.type_named_valtype(t, set))
2680 .unwrap_or(true)
2681 }
2682 ComponentDefinedType::List(ty)
2683 | ComponentDefinedType::FixedLengthList(ty, _)
2684 | ComponentDefinedType::Option(ty) => self.type_named_valtype(ty, set),
2685 ComponentDefinedType::Map(k, v) => {
2686 self.type_named_valtype(k, set) && self.type_named_valtype(v, set)
2687 }
2688
2689 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2692 set.contains(&ComponentAnyTypeId::from(*id))
2693 }
2694
2695 ComponentDefinedType::Future(ty) => ty
2696 .as_ref()
2697 .map(|ty| self.type_named_valtype(ty, set))
2698 .unwrap_or(true),
2699
2700 ComponentDefinedType::Stream(ty) => ty
2701 .as_ref()
2702 .map(|ty| self.type_named_valtype(ty, set))
2703 .unwrap_or(true),
2704 }
2705 }
2706
2707 pub(crate) fn type_named_valtype(
2708 &self,
2709 ty: &ComponentValType,
2710 set: &Set<ComponentAnyTypeId>,
2711 ) -> bool {
2712 match ty {
2713 ComponentValType::Primitive(_) => true,
2714 ComponentValType::Type(id) => self.type_named_type_id(*id, set),
2715 }
2716 }
2717}
2718
2719pub trait Remap
2725where
2726 Self: Index<ComponentTypeId, Output = ComponentType>,
2727 Self: Index<ComponentDefinedTypeId, Output = ComponentDefinedType>,
2728 Self: Index<ComponentInstanceTypeId, Output = ComponentInstanceType>,
2729 Self: Index<ComponentFuncTypeId, Output = ComponentFuncType>,
2730{
2731 #[doc(hidden)]
2736 fn push_ty<T>(&mut self, ty: T) -> T::Id
2737 where
2738 T: TypeData;
2739
2740 fn map_map(
2743 tmp: &mut IndexMap<ResourceId, Vec<usize>>,
2744 any_changed: &mut bool,
2745 map: &Remapping,
2746 ) {
2747 for (id, path) in mem::take(tmp) {
2748 let id = match map.resources.get(&id) {
2749 Some(id) => {
2750 *any_changed = true;
2751 *id
2752 }
2753 None => id,
2754 };
2755 tmp.insert(id, path);
2756 }
2757 }
2758
2759 fn insert_if_any_changed<T>(
2763 &mut self,
2764 map: &mut Remapping,
2765 any_changed: bool,
2766 id: &mut T::Id,
2767 ty: T,
2768 ) -> bool
2769 where
2770 T: TypeData,
2771 T::Id: Into<ComponentAnyTypeId>,
2772 {
2773 let new = if any_changed { self.push_ty(ty) } else { *id };
2774 map.types.insert((*id).into(), new.into());
2775 let changed = *id != new;
2776 *id = new;
2777 changed
2778 }
2779
2780 fn remap_component_any_type_id(
2784 &mut self,
2785 id: &mut ComponentAnyTypeId,
2786 map: &mut Remapping,
2787 ) -> bool {
2788 match id {
2789 ComponentAnyTypeId::Resource(id) => self.remap_resource_id(id, map),
2790 ComponentAnyTypeId::Defined(id) => self.remap_component_defined_type_id(id, map),
2791 ComponentAnyTypeId::Func(id) => self.remap_component_func_type_id(id, map),
2792 ComponentAnyTypeId::Instance(id) => self.remap_component_instance_type_id(id, map),
2793 ComponentAnyTypeId::Component(id) => self.remap_component_type_id(id, map),
2794 }
2795 }
2796
2797 fn remap_resource_id(&mut self, id: &mut AliasableResourceId, map: &Remapping) -> bool {
2800 if let Some(changed) = map.remap_id(id) {
2801 return changed;
2802 }
2803
2804 match map.resources.get(&id.resource()) {
2805 None => false,
2806 Some(new_id) => {
2807 *id.resource_mut() = *new_id;
2808 true
2809 }
2810 }
2811 }
2812
2813 fn remap_component_type_id(&mut self, id: &mut ComponentTypeId, map: &mut Remapping) -> bool {
2817 if let Some(changed) = map.remap_id(id) {
2818 return changed;
2819 }
2820
2821 let mut any_changed = false;
2822 let mut ty = self[*id].clone();
2823 for ty in ty.imports.values_mut().chain(ty.exports.values_mut()) {
2824 any_changed |= self.remap_component_entity(&mut ty.ty, map);
2825 }
2826 for (id, _) in ty
2827 .imported_resources
2828 .iter_mut()
2829 .chain(&mut ty.defined_resources)
2830 {
2831 if let Some(new) = map.resources.get(id) {
2832 *id = *new;
2833 any_changed = true;
2834 }
2835 }
2836 Self::map_map(&mut ty.explicit_resources, &mut any_changed, map);
2837 self.insert_if_any_changed(map, any_changed, id, ty)
2838 }
2839
2840 fn remap_component_defined_type_id(
2844 &mut self,
2845 id: &mut ComponentDefinedTypeId,
2846 map: &mut Remapping,
2847 ) -> bool {
2848 if let Some(changed) = map.remap_id(id) {
2849 return changed;
2850 }
2851
2852 let mut any_changed = false;
2853 let mut tmp = self[*id].clone();
2854 match &mut tmp {
2855 ComponentDefinedType::Primitive(_)
2856 | ComponentDefinedType::Flags(_)
2857 | ComponentDefinedType::Enum(_) => {}
2858 ComponentDefinedType::Record(r) => {
2859 for ty in r.fields.values_mut() {
2860 any_changed |= self.remap_valtype(ty, map);
2861 }
2862 }
2863 ComponentDefinedType::Tuple(r) => {
2864 for ty in r.types.iter_mut() {
2865 any_changed |= self.remap_valtype(ty, map);
2866 }
2867 }
2868 ComponentDefinedType::Variant(r) => {
2869 for ty in r.cases.values_mut() {
2870 if let Some(ty) = &mut ty.ty {
2871 any_changed |= self.remap_valtype(ty, map);
2872 }
2873 }
2874 }
2875 ComponentDefinedType::List(ty)
2876 | ComponentDefinedType::FixedLengthList(ty, _)
2877 | ComponentDefinedType::Option(ty) => {
2878 any_changed |= self.remap_valtype(ty, map);
2879 }
2880 ComponentDefinedType::Map(k, v) => {
2881 any_changed |= self.remap_valtype(k, map);
2882 any_changed |= self.remap_valtype(v, map);
2883 }
2884 ComponentDefinedType::Result { ok, err } => {
2885 if let Some(ok) = ok {
2886 any_changed |= self.remap_valtype(ok, map);
2887 }
2888 if let Some(err) = err {
2889 any_changed |= self.remap_valtype(err, map);
2890 }
2891 }
2892 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2893 any_changed |= self.remap_resource_id(id, map);
2894 }
2895 ComponentDefinedType::Future(ty) | ComponentDefinedType::Stream(ty) => {
2896 if let Some(ty) = ty {
2897 any_changed |= self.remap_valtype(ty, map);
2898 }
2899 }
2900 }
2901 self.insert_if_any_changed(map, any_changed, id, tmp)
2902 }
2903
2904 fn remap_component_instance_type_id(
2908 &mut self,
2909 id: &mut ComponentInstanceTypeId,
2910 map: &mut Remapping,
2911 ) -> bool {
2912 if let Some(changed) = map.remap_id(id) {
2913 return changed;
2914 }
2915
2916 let mut any_changed = false;
2917 let mut tmp = self[*id].clone();
2918 for ty in tmp.exports.values_mut() {
2919 any_changed |= self.remap_component_entity(&mut ty.ty, map);
2920 }
2921 for id in tmp.defined_resources.iter_mut() {
2922 if let Some(new) = map.resources.get(id) {
2923 *id = *new;
2924 any_changed = true;
2925 }
2926 }
2927 Self::map_map(&mut tmp.explicit_resources, &mut any_changed, map);
2928 self.insert_if_any_changed(map, any_changed, id, tmp)
2929 }
2930
2931 fn remap_component_func_type_id(
2935 &mut self,
2936 id: &mut ComponentFuncTypeId,
2937 map: &mut Remapping,
2938 ) -> bool {
2939 if let Some(changed) = map.remap_id(id) {
2940 return changed;
2941 }
2942
2943 let mut any_changed = false;
2944 let mut tmp = self[*id].clone();
2945 for ty in tmp
2946 .params
2947 .iter_mut()
2948 .map(|(_, ty)| ty)
2949 .chain(&mut tmp.result)
2950 {
2951 any_changed |= self.remap_valtype(ty, map);
2952 }
2953 self.insert_if_any_changed(map, any_changed, id, tmp)
2954 }
2955
2956 fn remap_component_entity(
2958 &mut self,
2959 ty: &mut ComponentEntityType,
2960 map: &mut Remapping,
2961 ) -> bool {
2962 match ty {
2963 ComponentEntityType::Module(_) => {
2964 false
2966 }
2967 ComponentEntityType::Func(id) => self.remap_component_func_type_id(id, map),
2968 ComponentEntityType::Instance(id) => self.remap_component_instance_type_id(id, map),
2969 ComponentEntityType::Component(id) => self.remap_component_type_id(id, map),
2970 ComponentEntityType::Type {
2971 referenced,
2972 created,
2973 } => {
2974 let mut changed = self.remap_component_any_type_id(referenced, map);
2975 if *referenced == *created {
2976 *created = *referenced;
2977 } else {
2978 changed |= self.remap_component_any_type_id(created, map);
2979 }
2980 changed
2981 }
2982 ComponentEntityType::Value(ty) => self.remap_valtype(ty, map),
2983 }
2984 }
2985
2986 fn remap_valtype(&mut self, ty: &mut ComponentValType, map: &mut Remapping) -> bool {
2988 match ty {
2989 ComponentValType::Primitive(_) => false,
2990 ComponentValType::Type(id) => self.remap_component_defined_type_id(id, map),
2991 }
2992 }
2993}
2994
2995#[derive(Debug, Default)]
2998pub struct Remapping {
2999 pub(crate) resources: Map<ResourceId, ResourceId>,
3001
3002 types: Map<ComponentAnyTypeId, ComponentAnyTypeId>,
3006}
3007
3008impl Remap for TypeAlloc {
3009 fn push_ty<T>(&mut self, ty: T) -> T::Id
3010 where
3011 T: TypeData,
3012 {
3013 <TypeList>::push(self, ty)
3014 }
3015}
3016
3017impl Remapping {
3018 pub fn add(&mut self, old: ResourceId, new: ResourceId) {
3020 self.resources.insert(old, new);
3021 }
3022
3023 pub fn reset_type_cache(&mut self) {
3025 self.types.clear()
3026 }
3027
3028 fn remap_id<T>(&self, id: &mut T) -> Option<bool>
3029 where
3030 T: Copy + Into<ComponentAnyTypeId> + TryFrom<ComponentAnyTypeId>,
3031 T::Error: core::fmt::Debug,
3032 {
3033 let old: ComponentAnyTypeId = (*id).into();
3034 let new = self.types.get(&old)?;
3035 if *new == old {
3036 Some(false)
3037 } else {
3038 *id = T::try_from(*new).expect("should never remap across different kinds");
3039 Some(true)
3040 }
3041 }
3042}
3043
3044pub struct SubtypeCx<'a> {
3063 pub a: SubtypeArena<'a>,
3065 pub b: SubtypeArena<'a>,
3067}
3068
3069macro_rules! limits_match {
3070 ($a:expr, $b:expr) => {{
3071 let a = $a;
3072 let b = $b;
3073 a.initial >= b.initial
3074 && match b.maximum {
3075 Some(b_max) => match a.maximum {
3076 Some(a_max) => a_max <= b_max,
3077 None => false,
3078 },
3079 None => true,
3080 }
3081 }};
3082}
3083
3084impl<'a> SubtypeCx<'a> {
3085 pub fn new_with_refs(a: TypesRef<'a>, b: TypesRef<'a>) -> SubtypeCx<'a> {
3092 assert_eq!(a.id(), b.id());
3093 Self::new(a.list, b.list)
3094 }
3095
3096 pub(crate) fn new(a: &'a TypeList, b: &'a TypeList) -> SubtypeCx<'a> {
3097 SubtypeCx {
3098 a: SubtypeArena::new(a),
3099 b: SubtypeArena::new(b),
3100 }
3101 }
3102
3103 pub fn swap(&mut self) {
3105 mem::swap(&mut self.a, &mut self.b);
3106 }
3107
3108 fn with_checkpoint<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
3114 let a = self.a.list.checkpoint();
3115 let b = self.b.list.checkpoint();
3116 let result = f(self);
3117 self.a.list.reset_to_checkpoint(a);
3118 self.b.list.reset_to_checkpoint(b);
3119 result
3120 }
3121
3122 pub fn component_entity_type(
3126 &mut self,
3127 a: &ComponentEntityType,
3128 b: &ComponentEntityType,
3129 offset: usize,
3130 ) -> Result<()> {
3131 use ComponentEntityType::*;
3132
3133 match (a, b) {
3134 (Module(a), Module(b)) => self.module_type(*a, *b, offset),
3135 (Module(_), b) => bail!(offset, "expected {}, found module", b.desc()),
3136
3137 (Func(a), Func(b)) => self.component_func_type(*a, *b, offset),
3138 (Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3139
3140 (Value(a), Value(b)) => self.component_val_type(a, b, offset),
3141 (Value(_), b) => bail!(offset, "expected {}, found value", b.desc()),
3142
3143 (Type { referenced: a, .. }, Type { referenced: b, .. }) => {
3144 self.component_any_type_id(*a, *b, offset)
3145 }
3146 (Type { .. }, b) => bail!(offset, "expected {}, found type", b.desc()),
3147
3148 (Instance(a), Instance(b)) => self.component_instance_type(*a, *b, offset),
3149 (Instance(_), b) => bail!(offset, "expected {}, found instance", b.desc()),
3150
3151 (Component(a), Component(b)) => self.component_type(*a, *b, offset),
3152 (Component(_), b) => bail!(offset, "expected {}, found component", b.desc()),
3153 }
3154 }
3155
3156 pub fn component_type(
3160 &mut self,
3161 a: ComponentTypeId,
3162 b: ComponentTypeId,
3163 offset: usize,
3164 ) -> Result<()> {
3165 let b_imports = self.b[b]
3219 .imports
3220 .iter()
3221 .map(|(name, ty)| (name.clone(), ty.ty))
3222 .collect();
3223 self.swap();
3224 let mut import_mapping =
3225 self.open_instance_type(&b_imports, a, ExternKind::Import, offset)?;
3226 self.swap();
3227 self.with_checkpoint(|this| {
3228 let mut a_exports = this.a[a]
3229 .exports
3230 .iter()
3231 .map(|(name, ty)| (name.clone(), ty.ty))
3232 .collect::<IndexMap<_, _>>();
3233 for ty in a_exports.values_mut() {
3234 this.a.remap_component_entity(ty, &mut import_mapping);
3235 }
3236 this.open_instance_type(&a_exports, b, ExternKind::Export, offset)?;
3237 Ok(())
3238 })
3239 }
3240
3241 pub fn component_instance_type(
3245 &mut self,
3246 a_id: ComponentInstanceTypeId,
3247 b_id: ComponentInstanceTypeId,
3248 offset: usize,
3249 ) -> Result<()> {
3250 let a = &self.a[a_id];
3255 let b = &self.b[b_id];
3256
3257 let mut exports = Vec::with_capacity(b.exports.len());
3258 for (k, b) in b.exports.iter() {
3259 match a.exports.get(k) {
3260 Some(a) => exports.push((a.ty, b.ty)),
3261 None => bail!(offset, "missing expected export `{k}`"),
3262 }
3263 }
3264 for (i, (a, b)) in exports.iter().enumerate() {
3265 let err = match self.component_entity_type(a, b, offset) {
3266 Ok(()) => continue,
3267 Err(e) => e,
3268 };
3269 let (name, _) = self.b[b_id].exports.get_index(i).unwrap();
3272 return Err(err.with_context(|| format!("type mismatch in instance export `{name}`")));
3273 }
3274 Ok(())
3275 }
3276
3277 pub fn component_func_type(
3281 &mut self,
3282 a: ComponentFuncTypeId,
3283 b: ComponentFuncTypeId,
3284 offset: usize,
3285 ) -> Result<()> {
3286 let a = &self.a[a];
3287 let b = &self.b[b];
3288
3289 if a.async_ != b.async_ {
3290 let a_desc = if a.async_ { "async" } else { "sync" };
3291 let b_desc = if b.async_ { "async" } else { "sync" };
3292 bail!(
3293 offset,
3294 "expected {a_desc} function, found {b_desc} function",
3295 );
3296 }
3297
3298 if a.params.len() != b.params.len() {
3329 bail!(
3330 offset,
3331 "expected {} parameters, found {}",
3332 b.params.len(),
3333 a.params.len(),
3334 );
3335 }
3336 for ((an, a), (bn, b)) in a.params.iter().zip(b.params.iter()) {
3337 if an != bn {
3338 bail!(offset, "expected parameter named `{bn}`, found `{an}`");
3339 }
3340 self.component_val_type(a, b, offset)
3341 .with_context(|| format!("type mismatch in function parameter `{an}`"))?;
3342 }
3343
3344 match (&a.result, &b.result) {
3345 (Some(a), Some(b)) => self
3346 .component_val_type(a, b, offset)
3347 .with_context(|| "type mismatch with result type")?,
3348 (None, None) => {}
3349
3350 (Some(_), None) => bail!(offset, "expected a result, found none"),
3351 (None, Some(_)) => bail!(offset, "expected no result, found one"),
3352 }
3353 Ok(())
3354 }
3355
3356 pub fn module_type(
3360 &mut self,
3361 a: ComponentCoreModuleTypeId,
3362 b: ComponentCoreModuleTypeId,
3363 offset: usize,
3364 ) -> Result<()> {
3365 self.swap();
3371 let a_imports = &self.b[a].imports;
3372 let b_imports = &self.a[b].imports;
3373 for (k, a) in a_imports {
3374 match b_imports.get(k) {
3375 Some(b) => self
3376 .entity_type(b, a, offset)
3377 .with_context(|| format!("type mismatch in import `{}::{}`", k.0, k.1))?,
3378 None => bail!(offset, "missing expected import `{}::{}`", k.0, k.1),
3379 }
3380 }
3381 self.swap();
3382 let a = &self.a[a];
3383 let b = &self.b[b];
3384 for (k, b) in b.exports.iter() {
3385 match a.exports.get(k) {
3386 Some(a) => self
3387 .entity_type(a, b, offset)
3388 .with_context(|| format!("type mismatch in export `{k}`"))?,
3389 None => bail!(offset, "missing expected export `{k}`"),
3390 }
3391 }
3392 Ok(())
3393 }
3394
3395 pub fn component_any_type_id(
3399 &mut self,
3400 a: ComponentAnyTypeId,
3401 b: ComponentAnyTypeId,
3402 offset: usize,
3403 ) -> Result<()> {
3404 match (a, b) {
3405 (ComponentAnyTypeId::Resource(a), ComponentAnyTypeId::Resource(b)) => {
3406 if a.resource() == b.resource() {
3407 Ok(())
3408 } else {
3409 bail!(
3410 offset,
3411 "resource types are not the same ({:?} vs. {:?})",
3412 a.resource(),
3413 b.resource()
3414 )
3415 }
3416 }
3417 (ComponentAnyTypeId::Resource(_), b) => {
3418 bail!(offset, "expected {}, found resource", b.desc())
3419 }
3420 (ComponentAnyTypeId::Defined(a), ComponentAnyTypeId::Defined(b)) => {
3421 self.component_defined_type(a, b, offset)
3422 }
3423 (ComponentAnyTypeId::Defined(_), b) => {
3424 bail!(offset, "expected {}, found defined type", b.desc())
3425 }
3426
3427 (ComponentAnyTypeId::Func(a), ComponentAnyTypeId::Func(b)) => {
3428 self.component_func_type(a, b, offset)
3429 }
3430 (ComponentAnyTypeId::Func(_), b) => {
3431 bail!(offset, "expected {}, found func type", b.desc())
3432 }
3433
3434 (ComponentAnyTypeId::Instance(a), ComponentAnyTypeId::Instance(b)) => {
3435 self.component_instance_type(a, b, offset)
3436 }
3437 (ComponentAnyTypeId::Instance(_), b) => {
3438 bail!(offset, "expected {}, found instance type", b.desc())
3439 }
3440
3441 (ComponentAnyTypeId::Component(a), ComponentAnyTypeId::Component(b)) => {
3442 self.component_type(a, b, offset)
3443 }
3444 (ComponentAnyTypeId::Component(_), b) => {
3445 bail!(offset, "expected {}, found component type", b.desc())
3446 }
3447 }
3448 }
3449
3450 pub fn open_instance_type(
3474 &mut self,
3475 a: &IndexMap<String, ComponentEntityType>,
3476 b: ComponentTypeId,
3477 kind: ExternKind,
3478 offset: usize,
3479 ) -> Result<Remapping> {
3480 let component_type = &self.b[b];
3510 let entities = match kind {
3511 ExternKind::Import => &component_type.imports,
3512 ExternKind::Export => &component_type.exports,
3513 };
3514 let resources = match kind {
3515 ExternKind::Import => &component_type.imported_resources,
3516 ExternKind::Export => &component_type.defined_resources,
3517 };
3518 let mut mapping = Remapping::default();
3519 'outer: for (resource, path) in resources.iter() {
3520 let (name, ty) = entities.get_index(path[0]).unwrap();
3523 let mut ty = ty.ty;
3524 let mut arg = a.get(name);
3525
3526 for i in path.iter().skip(1).copied() {
3530 let id = match ty {
3531 ComponentEntityType::Instance(id) => id,
3532 _ => unreachable!(),
3533 };
3534 let (name, next_ty) = self.b[id].exports.get_index(i).unwrap();
3535 ty = next_ty.ty;
3536 arg = match arg {
3537 Some(ComponentEntityType::Instance(id)) => {
3538 self.a[*id].exports.get(name).map(|t| &t.ty)
3539 }
3540 _ => continue 'outer,
3541 };
3542 }
3543
3544 if cfg!(debug_assertions) {
3547 let id = match ty {
3548 ComponentEntityType::Type { created, .. } => match created {
3549 ComponentAnyTypeId::Resource(id) => id.resource(),
3550 _ => unreachable!(),
3551 },
3552 _ => unreachable!(),
3553 };
3554 assert_eq!(id, *resource);
3555 }
3556
3557 if let Some(ComponentEntityType::Type { created, .. }) = arg {
3561 if let ComponentAnyTypeId::Resource(r) = created {
3562 mapping.resources.insert(*resource, r.resource());
3563 }
3564 }
3565 }
3566
3567 let mut to_typecheck = Vec::new();
3579 for (name, expected) in entities.iter() {
3580 match a.get(name) {
3581 Some(arg) => to_typecheck.push((*arg, expected.ty)),
3582 None => bail!(offset, "missing {} named `{name}`", kind.desc()),
3583 }
3584 }
3585 let mut type_map = Map::default();
3586 for (i, (actual, expected)) in to_typecheck.into_iter().enumerate() {
3587 let result = self.with_checkpoint(|this| {
3588 let mut expected = expected;
3589 this.b.remap_component_entity(&mut expected, &mut mapping);
3590 mapping.types.clear();
3591 this.component_entity_type(&actual, &expected, offset)
3592 });
3593 let err = match result {
3594 Ok(()) => {
3595 self.register_type_renamings(actual, expected, &mut type_map);
3601 continue;
3602 }
3603 Err(e) => e,
3604 };
3605
3606 let component_type = &self.b[b];
3609 let entities = match kind {
3610 ExternKind::Import => &component_type.imports,
3611 ExternKind::Export => &component_type.exports,
3612 };
3613 let (name, _) = entities.get_index(i).unwrap();
3614 return Err(err.with_context(|| format!("type mismatch for {} `{name}`", kind.desc())));
3615 }
3616 mapping.types = type_map;
3617 Ok(mapping)
3618 }
3619
3620 pub(crate) fn entity_type(&self, a: &EntityType, b: &EntityType, offset: usize) -> Result<()> {
3621 match (a, b) {
3622 (EntityType::Func(a), EntityType::Func(b))
3623 | (EntityType::FuncExact(a), EntityType::Func(b)) => {
3624 self.core_func_type(*a, *b, offset)
3625 }
3626 (EntityType::Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3627 (EntityType::FuncExact(a), EntityType::FuncExact(b)) => {
3628 self.core_func_type(*b, *a, offset)?;
3629 self.core_func_type(*a, *b, offset)
3630 }
3631 (EntityType::FuncExact(_), b) => {
3632 bail!(offset, "expected {}, found func_exact", b.desc())
3633 }
3634 (EntityType::Table(a), EntityType::Table(b)) => Self::table_type(a, b, offset),
3635 (EntityType::Table(_), b) => bail!(offset, "expected {}, found table", b.desc()),
3636 (EntityType::Memory(a), EntityType::Memory(b)) => Self::memory_type(a, b, offset),
3637 (EntityType::Memory(_), b) => bail!(offset, "expected {}, found memory", b.desc()),
3638 (EntityType::Global(a), EntityType::Global(b)) => {
3639 if a.mutable != b.mutable {
3640 bail!(offset, "global types differ in mutability")
3641 }
3642 if a.content_type == b.content_type {
3643 Ok(())
3644 } else {
3645 bail!(
3646 offset,
3647 "expected global type {}, found {}",
3648 b.content_type,
3649 a.content_type,
3650 )
3651 }
3652 }
3653 (EntityType::Global(_), b) => bail!(offset, "expected {}, found global", b.desc()),
3654 (EntityType::Tag(a), EntityType::Tag(b)) => self.core_func_type(*a, *b, offset),
3655 (EntityType::Tag(_), b) => bail!(offset, "expected {}, found tag", b.desc()),
3656 }
3657 }
3658
3659 pub(crate) fn table_type(a: &TableType, b: &TableType, offset: usize) -> Result<()> {
3660 if a.element_type != b.element_type {
3661 bail!(
3662 offset,
3663 "expected table element type {}, found {}",
3664 b.element_type,
3665 a.element_type,
3666 )
3667 }
3668 if a.shared != b.shared {
3669 bail!(offset, "mismatch in the shared flag for tables")
3670 }
3671 if limits_match!(a, b) {
3672 Ok(())
3673 } else {
3674 bail!(offset, "mismatch in table limits")
3675 }
3676 }
3677
3678 pub(crate) fn memory_type(a: &MemoryType, b: &MemoryType, offset: usize) -> Result<()> {
3679 if a.shared != b.shared {
3680 bail!(offset, "mismatch in the shared flag for memories")
3681 }
3682 if a.memory64 != b.memory64 {
3683 bail!(offset, "mismatch in index type used for memories")
3684 }
3685 if a.page_size_log2() != b.page_size_log2() {
3686 bail!(offset, "mismatch in page size for memories")
3687 }
3688 if limits_match!(a, b) {
3689 Ok(())
3690 } else {
3691 bail!(offset, "mismatch in memory limits")
3692 }
3693 }
3694
3695 fn core_func_type(&self, a: CoreTypeId, b: CoreTypeId, offset: usize) -> Result<()> {
3696 debug_assert!(self.a.get(a).is_some());
3697 debug_assert!(self.b.get(b).is_some());
3698 if self.a.id_is_subtype(a, b) {
3699 debug_assert!(self.a.get(b).is_some());
3700 debug_assert!(self.b.get(a).is_some());
3701 Ok(())
3702 } else {
3703 bail!(
3704 offset,
3705 "expected: {}\n\
3706 found: {}",
3707 self.b[b],
3708 self.a[a],
3709 )
3710 }
3711 }
3712
3713 pub(crate) fn component_val_type(
3714 &self,
3715 a: &ComponentValType,
3716 b: &ComponentValType,
3717 offset: usize,
3718 ) -> Result<()> {
3719 match (a, b) {
3720 (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
3721 self.primitive_val_type(*a, *b, offset)
3722 }
3723 (ComponentValType::Type(a), ComponentValType::Type(b)) => {
3724 self.component_defined_type(*a, *b, offset)
3725 }
3726 (ComponentValType::Primitive(a), ComponentValType::Type(b)) => match &self.b[*b] {
3727 ComponentDefinedType::Primitive(b) => self.primitive_val_type(*a, *b, offset),
3728 b => bail!(offset, "expected {}, found {a}", b.desc()),
3729 },
3730 (ComponentValType::Type(a), ComponentValType::Primitive(b)) => match &self.a[*a] {
3731 ComponentDefinedType::Primitive(a) => self.primitive_val_type(*a, *b, offset),
3732 a => bail!(offset, "expected {b}, found {}", a.desc()),
3733 },
3734 }
3735 }
3736
3737 fn component_defined_type(
3738 &self,
3739 a: ComponentDefinedTypeId,
3740 b: ComponentDefinedTypeId,
3741 offset: usize,
3742 ) -> Result<()> {
3743 use ComponentDefinedType::*;
3744
3745 match (&self.a[a], &self.b[b]) {
3749 (Primitive(a), Primitive(b)) => self.primitive_val_type(*a, *b, offset),
3750 (Primitive(a), b) => bail!(offset, "expected {}, found {a}", b.desc()),
3751 (Record(a), Record(b)) => {
3752 if a.fields.len() != b.fields.len() {
3753 bail!(
3754 offset,
3755 "expected {} fields, found {}",
3756 b.fields.len(),
3757 a.fields.len(),
3758 );
3759 }
3760
3761 for ((aname, a), (bname, b)) in a.fields.iter().zip(b.fields.iter()) {
3762 if aname != bname {
3763 bail!(offset, "expected field name `{bname}`, found `{aname}`");
3764 }
3765 self.component_val_type(a, b, offset)
3766 .with_context(|| format!("type mismatch in record field `{aname}`"))?;
3767 }
3768 Ok(())
3769 }
3770 (Record(_), b) => bail!(offset, "expected {}, found record", b.desc()),
3771 (Variant(a), Variant(b)) => {
3772 if a.cases.len() != b.cases.len() {
3773 bail!(
3774 offset,
3775 "expected {} cases, found {}",
3776 b.cases.len(),
3777 a.cases.len(),
3778 );
3779 }
3780 for ((aname, a), (bname, b)) in a.cases.iter().zip(b.cases.iter()) {
3781 if aname != bname {
3782 bail!(offset, "expected case named `{bname}`, found `{aname}`");
3783 }
3784 match (&a.ty, &b.ty) {
3785 (Some(a), Some(b)) => self
3786 .component_val_type(a, b, offset)
3787 .with_context(|| format!("type mismatch in variant case `{aname}`"))?,
3788 (None, None) => {}
3789 (None, Some(_)) => {
3790 bail!(offset, "expected case `{aname}` to have a type, found none")
3791 }
3792 (Some(_), None) => bail!(offset, "expected case `{aname}` to have no type"),
3793 }
3794 }
3795 Ok(())
3796 }
3797 (Variant(_), b) => bail!(offset, "expected {}, found variant", b.desc()),
3798 (List(a), List(b)) | (Option(a), Option(b)) => self.component_val_type(a, b, offset),
3799 (List(_), b) => bail!(offset, "expected {}, found list", b.desc()),
3800 (Map(ak, av), Map(bk, bv)) => {
3801 self.component_val_type(ak, bk, offset)
3802 .with_context(|| "type mismatch in map key")?;
3803 self.component_val_type(av, bv, offset)
3804 .with_context(|| "type mismatch in map value")
3805 }
3806 (Map(_, _), b) => bail!(offset, "expected {}, found map", b.desc()),
3807 (FixedLengthList(a, asize), FixedLengthList(b, bsize)) => {
3808 if asize != bsize {
3809 bail!(offset, "expected fixed-length {bsize}, found size {asize}")
3810 } else {
3811 self.component_val_type(a, b, offset)
3812 }
3813 }
3814 (FixedLengthList(_, _), b) => bail!(offset, "expected {}, found list", b.desc()),
3815 (Option(_), b) => bail!(offset, "expected {}, found option", b.desc()),
3816 (Tuple(a), Tuple(b)) => {
3817 if a.types.len() != b.types.len() {
3818 bail!(
3819 offset,
3820 "expected {} types, found {}",
3821 b.types.len(),
3822 a.types.len(),
3823 );
3824 }
3825 for (i, (a, b)) in a.types.iter().zip(b.types.iter()).enumerate() {
3826 self.component_val_type(a, b, offset)
3827 .with_context(|| format!("type mismatch in tuple field {i}"))?;
3828 }
3829 Ok(())
3830 }
3831 (Tuple(_), b) => bail!(offset, "expected {}, found tuple", b.desc()),
3832 (at @ Flags(a), Flags(b)) | (at @ Enum(a), Enum(b)) => {
3833 let desc = match at {
3834 Flags(_) => "flags",
3835 _ => "enum",
3836 };
3837 if a.len() == b.len() && a.iter().eq(b.iter()) {
3838 Ok(())
3839 } else {
3840 bail!(offset, "mismatch in {desc} elements")
3841 }
3842 }
3843 (Flags(_), b) => bail!(offset, "expected {}, found flags", b.desc()),
3844 (Enum(_), b) => bail!(offset, "expected {}, found enum", b.desc()),
3845 (Result { ok: ao, err: ae }, Result { ok: bo, err: be }) => {
3846 match (ao, bo) {
3847 (None, None) => {}
3848 (Some(a), Some(b)) => self
3849 .component_val_type(a, b, offset)
3850 .with_context(|| "type mismatch in ok variant")?,
3851 (None, Some(_)) => bail!(offset, "expected ok type, but found none"),
3852 (Some(_), None) => bail!(offset, "expected ok type to not be present"),
3853 }
3854 match (ae, be) {
3855 (None, None) => {}
3856 (Some(a), Some(b)) => self
3857 .component_val_type(a, b, offset)
3858 .with_context(|| "type mismatch in err variant")?,
3859 (None, Some(_)) => bail!(offset, "expected err type, but found none"),
3860 (Some(_), None) => bail!(offset, "expected err type to not be present"),
3861 }
3862 Ok(())
3863 }
3864 (Result { .. }, b) => bail!(offset, "expected {}, found result", b.desc()),
3865 (Own(a), Own(b)) | (Borrow(a), Borrow(b)) => {
3866 if a.resource() == b.resource() {
3867 Ok(())
3868 } else {
3869 bail!(offset, "resource types are not the same")
3870 }
3871 }
3872 (Own(_), b) => bail!(offset, "expected {}, found own", b.desc()),
3873 (Borrow(_), b) => bail!(offset, "expected {}, found borrow", b.desc()),
3874 (Future(a), Future(b)) => match (a, b) {
3875 (None, None) => Ok(()),
3876 (Some(a), Some(b)) => self
3877 .component_val_type(a, b, offset)
3878 .with_context(|| "type mismatch in future"),
3879 (None, Some(_)) => bail!(offset, "expected future type, but found none"),
3880 (Some(_), None) => bail!(offset, "expected future type to not be present"),
3881 },
3882 (Future(_), b) => bail!(offset, "expected {}, found future", b.desc()),
3883 (Stream(a), Stream(b)) => match (a, b) {
3884 (None, None) => Ok(()),
3885 (Some(a), Some(b)) => self
3886 .component_val_type(a, b, offset)
3887 .with_context(|| "type mismatch in stream"),
3888 (None, Some(_)) => bail!(offset, "expected stream type, but found none"),
3889 (Some(_), None) => bail!(offset, "expected stream type to not be present"),
3890 },
3891 (Stream(_), b) => bail!(offset, "expected {}, found stream", b.desc()),
3892 }
3893 }
3894
3895 fn primitive_val_type(
3896 &self,
3897 a: PrimitiveValType,
3898 b: PrimitiveValType,
3899 offset: usize,
3900 ) -> Result<()> {
3901 if a == b {
3908 Ok(())
3909 } else {
3910 bail!(offset, "expected primitive `{b}` found primitive `{a}`")
3911 }
3912 }
3913
3914 fn register_type_renamings(
3915 &self,
3916 actual: ComponentEntityType,
3917 expected: ComponentEntityType,
3918 type_map: &mut Map<ComponentAnyTypeId, ComponentAnyTypeId>,
3919 ) {
3920 match (expected, actual) {
3921 (
3922 ComponentEntityType::Type {
3923 created: expected, ..
3924 },
3925 ComponentEntityType::Type {
3926 created: actual, ..
3927 },
3928 ) => {
3929 let prev = type_map.insert(expected, actual);
3930 assert!(prev.is_none());
3931 }
3932 (ComponentEntityType::Instance(expected), ComponentEntityType::Instance(actual)) => {
3933 let actual = &self.a[actual];
3934 for (name, expected) in self.b[expected].exports.iter() {
3935 let actual = actual.exports[name].ty;
3936 self.register_type_renamings(actual, expected.ty, type_map);
3937 }
3938 }
3939 _ => {}
3940 }
3941 }
3942}
3943
3944pub struct SubtypeArena<'a> {
3954 types: &'a TypeList,
3955 list: TypeList,
3956}
3957
3958impl<'a> SubtypeArena<'a> {
3959 fn new(types: &'a TypeList) -> SubtypeArena<'a> {
3960 SubtypeArena {
3961 types,
3962 list: TypeList::default(),
3963 }
3964 }
3965
3966 fn get<T>(&self, id: T) -> Option<&T::Data>
3967 where
3968 T: TypeIdentifier,
3969 {
3970 let index = id.index();
3971 if index < T::list(self.types).len() {
3972 self.types.get(id)
3973 } else {
3974 let temp_index = index - T::list(self.types).len();
3975 let temp_index = u32::try_from(temp_index).unwrap();
3976 let temp_id = T::from_index(temp_index);
3977 self.list.get(temp_id)
3978 }
3979 }
3980
3981 fn id_is_subtype(&self, a: CoreTypeId, b: CoreTypeId) -> bool {
3984 self.get(a).is_some() && self.get(b).is_some() && {
3985 debug_assert!(a.index() < CoreTypeId::list(self.types).len());
3988 debug_assert!(b.index() < CoreTypeId::list(self.types).len());
3989 self.types.id_is_subtype(a, b)
3990 }
3991 }
3992}
3993
3994impl<T> Index<T> for SubtypeArena<'_>
3995where
3996 T: TypeIdentifier,
3997{
3998 type Output = T::Data;
3999
4000 fn index(&self, id: T) -> &T::Data {
4001 self.get(id).unwrap()
4002 }
4003}
4004
4005impl Remap for SubtypeArena<'_> {
4006 fn push_ty<T>(&mut self, ty: T) -> T::Id
4007 where
4008 T: TypeData,
4009 {
4010 assert!(
4011 !T::IS_CORE_SUB_TYPE,
4012 "cannot push core sub types into `SubtypeArena`s, that would break type canonicalization"
4013 );
4014 let index = T::Id::list(&self.list).len() + T::Id::list(self.types).len();
4015 let index = u32::try_from(index).unwrap();
4016 self.list.push(ty);
4017 T::Id::from_index(index)
4018 }
4019}
4020
4021pub(crate) trait Context {
4024 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
4025 where
4026 S: Into<String>;
4027}
4028
4029impl<T> Context for Result<T> {
4030 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
4031 where
4032 S: Into<String>,
4033 {
4034 match self {
4035 Ok(val) => Ok(val),
4036 Err(e) => Err(e.with_context(context)),
4037 }
4038 }
4039}
4040
4041impl Context for BinaryReaderError {
4042 fn with_context<S>(mut self, context: impl FnOnce() -> S) -> Self
4043 where
4044 S: Into<String>,
4045 {
4046 self.add_context(context().into());
4047 self
4048 }
4049}