1//! Types relating to type information provided by validation.
2
3use super::component::ExternKind;
4use crate::prelude::*;
5use crate::validator::names::KebabString;
6use crate::validator::types::{
7 CoreTypeId, EntityType, SnapshotList, TypeAlloc, TypeData, TypeIdentifier, TypeInfo, TypeList,
8 Types, TypesKind, TypesRef, TypesRefKind,
9};
10use crate::{BinaryReaderError, FuncType, PrimitiveValType, Result, ValType};
11use core::ops::Index;
12use core::sync::atomic::{AtomicUsize, Ordering};
13use core::{
14 borrow::Borrow,
15 hash::{Hash, Hasher},
16 mem,
17};
18
19/// The maximum number of parameters in the canonical ABI that can be passed by value.
20///
21/// Functions that exceed this limit will instead pass parameters indirectly from
22/// linear memory via a single pointer parameter.
23const MAX_FLAT_FUNC_PARAMS: usize = 16;
24/// The maximum number of results in the canonical ABI that can be returned by a function.
25///
26/// Functions that exceed this limit have their results written to linear memory via an
27/// additional pointer parameter (imports) or return a single pointer value (exports).
28const MAX_FLAT_FUNC_RESULTS: usize = 1;
29
30/// The maximum lowered types, including a possible type for a return pointer parameter.
31const MAX_LOWERED_TYPES: usize = MAX_FLAT_FUNC_PARAMS + 1;
32
33/// A simple alloc-free list of types used for calculating lowered function signatures.
34pub(crate) struct LoweredTypes {
35 types: [ValType; MAX_LOWERED_TYPES],
36 len: usize,
37 max: usize,
38}
39
40impl LoweredTypes {
41 fn new(max: usize) -> Self {
42 assert!(max <= MAX_LOWERED_TYPES);
43 Self {
44 types: [ValType::I32; MAX_LOWERED_TYPES],
45 len: 0,
46 max,
47 }
48 }
49
50 fn len(&self) -> usize {
51 self.len
52 }
53
54 fn maxed(&self) -> bool {
55 self.len == self.max
56 }
57
58 fn get_mut(&mut self, index: usize) -> Option<&mut ValType> {
59 if index < self.len {
60 Some(&mut self.types[index])
61 } else {
62 None
63 }
64 }
65
66 fn push(&mut self, ty: ValType) -> bool {
67 if self.maxed() {
68 return false;
69 }
70
71 self.types[self.len] = ty;
72 self.len += 1;
73 true
74 }
75
76 fn clear(&mut self) {
77 self.len = 0;
78 }
79
80 pub fn as_slice(&self) -> &[ValType] {
81 &self.types[..self.len]
82 }
83
84 pub fn iter(&self) -> impl Iterator<Item = ValType> + '_ {
85 self.as_slice().iter().copied()
86 }
87}
88
89/// Represents information about a component function type lowering.
90pub(crate) struct LoweringInfo {
91 pub(crate) params: LoweredTypes,
92 pub(crate) results: LoweredTypes,
93 pub(crate) requires_memory: bool,
94 pub(crate) requires_realloc: bool,
95}
96
97impl LoweringInfo {
98 pub(crate) fn into_func_type(self) -> FuncType {
99 FuncType::new(
100 self.params.as_slice().iter().copied(),
101 self.results.as_slice().iter().copied(),
102 )
103 }
104}
105
106impl Default for LoweringInfo {
107 fn default() -> Self {
108 Self {
109 params: LoweredTypes::new(MAX_FLAT_FUNC_PARAMS),
110 results: LoweredTypes::new(MAX_FLAT_FUNC_RESULTS),
111 requires_memory: false,
112 requires_realloc: false,
113 }
114 }
115}
116
117fn push_primitive_wasm_types(ty: &PrimitiveValType, lowered_types: &mut LoweredTypes) -> bool {
118 match ty {
119 PrimitiveValType::Bool
120 | PrimitiveValType::S8
121 | PrimitiveValType::U8
122 | PrimitiveValType::S16
123 | PrimitiveValType::U16
124 | PrimitiveValType::S32
125 | PrimitiveValType::U32
126 | PrimitiveValType::Char => lowered_types.push(ty:ValType::I32),
127 PrimitiveValType::S64 | PrimitiveValType::U64 => lowered_types.push(ty:ValType::I64),
128 PrimitiveValType::F32 => lowered_types.push(ty:ValType::F32),
129 PrimitiveValType::F64 => lowered_types.push(ty:ValType::F64),
130 PrimitiveValType::String => {
131 lowered_types.push(ty:ValType::I32) && lowered_types.push(ty:ValType::I32)
132 }
133 }
134}
135
136/// A type that can be aliased in the component model.
137pub trait Aliasable {
138 #[doc(hidden)]
139 fn alias_id(&self) -> u32;
140
141 #[doc(hidden)]
142 fn set_alias_id(&mut self, alias_id: u32);
143}
144
145/// A fresh alias id that means the entity is not an alias of anything.
146///
147/// Note that the `TypeList::alias_counter` starts at zero, so we can't use that
148/// as this sentinel. The implementation limits are such that we can't ever
149/// generate `u32::MAX` aliases, so we don't need to worryabout running into
150/// this value in practice either.
151const NO_ALIAS: u32 = u32::MAX;
152
153macro_rules! define_wrapper_id {
154 (
155 $(#[$outer_attrs:meta])*
156 pub enum $name:ident {
157 $(
158 #[unwrap = $unwrap:ident]
159 $(#[$inner_attrs:meta])*
160 $variant:ident ( $inner:ty ) ,
161 )*
162 }
163 ) => {
164 $(#[$outer_attrs])*
165 pub enum $name {
166 $(
167 $(#[$inner_attrs])*
168 $variant ( $inner ) ,
169 )*
170 }
171
172 $(
173 impl From<$inner> for $name {
174 #[inline]
175 fn from(x: $inner) -> Self {
176 Self::$variant(x)
177 }
178 }
179
180 impl TryFrom<$name> for $inner {
181 type Error = ();
182
183 #[inline]
184 fn try_from(x: $name) -> Result<Self, Self::Error> {
185 match x {
186 $name::$variant(x) => Ok(x),
187 _ => Err(())
188 }
189 }
190 }
191 )*
192
193 impl $name {
194 $(
195 #[doc = "Unwrap a `"]
196 #[doc = stringify!($inner)]
197 #[doc = "` or panic."]
198 #[inline]
199 pub fn $unwrap(self) -> $inner {
200 <$inner>::try_from(self).unwrap()
201 }
202 )*
203 }
204 };
205}
206
207macro_rules! define_transitive_conversions {
208 (
209 $(
210 $outer:ty,
211 $middle:ty,
212 $inner:ty,
213 $unwrap:ident;
214 )*
215 ) => {
216 $(
217 impl From<$inner> for $outer {
218 #[inline]
219 fn from(x: $inner) -> Self {
220 <$middle>::from(x).into()
221 }
222 }
223
224 impl TryFrom<$outer> for $inner {
225 type Error = ();
226
227 #[inline]
228 fn try_from(x: $outer) -> Result<Self, Self::Error> {
229 let middle = <$middle>::try_from(x)?;
230 <$inner>::try_from(middle)
231 }
232 }
233
234 impl $outer {
235 #[doc = "Unwrap a `"]
236 #[doc = stringify!($inner)]
237 #[doc = "` or panic."]
238 #[inline]
239 pub fn $unwrap(self) -> $inner {
240 <$inner>::try_from(self).unwrap()
241 }
242 }
243 )*
244 };
245}
246
247define_wrapper_id! {
248 /// An identifier pointing to any kind of type, component or core.
249 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
250 pub enum AnyTypeId {
251 #[unwrap = unwrap_component_core_type]
252 /// A core type.
253 Core(ComponentCoreTypeId),
254
255 #[unwrap = unwrap_component_any_type]
256 /// A component type.
257 Component(ComponentAnyTypeId),
258 }
259}
260
261define_transitive_conversions! {
262 AnyTypeId, ComponentCoreTypeId, CoreTypeId, unwrap_core_type;
263 AnyTypeId, ComponentCoreTypeId, ComponentCoreModuleTypeId, unwrap_component_core_module_type;
264 AnyTypeId, ComponentAnyTypeId, AliasableResourceId, unwrap_aliasable_resource;
265 AnyTypeId, ComponentAnyTypeId, ComponentDefinedTypeId, unwrap_component_defined_type;
266 AnyTypeId, ComponentAnyTypeId, ComponentFuncTypeId, unwrap_component_func_type;
267 AnyTypeId, ComponentAnyTypeId, ComponentInstanceTypeId, unwrap_component_instance_type;
268 AnyTypeId, ComponentAnyTypeId, ComponentTypeId, unwrap_component_type;
269}
270
271impl AnyTypeId {
272 /// Peel off one layer of aliasing from this type and return the aliased
273 /// inner type, or `None` if this type is not aliasing anything.
274 pub fn peel_alias(&self, types: &Types) -> Option<Self> {
275 match *self {
276 Self::Core(id: ComponentCoreTypeId) => id.peel_alias(types).map(Self::Core),
277 Self::Component(id: ComponentAnyTypeId) => types.peel_alias(ty:id).map(Self::Component),
278 }
279 }
280}
281
282define_wrapper_id! {
283 /// An identifier for a core type or a core module's type.
284 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
285 pub enum ComponentCoreTypeId {
286 #[unwrap = unwrap_sub]
287 /// A core type.
288 Sub(CoreTypeId),
289
290 #[unwrap = unwrap_module]
291 /// A core module's type.
292 Module(ComponentCoreModuleTypeId),
293 }
294}
295
296impl ComponentCoreTypeId {
297 /// Peel off one layer of aliasing from this type and return the aliased
298 /// inner type, or `None` if this type is not aliasing anything.
299 pub fn peel_alias(&self, types: &Types) -> Option<Self> {
300 match *self {
301 Self::Sub(_) => None,
302 Self::Module(id: ComponentCoreModuleTypeId) => types.peel_alias(ty:id).map(Self::Module),
303 }
304 }
305}
306
307/// An aliasable resource identifier.
308#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
309pub struct AliasableResourceId {
310 id: ResourceId,
311 alias_id: u32,
312}
313
314impl Aliasable for AliasableResourceId {
315 fn alias_id(&self) -> u32 {
316 self.alias_id
317 }
318
319 fn set_alias_id(&mut self, alias_id: u32) {
320 self.alias_id = alias_id;
321 }
322}
323
324impl AliasableResourceId {
325 /// Create a new instance with the specified resource ID and `self`'s alias
326 /// ID.
327 pub fn with_resource_id(&self, id: ResourceId) -> Self {
328 Self {
329 id,
330 alias_id: self.alias_id,
331 }
332 }
333
334 /// Get the underlying resource.
335 pub fn resource(&self) -> ResourceId {
336 self.id
337 }
338
339 pub(crate) fn resource_mut(&mut self) -> &mut ResourceId {
340 &mut self.id
341 }
342}
343
344define_wrapper_id! {
345 /// An identifier for any kind of component type.
346 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
347 pub enum ComponentAnyTypeId {
348 #[unwrap = unwrap_resource]
349 /// The type is a resource with the specified id.
350 Resource(AliasableResourceId),
351
352 #[unwrap = unwrap_defined]
353 /// The type is a defined type with the specified id.
354 Defined(ComponentDefinedTypeId),
355
356 #[unwrap = unwrap_func]
357 /// The type is a function type with the specified id.
358 Func(ComponentFuncTypeId),
359
360 #[unwrap = unwrap_instance]
361 /// The type is an instance type with the specified id.
362 Instance(ComponentInstanceTypeId),
363
364 #[unwrap = unwrap_component]
365 /// The type is a component type with the specified id.
366 Component(ComponentTypeId),
367 }
368}
369
370impl Aliasable for ComponentAnyTypeId {
371 fn alias_id(&self) -> u32 {
372 match self {
373 ComponentAnyTypeId::Resource(x: &AliasableResourceId) => x.alias_id(),
374 ComponentAnyTypeId::Defined(x: &ComponentDefinedTypeId) => x.alias_id(),
375 ComponentAnyTypeId::Func(x: &ComponentFuncTypeId) => x.alias_id(),
376 ComponentAnyTypeId::Instance(x: &ComponentInstanceTypeId) => x.alias_id(),
377 ComponentAnyTypeId::Component(x: &ComponentTypeId) => x.alias_id(),
378 }
379 }
380
381 fn set_alias_id(&mut self, alias_id: u32) {
382 match self {
383 ComponentAnyTypeId::Resource(x: &mut AliasableResourceId) => x.set_alias_id(alias_id),
384 ComponentAnyTypeId::Defined(x: &mut ComponentDefinedTypeId) => x.set_alias_id(alias_id),
385 ComponentAnyTypeId::Func(x: &mut ComponentFuncTypeId) => x.set_alias_id(alias_id),
386 ComponentAnyTypeId::Instance(x: &mut ComponentInstanceTypeId) => x.set_alias_id(alias_id),
387 ComponentAnyTypeId::Component(x: &mut ComponentTypeId) => x.set_alias_id(alias_id),
388 }
389 }
390}
391
392impl ComponentAnyTypeId {
393 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
394 match *self {
395 Self::Resource(_) => TypeInfo::new(),
396 Self::Defined(id: ComponentDefinedTypeId) => types[id].type_info(types),
397 Self::Func(id: ComponentFuncTypeId) => types[id].type_info(types),
398 Self::Instance(id: ComponentInstanceTypeId) => types[id].type_info(types),
399 Self::Component(id: ComponentTypeId) => types[id].type_info(types),
400 }
401 }
402
403 pub(crate) fn desc(&self) -> &'static str {
404 match self {
405 Self::Resource(_) => "resource",
406 Self::Defined(_) => "defined type",
407 Self::Func(_) => "func",
408 Self::Instance(_) => "instance",
409 Self::Component(_) => "component",
410 }
411 }
412}
413
414macro_rules! define_type_id {
415 ($name:ident $($rest:tt)*) => {
416 super::types::define_type_id!($name $($rest)*);
417
418 impl Aliasable for $name {
419 fn alias_id(&self) -> u32 {
420 NO_ALIAS
421 }
422
423 fn set_alias_id(&mut self, _: u32) {}
424 }
425 }
426}
427
428define_type_id!(
429 ComponentTypeId,
430 ComponentType,
431 component.components,
432 "component"
433);
434
435define_type_id!(
436 ComponentValueTypeId,
437 ComponentValType,
438 component.component_values,
439 "component value"
440);
441
442define_type_id!(
443 ComponentInstanceTypeId,
444 ComponentInstanceType,
445 component.component_instances,
446 "component instance"
447);
448
449define_type_id!(
450 ComponentFuncTypeId,
451 ComponentFuncType,
452 component.component_funcs,
453 "component function"
454);
455
456define_type_id!(
457 ComponentCoreInstanceTypeId,
458 InstanceType,
459 component.core_instances,
460 "component's core instance"
461);
462
463define_type_id!(
464 ComponentCoreModuleTypeId,
465 ModuleType,
466 component.core_modules,
467 "component's core module"
468);
469
470/// Represents a unique identifier for a component type type known to a
471/// [`crate::Validator`].
472#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
473#[repr(C)]
474pub struct ComponentDefinedTypeId {
475 index: u32,
476 alias_id: u32,
477}
478
479#[test]
480fn assert_defined_type_small() {
481 assert!(core::mem::size_of::<ComponentDefinedTypeId>() <= 8);
482}
483
484impl TypeIdentifier for ComponentDefinedTypeId {
485 type Data = ComponentDefinedType;
486
487 fn from_index(index: u32) -> Self {
488 ComponentDefinedTypeId {
489 index,
490 alias_id: NO_ALIAS,
491 }
492 }
493
494 fn list(types: &TypeList) -> &SnapshotList<Self::Data> {
495 &types.component.component_defined_types
496 }
497
498 fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> {
499 &mut types.component.component_defined_types
500 }
501
502 fn index(&self) -> usize {
503 usize::try_from(self.index).unwrap()
504 }
505}
506
507impl Aliasable for ComponentDefinedTypeId {
508 fn alias_id(&self) -> u32 {
509 self.alias_id
510 }
511
512 fn set_alias_id(&mut self, alias_id: u32) {
513 self.alias_id = alias_id;
514 }
515}
516
517/// A component value type.
518#[derive(Debug, Clone, Copy)]
519pub enum ComponentValType {
520 /// The value type is one of the primitive types.
521 Primitive(PrimitiveValType),
522 /// The type is represented with the given type identifier.
523 Type(ComponentDefinedTypeId),
524}
525
526impl TypeData for ComponentValType {
527 type Id = ComponentValueTypeId;
528
529 fn type_info(&self, types: &TypeList) -> TypeInfo {
530 match self {
531 ComponentValType::Primitive(_) => TypeInfo::new(),
532 ComponentValType::Type(id: &ComponentDefinedTypeId) => types[*id].type_info(types),
533 }
534 }
535}
536
537impl ComponentValType {
538 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
539 match self {
540 ComponentValType::Primitive(ty: &PrimitiveValType) => ty.contains_ptr(),
541 ComponentValType::Type(ty: &ComponentDefinedTypeId) => types[*ty].contains_ptr(types),
542 }
543 }
544
545 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
546 match self {
547 Self::Primitive(ty: &PrimitiveValType) => push_primitive_wasm_types(ty, lowered_types),
548 Self::Type(id: &ComponentDefinedTypeId) => types[*id].push_wasm_types(types, lowered_types),
549 }
550 }
551
552 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
553 match self {
554 Self::Primitive(_) => TypeInfo::new(),
555 Self::Type(id: &ComponentDefinedTypeId) => types[*id].type_info(types),
556 }
557 }
558}
559
560trait ModuleImportKey {
561 fn module(&self) -> &str;
562 fn name(&self) -> &str;
563}
564
565impl<'a> Borrow<dyn ModuleImportKey + 'a> for (String, String) {
566 fn borrow(&self) -> &(dyn ModuleImportKey + 'a) {
567 self
568 }
569}
570
571impl Hash for (dyn ModuleImportKey + '_) {
572 fn hash<H: Hasher>(&self, state: &mut H) {
573 self.module().hash(state);
574 self.name().hash(state);
575 }
576}
577
578impl PartialEq for (dyn ModuleImportKey + '_) {
579 fn eq(&self, other: &Self) -> bool {
580 self.module() == other.module() && self.name() == other.name()
581 }
582}
583
584impl Eq for (dyn ModuleImportKey + '_) {}
585
586impl Ord for (dyn ModuleImportKey + '_) {
587 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
588 match self.module().cmp(other.module()) {
589 core::cmp::Ordering::Equal => (),
590 order: Ordering => return order,
591 };
592 self.name().cmp(other.name())
593 }
594}
595
596impl PartialOrd for (dyn ModuleImportKey + '_) {
597 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
598 Some(self.cmp(other))
599 }
600}
601
602impl ModuleImportKey for (String, String) {
603 fn module(&self) -> &str {
604 &self.0
605 }
606
607 fn name(&self) -> &str {
608 &self.1
609 }
610}
611
612impl ModuleImportKey for (&str, &str) {
613 fn module(&self) -> &str {
614 self.0
615 }
616
617 fn name(&self) -> &str {
618 self.1
619 }
620}
621
622/// Represents a core module type.
623#[derive(Debug, Clone)]
624pub struct ModuleType {
625 /// Metadata about this module type
626 pub(crate) info: TypeInfo,
627 /// The imports of the module type.
628 pub imports: IndexMap<(String, String), EntityType>,
629 /// The exports of the module type.
630 pub exports: IndexMap<String, EntityType>,
631}
632
633impl TypeData for ModuleType {
634 type Id = ComponentCoreModuleTypeId;
635
636 fn type_info(&self, _types: &TypeList) -> TypeInfo {
637 self.info
638 }
639}
640
641impl ModuleType {
642 /// Looks up an import by its module and name.
643 ///
644 /// Returns `None` if the import was not found.
645 pub fn lookup_import(&self, module: &str, name: &str) -> Option<&EntityType> {
646 self.imports.get(&(module, name) as &dyn ModuleImportKey)
647 }
648}
649
650/// Represents the kind of module instance type.
651#[derive(Debug, Clone)]
652pub enum CoreInstanceTypeKind {
653 /// The instance type is the result of instantiating a module type.
654 Instantiated(ComponentCoreModuleTypeId),
655
656 /// The instance type is the result of instantiating from exported items.
657 Exports(IndexMap<String, EntityType>),
658}
659
660/// Represents a module instance type.
661#[derive(Debug, Clone)]
662pub struct InstanceType {
663 /// Metadata about this instance type
664 pub(crate) info: TypeInfo,
665 /// The kind of module instance type.
666 pub kind: CoreInstanceTypeKind,
667}
668
669impl TypeData for InstanceType {
670 type Id = ComponentCoreInstanceTypeId;
671
672 fn type_info(&self, _types: &TypeList) -> TypeInfo {
673 self.info
674 }
675}
676
677impl InstanceType {
678 /// Gets the exports of the instance type.
679 pub fn exports<'a>(&'a self, types: TypesRef<'a>) -> &'a IndexMap<String, EntityType> {
680 self.internal_exports(types.list)
681 }
682
683 pub(crate) fn internal_exports<'a>(
684 &'a self,
685 types: &'a TypeList,
686 ) -> &'a IndexMap<String, EntityType> {
687 match &self.kind {
688 CoreInstanceTypeKind::Instantiated(id: &ComponentCoreModuleTypeId) => &types[*id].exports,
689 CoreInstanceTypeKind::Exports(exports: &IndexMap) => exports,
690 }
691 }
692}
693
694/// The entity type for imports and exports of a component.
695#[derive(Debug, Clone, Copy)]
696pub enum ComponentEntityType {
697 /// The entity is a core module.
698 Module(ComponentCoreModuleTypeId),
699 /// The entity is a function.
700 Func(ComponentFuncTypeId),
701 /// The entity is a value.
702 Value(ComponentValType),
703 /// The entity is a type.
704 Type {
705 /// This is the identifier of the type that was referenced when this
706 /// entity was created.
707 referenced: ComponentAnyTypeId,
708 /// This is the identifier of the type that was created when this type
709 /// was imported or exported from the component.
710 ///
711 /// Note that the underlying type information for the `referenced`
712 /// field and for this `created` field is the same, but these two types
713 /// will hash to different values.
714 created: ComponentAnyTypeId,
715 },
716 /// The entity is a component instance.
717 Instance(ComponentInstanceTypeId),
718 /// The entity is a component.
719 Component(ComponentTypeId),
720}
721
722impl ComponentEntityType {
723 /// Determines if component entity type `a` is a subtype of `b`.
724 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
725 SubtypeCx::new(at.list, bt.list)
726 .component_entity_type(a, b, 0)
727 .is_ok()
728 }
729
730 pub(crate) fn desc(&self) -> &'static str {
731 match self {
732 Self::Module(_) => "module",
733 Self::Func(_) => "func",
734 Self::Value(_) => "value",
735 Self::Type { .. } => "type",
736 Self::Instance(_) => "instance",
737 Self::Component(_) => "component",
738 }
739 }
740
741 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
742 match self {
743 Self::Module(ty) => types[*ty].type_info(types),
744 Self::Func(ty) => types[*ty].type_info(types),
745 Self::Type { referenced: ty, .. } => ty.info(types),
746 Self::Instance(ty) => types[*ty].type_info(types),
747 Self::Component(ty) => types[*ty].type_info(types),
748 Self::Value(ty) => ty.info(types),
749 }
750 }
751}
752
753/// Represents a type of a component.
754#[derive(Debug, Clone)]
755pub struct ComponentType {
756 /// Metadata about this component type
757 pub(crate) info: TypeInfo,
758
759 /// The imports of the component type.
760 ///
761 /// Each import has its own kebab-name and an optional URL listed. Note that
762 /// the set of import names is disjoint with the set of export names.
763 pub imports: IndexMap<String, ComponentEntityType>,
764
765 /// The exports of the component type.
766 ///
767 /// Each export has its own kebab-name and an optional URL listed. Note that
768 /// the set of export names is disjoint with the set of import names.
769 pub exports: IndexMap<String, ComponentEntityType>,
770
771 /// Universally quantified resources required to be provided when
772 /// instantiating this component type.
773 ///
774 /// Each resource in this map is explicitly imported somewhere in the
775 /// `imports` map. The "path" to where it's imported is specified by the
776 /// `Vec<usize>` payload here. For more information about the indexes see
777 /// the documentation on `ComponentState::imported_resources`.
778 ///
779 /// This should technically be inferrable from the structure of `imports`,
780 /// but it's stored as an auxiliary set for subtype checking and
781 /// instantiation.
782 ///
783 /// Note that this is not a set of all resources referred to by the
784 /// `imports`. Instead it's only those created, relative to the internals of
785 /// this component, by the imports.
786 pub imported_resources: Vec<(ResourceId, Vec<usize>)>,
787
788 /// The dual of the `imported_resources`, or the set of defined
789 /// resources -- those created through the instantiation process which are
790 /// unique to this component.
791 ///
792 /// This set is similar to the `imported_resources` set but it's those
793 /// contained within the `exports`. Instantiating this component will
794 /// create fresh new versions of all of these resources. The path here is
795 /// within the `exports` array.
796 pub defined_resources: Vec<(ResourceId, Vec<usize>)>,
797
798 /// The set of all resources which are explicitly exported by this
799 /// component, and where they're exported.
800 ///
801 /// This mapping is stored separately from `defined_resources` to ensure
802 /// that it contains all exported resources, not just those which are
803 /// defined. That means that this can cover reexports of imported
804 /// resources, exports of local resources, or exports of closed-over
805 /// resources for example.
806 pub explicit_resources: IndexMap<ResourceId, Vec<usize>>,
807}
808
809impl TypeData for ComponentType {
810 type Id = ComponentTypeId;
811
812 fn type_info(&self, _types: &TypeList) -> TypeInfo {
813 self.info
814 }
815}
816
817/// Represents a type of a component instance.
818#[derive(Debug, Clone)]
819pub struct ComponentInstanceType {
820 /// Metadata about this instance type
821 pub(crate) info: TypeInfo,
822
823 /// The list of exports, keyed by name, that this instance has.
824 ///
825 /// An optional URL and type of each export is provided as well.
826 pub exports: IndexMap<String, ComponentEntityType>,
827
828 /// The list of "defined resources" or those which are closed over in
829 /// this instance type.
830 ///
831 /// This list is populated, for example, when the type of an instance is
832 /// declared and it contains its own resource type exports defined
833 /// internally. For example:
834 ///
835 /// ```wasm
836 /// (component
837 /// (type (instance
838 /// (export "x" (type sub resource)) ;; one `defined_resources` entry
839 /// ))
840 /// )
841 /// ```
842 ///
843 /// This list is also a bit of an oddity, however, because the type of a
844 /// concrete instance will always have this as empty. For example:
845 ///
846 /// ```wasm
847 /// (component
848 /// (type $t (instance (export "x" (type sub resource))))
849 ///
850 /// ;; the type of this instance has no defined resources
851 /// (import "i" (instance (type $t)))
852 /// )
853 /// ```
854 ///
855 /// This list ends up only being populated for instance types declared in a
856 /// module which aren't yet "attached" to anything. Once something is
857 /// instantiated, imported, exported, or otherwise refers to a concrete
858 /// instance then this list is always empty. For concrete instances
859 /// defined resources are tracked in the component state or component type.
860 pub defined_resources: Vec<ResourceId>,
861
862 /// The list of all resources that are explicitly exported from this
863 /// instance type along with the path they're exported at.
864 pub explicit_resources: IndexMap<ResourceId, Vec<usize>>,
865}
866
867impl TypeData for ComponentInstanceType {
868 type Id = ComponentInstanceTypeId;
869
870 fn type_info(&self, _types: &TypeList) -> TypeInfo {
871 self.info
872 }
873}
874
875/// Represents a type of a component function.
876#[derive(Debug, Clone)]
877pub struct ComponentFuncType {
878 /// Metadata about this function type.
879 pub(crate) info: TypeInfo,
880 /// The function parameters.
881 pub params: Box<[(KebabString, ComponentValType)]>,
882 /// The function's results.
883 pub results: Box<[(Option<KebabString>, ComponentValType)]>,
884}
885
886impl TypeData for ComponentFuncType {
887 type Id = ComponentFuncTypeId;
888
889 fn type_info(&self, _types: &TypeList) -> TypeInfo {
890 self.info
891 }
892}
893
894#[derive(Copy, Clone, Debug)]
895pub(crate) enum Abi {
896 LowerSync,
897 LowerAsync,
898 LiftSync,
899 LiftAsync,
900 LiftAsyncStackful,
901}
902
903impl ComponentFuncType {
904 /// Lowers the component function type to core parameter and result types for the
905 /// canonical ABI.
906 pub(crate) fn lower(&self, types: &TypeList, abi: Abi) -> LoweringInfo {
907 let mut info = LoweringInfo::default();
908
909 let is_lower = match abi {
910 Abi::LowerAsync => {
911 for _ in 0..2 {
912 info.params.push(ValType::I32);
913 }
914 info.results.push(ValType::I32);
915 info.requires_memory = true;
916 info.requires_realloc = self.results.iter().any(|(_, ty)| ty.contains_ptr(types));
917 return info;
918 }
919 Abi::LowerSync => true,
920 Abi::LiftSync | Abi::LiftAsync | Abi::LiftAsyncStackful => false,
921 };
922
923 for (_, ty) in self.params.iter() {
924 // Check to see if `ty` has a pointer somewhere in it, needed for
925 // any type that transitively contains either a string or a list.
926 // In this situation lowered functions must specify `memory`, and
927 // lifted functions must specify `realloc` as well. Lifted functions
928 // gain their memory requirement through the final clause of this
929 // function.
930 if is_lower {
931 if !info.requires_memory {
932 info.requires_memory = ty.contains_ptr(types);
933 }
934 } else {
935 if !info.requires_realloc {
936 info.requires_realloc = ty.contains_ptr(types);
937 }
938 }
939
940 if !ty.push_wasm_types(types, &mut info.params) {
941 // Too many parameters to pass directly
942 // Function will have a single pointer parameter to pass the arguments
943 // via linear memory
944 info.params.clear();
945 assert!(info.params.push(ValType::I32));
946 info.requires_memory = true;
947
948 // We need realloc as well when lifting a function
949 if !is_lower {
950 info.requires_realloc = true;
951 }
952 break;
953 }
954 }
955
956 match abi {
957 Abi::LowerAsync => unreachable!(),
958 Abi::LowerSync | Abi::LiftSync => {
959 for (_, ty) in self.results.iter() {
960 // Results of lowered functions that contains pointers must be
961 // allocated by the callee meaning that realloc is required.
962 // Results of lifted function are allocated by the guest which
963 // means that no realloc option is necessary.
964 if is_lower && !info.requires_realloc {
965 info.requires_realloc = ty.contains_ptr(types);
966 }
967
968 if !ty.push_wasm_types(types, &mut info.results) {
969 // Too many results to return directly, either a retptr parameter will be used (import)
970 // or a single pointer will be returned (export)
971 info.results.clear();
972 if is_lower {
973 info.params.max = MAX_LOWERED_TYPES;
974 assert!(info.params.push(ValType::I32));
975 } else {
976 assert!(info.results.push(ValType::I32));
977 }
978 info.requires_memory = true;
979 break;
980 }
981 }
982 }
983 Abi::LiftAsync => {
984 info.results.push(ValType::I32);
985 }
986 Abi::LiftAsyncStackful => {}
987 }
988
989 // Memory is always required when realloc is required
990 info.requires_memory |= info.requires_realloc;
991
992 info
993 }
994}
995
996/// Represents a variant case.
997#[derive(Debug, Clone)]
998pub struct VariantCase {
999 /// The variant case type.
1000 pub ty: Option<ComponentValType>,
1001 /// The name of the variant case refined by this one.
1002 pub refines: Option<KebabString>,
1003}
1004
1005/// Represents a record type.
1006#[derive(Debug, Clone)]
1007pub struct RecordType {
1008 /// Metadata about this record type.
1009 pub(crate) info: TypeInfo,
1010 /// The map of record fields.
1011 pub fields: IndexMap<KebabString, ComponentValType>,
1012}
1013
1014/// Represents a variant type.
1015#[derive(Debug, Clone)]
1016pub struct VariantType {
1017 /// Metadata about this variant type.
1018 pub(crate) info: TypeInfo,
1019 /// The map of variant cases.
1020 pub cases: IndexMap<KebabString, VariantCase>,
1021}
1022
1023/// Represents a tuple type.
1024#[derive(Debug, Clone)]
1025pub struct TupleType {
1026 /// Metadata about this tuple type.
1027 pub(crate) info: TypeInfo,
1028 /// The types of the tuple.
1029 pub types: Box<[ComponentValType]>,
1030}
1031
1032/// Represents a component defined type.
1033#[derive(Debug, Clone)]
1034pub enum ComponentDefinedType {
1035 /// The type is a primitive value type.
1036 Primitive(PrimitiveValType),
1037 /// The type is a record.
1038 Record(RecordType),
1039 /// The type is a variant.
1040 Variant(VariantType),
1041 /// The type is a list.
1042 List(ComponentValType),
1043 /// The type is a tuple.
1044 Tuple(TupleType),
1045 /// The type is a set of flags.
1046 Flags(IndexSet<KebabString>),
1047 /// The type is an enumeration.
1048 Enum(IndexSet<KebabString>),
1049 /// The type is an `option`.
1050 Option(ComponentValType),
1051 /// The type is a `result`.
1052 Result {
1053 /// The `ok` type.
1054 ok: Option<ComponentValType>,
1055 /// The `error` type.
1056 err: Option<ComponentValType>,
1057 },
1058 /// The type is an owned handle to the specified resource.
1059 Own(AliasableResourceId),
1060 /// The type is a borrowed handle to the specified resource.
1061 Borrow(AliasableResourceId),
1062 /// A future type with the specified payload type.
1063 Future(Option<ComponentValType>),
1064 /// A stream type with the specified payload type.
1065 Stream(ComponentValType),
1066 /// The error-context type.
1067 ErrorContext,
1068}
1069
1070impl TypeData for ComponentDefinedType {
1071 type Id = ComponentDefinedTypeId;
1072
1073 fn type_info(&self, types: &TypeList) -> TypeInfo {
1074 match self {
1075 Self::Primitive(_)
1076 | Self::Flags(_)
1077 | Self::Enum(_)
1078 | Self::Own(_)
1079 | Self::Future(_)
1080 | Self::Stream(_)
1081 | Self::ErrorContext => TypeInfo::new(),
1082 Self::Borrow(_) => TypeInfo::borrow(),
1083 Self::Record(r) => r.info,
1084 Self::Variant(v) => v.info,
1085 Self::Tuple(t) => t.info,
1086 Self::List(ty) | Self::Option(ty) => ty.info(types),
1087 Self::Result { ok, err } => {
1088 let default = TypeInfo::new();
1089 let mut info = ok.map(|ty| ty.type_info(types)).unwrap_or(default);
1090 info.combine(err.map(|ty| ty.type_info(types)).unwrap_or(default), 0)
1091 .unwrap();
1092 info
1093 }
1094 }
1095 }
1096}
1097
1098impl ComponentDefinedType {
1099 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
1100 match self {
1101 Self::Primitive(ty) => ty.contains_ptr(),
1102 Self::Record(r) => r.fields.values().any(|ty| ty.contains_ptr(types)),
1103 Self::Variant(v) => v
1104 .cases
1105 .values()
1106 .any(|case| case.ty.map(|ty| ty.contains_ptr(types)).unwrap_or(false)),
1107 Self::List(_) => true,
1108 Self::Tuple(t) => t.types.iter().any(|ty| ty.contains_ptr(types)),
1109 Self::Flags(_)
1110 | Self::Enum(_)
1111 | Self::Own(_)
1112 | Self::Borrow(_)
1113 | Self::Future(_)
1114 | Self::Stream(_)
1115 | Self::ErrorContext => false,
1116 Self::Option(ty) => ty.contains_ptr(types),
1117 Self::Result { ok, err } => {
1118 ok.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1119 || err.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1120 }
1121 }
1122 }
1123
1124 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1125 match self {
1126 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1127 Self::Record(r) => r
1128 .fields
1129 .iter()
1130 .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1131 Self::Variant(v) => Self::push_variant_wasm_types(
1132 v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1133 types,
1134 lowered_types,
1135 ),
1136 Self::List(_) => lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32),
1137 Self::Tuple(t) => t
1138 .types
1139 .iter()
1140 .all(|ty| ty.push_wasm_types(types, lowered_types)),
1141 Self::Flags(names) => {
1142 (0..(names.len() + 31) / 32).all(|_| lowered_types.push(ValType::I32))
1143 }
1144 Self::Enum(_)
1145 | Self::Own(_)
1146 | Self::Borrow(_)
1147 | Self::Future(_)
1148 | Self::Stream(_)
1149 | Self::ErrorContext => lowered_types.push(ValType::I32),
1150 Self::Option(ty) => {
1151 Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1152 }
1153 Self::Result { ok, err } => {
1154 Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1155 }
1156 }
1157 }
1158
1159 fn push_variant_wasm_types<'a>(
1160 cases: impl Iterator<Item = &'a ComponentValType>,
1161 types: &TypeList,
1162 lowered_types: &mut LoweredTypes,
1163 ) -> bool {
1164 // Push the discriminant
1165 if !lowered_types.push(ValType::I32) {
1166 return false;
1167 }
1168
1169 let start = lowered_types.len();
1170
1171 for ty in cases {
1172 let mut temp = LoweredTypes::new(lowered_types.max);
1173
1174 if !ty.push_wasm_types(types, &mut temp) {
1175 return false;
1176 }
1177
1178 for (i, ty) in temp.iter().enumerate() {
1179 match lowered_types.get_mut(start + i) {
1180 Some(prev) => *prev = Self::join_types(*prev, ty),
1181 None => {
1182 if !lowered_types.push(ty) {
1183 return false;
1184 }
1185 }
1186 }
1187 }
1188 }
1189
1190 true
1191 }
1192
1193 fn join_types(a: ValType, b: ValType) -> ValType {
1194 use ValType::*;
1195
1196 match (a, b) {
1197 (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1198 (I32, F32) | (F32, I32) => I32,
1199 (_, I64 | F64) | (I64 | F64, _) => I64,
1200 _ => panic!("unexpected wasm type for canonical ABI"),
1201 }
1202 }
1203
1204 fn desc(&self) -> &'static str {
1205 match self {
1206 ComponentDefinedType::Record(_) => "record",
1207 ComponentDefinedType::Primitive(_) => "primitive",
1208 ComponentDefinedType::Variant(_) => "variant",
1209 ComponentDefinedType::Tuple(_) => "tuple",
1210 ComponentDefinedType::Enum(_) => "enum",
1211 ComponentDefinedType::Flags(_) => "flags",
1212 ComponentDefinedType::Option(_) => "option",
1213 ComponentDefinedType::List(_) => "list",
1214 ComponentDefinedType::Result { .. } => "result",
1215 ComponentDefinedType::Own(_) => "own",
1216 ComponentDefinedType::Borrow(_) => "borrow",
1217 ComponentDefinedType::Future(_) => "future",
1218 ComponentDefinedType::Stream(_) => "stream",
1219 ComponentDefinedType::ErrorContext => "error-context",
1220 }
1221 }
1222}
1223
1224/// An opaque identifier intended to be used to distinguish whether two
1225/// resource types are equivalent or not.
1226#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
1227#[repr(packed(4))] // try to not waste 4 bytes in padding
1228pub struct ResourceId {
1229 // This is a globally unique identifier which is assigned once per
1230 // `TypeAlloc`. This ensures that resource identifiers from different
1231 // instances of `Types`, for example, are considered unique.
1232 //
1233 // Technically 64-bits should be enough for all resource ids ever, but
1234 // they're allocated so often it's predicted that an atomic increment
1235 // per resource id is probably too expensive. To amortize that cost each
1236 // top-level wasm component gets a single globally unique identifier, and
1237 // then within a component contextually unique identifiers are handed out.
1238 globally_unique_id: usize,
1239
1240 // A contextually unique id within the globally unique id above. This is
1241 // allocated within a `TypeAlloc` with its own counter, and allocations of
1242 // this are cheap as nothing atomic is required.
1243 //
1244 // The 32-bit storage here should ideally be enough for any component
1245 // containing resources. If memory usage becomes an issue (this struct is
1246 // 12 bytes instead of 8 or 4) then this could get folded into the globally
1247 // unique id with everything using an atomic increment perhaps.
1248 contextually_unique_id: u32,
1249}
1250
1251impl<'a> TypesRef<'a> {
1252 /// Gets a core WebAssembly type id from a type index.
1253 ///
1254 /// Note that this is not to be confused with
1255 /// [`TypesRef::component_type_at`] which gets a component type from its
1256 /// index, nor [`TypesRef::core_type_count_in_module`] which does not work
1257 /// for components.
1258 ///
1259 /// # Panics
1260 ///
1261 /// This will panic if the `index` provided is out of bounds.
1262 pub fn core_type_at_in_component(&self, index: u32) -> ComponentCoreTypeId {
1263 match &self.kind {
1264 TypesRefKind::Module(_) => panic!("use `component_type_at_in_module` instead"),
1265 TypesRefKind::Component(component) => component.core_types[index as usize],
1266 }
1267 }
1268
1269 /// Returns the number of core types defined so far within a component.
1270 ///
1271 /// This should only be used for components. For modules see
1272 /// [`TypesRef::core_type_count_in_module`].
1273 pub fn core_type_count_in_component(&self) -> u32 {
1274 match &self.kind {
1275 TypesRefKind::Module(_) => 0,
1276 TypesRefKind::Component(component) => component.core_types.len() as u32,
1277 }
1278 }
1279
1280 /// Gets a type id from a type index.
1281 ///
1282 /// # Panics
1283 ///
1284 /// Panics if `index` is not a valid type index or if this type information
1285 /// represents a core module.
1286 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1287 match &self.kind {
1288 TypesRefKind::Module(_) => panic!("not a component"),
1289 TypesRefKind::Component(component) => component.types[index as usize],
1290 }
1291 }
1292
1293 /// Gets a component type id from a type index.
1294 ///
1295 /// # Panics
1296 ///
1297 /// Panics if `index` is not a valid component type index or if this type
1298 /// information represents a core module.
1299 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1300 match self.component_any_type_at(index) {
1301 ComponentAnyTypeId::Component(id) => id,
1302 _ => panic!("not a component type"),
1303 }
1304 }
1305
1306 /// Gets a type id from a type index.
1307 ///
1308 /// # Panics
1309 ///
1310 /// Panics if `index` is not a valid function index or if this type
1311 /// information represents a core module.
1312 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1313 match self.component_any_type_at(index) {
1314 ComponentAnyTypeId::Defined(id) => id,
1315 _ => panic!("not a defined type"),
1316 }
1317 }
1318
1319 /// Returns the number of component types defined so far.
1320 pub fn component_type_count(&self) -> u32 {
1321 match &self.kind {
1322 TypesRefKind::Module(_module) => 0,
1323 TypesRefKind::Component(component) => component.types.len() as u32,
1324 }
1325 }
1326
1327 /// Gets the type of a component function at the given function index.
1328 ///
1329 /// # Panics
1330 ///
1331 /// This will panic if the `index` provided is out of bounds or if this type
1332 /// information represents a core module.
1333 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
1334 match &self.kind {
1335 TypesRefKind::Module(_) => panic!("not a component"),
1336 TypesRefKind::Component(component) => component.funcs[index as usize],
1337 }
1338 }
1339
1340 /// Returns the number of component functions defined so far.
1341 pub fn component_function_count(&self) -> u32 {
1342 match &self.kind {
1343 TypesRefKind::Module(_module) => 0,
1344 TypesRefKind::Component(component) => component.funcs.len() as u32,
1345 }
1346 }
1347
1348 /// Gets the type of a module at the given module index.
1349 ///
1350 /// # Panics
1351 ///
1352 /// This will panic if the `index` provided is out of bounds or if this type
1353 /// information represents a core module.
1354 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
1355 match &self.kind {
1356 TypesRefKind::Module(_) => panic!("not a component"),
1357 TypesRefKind::Component(component) => component.core_modules[index as usize],
1358 }
1359 }
1360
1361 /// Returns the number of core wasm modules defined so far.
1362 pub fn module_count(&self) -> u32 {
1363 match &self.kind {
1364 TypesRefKind::Module(_module) => 0,
1365 TypesRefKind::Component(component) => component.core_modules.len() as u32,
1366 }
1367 }
1368
1369 /// Gets the type of a module instance at the given module instance index.
1370 ///
1371 /// # Panics
1372 ///
1373 /// This will panic if the `index` provided is out of bounds or if this type
1374 /// information represents a core module.
1375 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
1376 match &self.kind {
1377 TypesRefKind::Module(_) => panic!("not a component"),
1378 TypesRefKind::Component(component) => component.core_instances[index as usize],
1379 }
1380 }
1381
1382 /// Returns the number of core wasm instances defined so far.
1383 pub fn core_instance_count(&self) -> u32 {
1384 match &self.kind {
1385 TypesRefKind::Module(_module) => 0,
1386 TypesRefKind::Component(component) => component.core_instances.len() as u32,
1387 }
1388 }
1389
1390 /// Gets the type of a component at the given component index.
1391 ///
1392 /// # Panics
1393 ///
1394 /// This will panic if the `index` provided is out of bounds or if this type
1395 /// information represents a core module.
1396 pub fn component_at(&self, index: u32) -> ComponentTypeId {
1397 match &self.kind {
1398 TypesRefKind::Module(_) => panic!("not a component"),
1399 TypesRefKind::Component(component) => component.components[index as usize],
1400 }
1401 }
1402
1403 /// Returns the number of components defined so far.
1404 pub fn component_count(&self) -> u32 {
1405 match &self.kind {
1406 TypesRefKind::Module(_module) => 0,
1407 TypesRefKind::Component(component) => component.components.len() as u32,
1408 }
1409 }
1410
1411 /// Gets the type of an component instance at the given component instance index.
1412 ///
1413 /// # Panics
1414 ///
1415 /// This will panic if the `index` provided is out of bounds or if this type
1416 /// information represents a core module.
1417 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
1418 match &self.kind {
1419 TypesRefKind::Module(_) => panic!("not a component"),
1420 TypesRefKind::Component(component) => component.instances[index as usize],
1421 }
1422 }
1423
1424 /// Returns the number of component instances defined so far.
1425 pub fn component_instance_count(&self) -> u32 {
1426 match &self.kind {
1427 TypesRefKind::Module(_module) => 0,
1428 TypesRefKind::Component(component) => component.instances.len() as u32,
1429 }
1430 }
1431
1432 /// Gets the type of a value at the given value index.
1433 ///
1434 /// # Panics
1435 ///
1436 /// This will panic if the `index` provided is out of bounds or if this type
1437 /// information represents a core module.
1438 pub fn value_at(&self, index: u32) -> ComponentValType {
1439 match &self.kind {
1440 TypesRefKind::Module(_) => panic!("not a component"),
1441 TypesRefKind::Component(component) => component.values[index as usize].0,
1442 }
1443 }
1444
1445 /// Returns the number of component values defined so far.
1446 pub fn value_count(&self) -> u32 {
1447 match &self.kind {
1448 TypesRefKind::Module(_module) => 0,
1449 TypesRefKind::Component(component) => component.values.len() as u32,
1450 }
1451 }
1452
1453 /// Gets the component entity type for the given component import.
1454 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
1455 match &self.kind {
1456 TypesRefKind::Module(_) => None,
1457 TypesRefKind::Component(component) => Some(*component.imports.get(name)?),
1458 }
1459 }
1460
1461 /// Gets the component entity type for the given component export.
1462 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
1463 match &self.kind {
1464 TypesRefKind::Module(_) => None,
1465 TypesRefKind::Component(component) => Some(*component.exports.get(name)?),
1466 }
1467 }
1468
1469 /// Attempts to lookup the type id that `ty` is an alias of.
1470 ///
1471 /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
1472 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
1473 where
1474 T: Aliasable,
1475 {
1476 self.list.peel_alias(ty)
1477 }
1478}
1479
1480impl Types {
1481 /// Gets a component WebAssembly type at the given type index.
1482 ///
1483 /// Note that this is in contrast to [`TypesRef::core_type_at_in_component`]
1484 /// which gets a core type from its index.
1485 ///
1486 /// # Panics
1487 ///
1488 /// Panics if `index` is not a valid type index.
1489 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1490 self.as_ref().component_any_type_at(index)
1491 }
1492
1493 /// Gets a component type at the given type index.
1494 ///
1495 /// # Panics
1496 ///
1497 /// Panics if `index` is not a valid component type index.
1498 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1499 self.as_ref().component_type_at(index)
1500 }
1501
1502 /// Gets a component type from the given component type index.
1503 ///
1504 /// # Panics
1505 ///
1506 /// Panics if `index` is not a valid defined type index or if this type
1507 /// information represents a core module.
1508 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1509 self.as_ref().component_defined_type_at(index)
1510 }
1511
1512 /// Gets the type of a component function at the given function index.
1513 ///
1514 /// # Panics
1515 ///
1516 /// This will panic if the `index` provided is out of bounds or if this type
1517 /// information represents a core module.
1518 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
1519 self.as_ref().component_function_at(index)
1520 }
1521
1522 /// Gets the count of imported, exported, or aliased component functions.
1523 pub fn component_function_count(&self) -> u32 {
1524 self.as_ref().component_function_count()
1525 }
1526
1527 /// Gets the type of a module at the given module index.
1528 ///
1529 /// # Panics
1530 ///
1531 /// This will panic if the `index` provided is out of bounds or if this type
1532 /// information represents a core module.
1533 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
1534 self.as_ref().module_at(index)
1535 }
1536
1537 /// Gets the count of imported, exported, or aliased modules.
1538 pub fn module_count(&self) -> usize {
1539 match &self.kind {
1540 TypesKind::Module(_) => 0,
1541 TypesKind::Component(component) => component.core_modules.len(),
1542 }
1543 }
1544
1545 /// Gets the type of a module instance at the given module instance index.
1546 ///
1547 /// # Panics
1548 ///
1549 /// This will panic if the `index` provided is out of bounds or if this type
1550 /// information represents a core module.
1551 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
1552 self.as_ref().core_instance_at(index)
1553 }
1554
1555 /// Gets the count of imported, exported, or aliased core module instances.
1556 pub fn core_instance_count(&self) -> usize {
1557 match &self.kind {
1558 TypesKind::Module(_) => 0,
1559 TypesKind::Component(component) => component.core_instances.len(),
1560 }
1561 }
1562
1563 /// Gets the type of a component at the given component index.
1564 ///
1565 /// # Panics
1566 ///
1567 /// This will panic if the `index` provided is out of bounds or if this type
1568 /// information represents a core module.
1569 pub fn component_at(&self, index: u32) -> ComponentTypeId {
1570 self.as_ref().component_at(index)
1571 }
1572
1573 /// Gets the count of imported, exported, or aliased components.
1574 pub fn component_count(&self) -> usize {
1575 match &self.kind {
1576 TypesKind::Module(_) => 0,
1577 TypesKind::Component(component) => component.components.len(),
1578 }
1579 }
1580
1581 /// Gets the type of an component instance at the given component instance index.
1582 ///
1583 /// # Panics
1584 ///
1585 /// This will panic if the `index` provided is out of bounds or if this type
1586 /// information represents a core module.
1587 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
1588 self.as_ref().component_instance_at(index)
1589 }
1590
1591 /// Gets the count of imported, exported, or aliased component instances.
1592 pub fn component_instance_count(&self) -> usize {
1593 match &self.kind {
1594 TypesKind::Module(_) => 0,
1595 TypesKind::Component(component) => component.instances.len(),
1596 }
1597 }
1598
1599 /// Gets the type of a value at the given value index.
1600 ///
1601 /// # Panics
1602 ///
1603 /// This will panic if the `index` provided is out of bounds or if this type
1604 /// information represents a core module.
1605 pub fn value_at(&self, index: u32) -> ComponentValType {
1606 self.as_ref().value_at(index)
1607 }
1608
1609 /// Gets the count of imported, exported, or aliased values.
1610 pub fn value_count(&self) -> usize {
1611 match &self.kind {
1612 TypesKind::Module(_) => 0,
1613 TypesKind::Component(component) => component.values.len(),
1614 }
1615 }
1616
1617 /// Gets the component entity type for the given component import name.
1618 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
1619 self.as_ref().component_entity_type_of_import(name)
1620 }
1621
1622 /// Gets the component entity type for the given component export name.
1623 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
1624 self.as_ref().component_entity_type_of_export(name)
1625 }
1626
1627 /// Attempts to lookup the type id that `ty` is an alias of.
1628 ///
1629 /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
1630 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
1631 where
1632 T: Aliasable,
1633 {
1634 self.list.peel_alias(ty)
1635 }
1636}
1637
1638/// A snapshot list of types.
1639#[derive(Debug, Default)]
1640pub(crate) struct ComponentTypeList {
1641 // Keeps track of which `alias_id` is an alias of which other `alias_id`.
1642 alias_mappings: Map<u32, u32>,
1643 // Counter for generating new `alias_id`s.
1644 alias_counter: u32,
1645 // Snapshots of previously committed `TypeList`s' aliases.
1646 alias_snapshots: Vec<TypeListAliasSnapshot>,
1647
1648 // Component model types.
1649 components: SnapshotList<ComponentType>,
1650 component_defined_types: SnapshotList<ComponentDefinedType>,
1651 component_values: SnapshotList<ComponentValType>,
1652 component_instances: SnapshotList<ComponentInstanceType>,
1653 component_funcs: SnapshotList<ComponentFuncType>,
1654 core_modules: SnapshotList<ModuleType>,
1655 core_instances: SnapshotList<InstanceType>,
1656}
1657
1658#[derive(Clone, Debug)]
1659struct TypeListAliasSnapshot {
1660 // The `alias_counter` at the time that this snapshot was taken.
1661 alias_counter: u32,
1662
1663 // The alias mappings in this snapshot.
1664 alias_mappings: Map<u32, u32>,
1665}
1666
1667struct TypeListCheckpoint {
1668 core_types: usize,
1669 components: usize,
1670 component_defined_types: usize,
1671 component_values: usize,
1672 component_instances: usize,
1673 component_funcs: usize,
1674 core_modules: usize,
1675 core_instances: usize,
1676 core_type_to_rec_group: usize,
1677 core_type_to_supertype: usize,
1678 core_type_to_depth: usize,
1679 rec_group_elements: usize,
1680 canonical_rec_groups: usize,
1681}
1682
1683impl TypeList {
1684 fn checkpoint(&self) -> TypeListCheckpoint {
1685 let TypeList {
1686 component:
1687 ComponentTypeList {
1688 alias_mappings: _,
1689 alias_counter: _,
1690 alias_snapshots: _,
1691 components,
1692 component_defined_types,
1693 component_values,
1694 component_instances,
1695 component_funcs,
1696 core_modules,
1697 core_instances,
1698 },
1699 core_types,
1700 core_type_to_rec_group,
1701 core_type_to_supertype,
1702 core_type_to_depth,
1703 rec_group_elements,
1704 canonical_rec_groups,
1705 } = self;
1706
1707 TypeListCheckpoint {
1708 core_types: core_types.len(),
1709 components: components.len(),
1710 component_defined_types: component_defined_types.len(),
1711 component_values: component_values.len(),
1712 component_instances: component_instances.len(),
1713 component_funcs: component_funcs.len(),
1714 core_modules: core_modules.len(),
1715 core_instances: core_instances.len(),
1716 core_type_to_rec_group: core_type_to_rec_group.len(),
1717 core_type_to_supertype: core_type_to_supertype.len(),
1718 core_type_to_depth: core_type_to_depth.as_ref().map(|m| m.len()).unwrap_or(0),
1719 rec_group_elements: rec_group_elements.len(),
1720 canonical_rec_groups: canonical_rec_groups.as_ref().map(|m| m.len()).unwrap_or(0),
1721 }
1722 }
1723
1724 fn reset_to_checkpoint(&mut self, checkpoint: TypeListCheckpoint) {
1725 let TypeList {
1726 component:
1727 ComponentTypeList {
1728 alias_mappings: _,
1729 alias_counter: _,
1730 alias_snapshots: _,
1731 components,
1732 component_defined_types,
1733 component_values,
1734 component_instances,
1735 component_funcs,
1736 core_modules,
1737 core_instances,
1738 },
1739 core_types,
1740 core_type_to_rec_group,
1741 core_type_to_supertype,
1742 core_type_to_depth,
1743 rec_group_elements,
1744 canonical_rec_groups,
1745 } = self;
1746
1747 core_types.truncate(checkpoint.core_types);
1748 components.truncate(checkpoint.components);
1749 component_defined_types.truncate(checkpoint.component_defined_types);
1750 component_values.truncate(checkpoint.component_values);
1751 component_instances.truncate(checkpoint.component_instances);
1752 component_funcs.truncate(checkpoint.component_funcs);
1753 core_modules.truncate(checkpoint.core_modules);
1754 core_instances.truncate(checkpoint.core_instances);
1755 core_type_to_rec_group.truncate(checkpoint.core_type_to_rec_group);
1756 core_type_to_supertype.truncate(checkpoint.core_type_to_supertype);
1757 rec_group_elements.truncate(checkpoint.rec_group_elements);
1758
1759 if let Some(core_type_to_depth) = core_type_to_depth {
1760 assert_eq!(
1761 core_type_to_depth.len(),
1762 checkpoint.core_type_to_depth,
1763 "checkpointing does not support resetting `core_type_to_depth` (it would require a \
1764 proper immutable and persistent hash map) so adding new groups is disallowed"
1765 );
1766 }
1767 if let Some(canonical_rec_groups) = canonical_rec_groups {
1768 assert_eq!(
1769 canonical_rec_groups.len(),
1770 checkpoint.canonical_rec_groups,
1771 "checkpointing does not support resetting `canonical_rec_groups` (it would require a \
1772 proper immutable and persistent hash map) so adding new groups is disallowed"
1773 );
1774 }
1775 }
1776
1777 /// See `SnapshotList::with_unique`.
1778 pub fn with_unique<T>(&mut self, mut ty: T) -> T
1779 where
1780 T: Aliasable,
1781 {
1782 self.component
1783 .alias_mappings
1784 .insert(self.component.alias_counter, ty.alias_id());
1785 ty.set_alias_id(self.component.alias_counter);
1786 self.component.alias_counter += 1;
1787 ty
1788 }
1789
1790 /// Attempts to lookup the type id that `ty` is an alias of.
1791 ///
1792 /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
1793 pub fn peel_alias<T>(&self, mut ty: T) -> Option<T>
1794 where
1795 T: Aliasable,
1796 {
1797 let alias_id = ty.alias_id();
1798
1799 // The unique counter in each snapshot is the unique counter at the
1800 // time of the snapshot so it's guaranteed to never be used, meaning
1801 // that `Ok` should never show up here. With an `Err` it's where the
1802 // index would be placed meaning that the index in question is the
1803 // smallest value over the unique id's value, meaning that slot has the
1804 // mapping we're interested in.
1805 let i = match self
1806 .component
1807 .alias_snapshots
1808 .binary_search_by_key(&alias_id, |snapshot| snapshot.alias_counter)
1809 {
1810 Ok(_) => unreachable!(),
1811 Err(i) => i,
1812 };
1813
1814 // If the `i` index is beyond the snapshot array then lookup in the
1815 // current mappings instead since it may refer to a type not snapshot
1816 // yet.
1817 ty.set_alias_id(match self.component.alias_snapshots.get(i) {
1818 Some(snapshot) => *snapshot.alias_mappings.get(&alias_id)?,
1819 None => *self.component.alias_mappings.get(&alias_id)?,
1820 });
1821 Some(ty)
1822 }
1823}
1824
1825impl ComponentTypeList {
1826 pub fn commit(&mut self) -> ComponentTypeList {
1827 // Note that the `alias_counter` is bumped here to ensure that the
1828 // previous value of the unique counter is never used for an actual type
1829 // so it's suitable for lookup via a binary search.
1830 let alias_counter = self.alias_counter;
1831 self.alias_counter += 1;
1832
1833 self.alias_snapshots.push(TypeListAliasSnapshot {
1834 alias_counter,
1835 alias_mappings: mem::take(&mut self.alias_mappings),
1836 });
1837
1838 ComponentTypeList {
1839 alias_mappings: Map::default(),
1840 alias_counter: self.alias_counter,
1841 alias_snapshots: self.alias_snapshots.clone(),
1842 components: self.components.commit(),
1843 component_defined_types: self.component_defined_types.commit(),
1844 component_values: self.component_values.commit(),
1845 component_instances: self.component_instances.commit(),
1846 component_funcs: self.component_funcs.commit(),
1847 core_modules: self.core_modules.commit(),
1848 core_instances: self.core_instances.commit(),
1849 }
1850 }
1851}
1852
1853pub(crate) struct ComponentTypeAlloc {
1854 // This is assigned at creation of a `TypeAlloc` and then never changed.
1855 // It's used in one entry for all `ResourceId`s contained within.
1856 globally_unique_id: usize,
1857
1858 // This is a counter that's incremeneted each time `alloc_resource_id` is
1859 // called.
1860 next_resource_id: u32,
1861}
1862
1863impl Default for ComponentTypeAlloc {
1864 fn default() -> ComponentTypeAlloc {
1865 static NEXT_GLOBAL_ID: AtomicUsize = AtomicUsize::new(0);
1866 ComponentTypeAlloc {
1867 globally_unique_id: {
1868 let id: usize = NEXT_GLOBAL_ID.fetch_add(val:1, order:Ordering::Relaxed);
1869 if id > usize::MAX - 10_000 {
1870 NEXT_GLOBAL_ID.store(val:usize::MAX - 10_000, order:Ordering::Relaxed);
1871 panic!("overflow on the global id counter");
1872 }
1873 id
1874 },
1875 next_resource_id: 0,
1876 }
1877 }
1878}
1879
1880impl TypeAlloc {
1881 /// Allocates a new unique resource identifier.
1882 ///
1883 /// Note that uniqueness is only a property within this `TypeAlloc`.
1884 pub fn alloc_resource_id(&mut self) -> AliasableResourceId {
1885 let contextually_unique_id = self.component_alloc.next_resource_id;
1886 self.component_alloc.next_resource_id = self
1887 .component_alloc
1888 .next_resource_id
1889 .checked_add(1)
1890 .unwrap();
1891 AliasableResourceId {
1892 id: ResourceId {
1893 globally_unique_id: self.component_alloc.globally_unique_id,
1894 contextually_unique_id,
1895 },
1896 alias_id: NO_ALIAS,
1897 }
1898 }
1899
1900 /// Adds the set of "free variables" of the `id` provided to the `set`
1901 /// provided.
1902 ///
1903 /// Free variables are defined as resources. Any resource, perhaps
1904 /// transitively, referred to but not defined by `id` is added to the `set`
1905 /// and returned.
1906 pub fn free_variables_any_type_id(
1907 &self,
1908 id: ComponentAnyTypeId,
1909 set: &mut IndexSet<ResourceId>,
1910 ) {
1911 match id {
1912 ComponentAnyTypeId::Resource(r) => {
1913 set.insert(r.resource());
1914 }
1915 ComponentAnyTypeId::Defined(id) => {
1916 self.free_variables_component_defined_type_id(id, set)
1917 }
1918 ComponentAnyTypeId::Func(id) => self.free_variables_component_func_type_id(id, set),
1919 ComponentAnyTypeId::Instance(id) => {
1920 self.free_variables_component_instance_type_id(id, set)
1921 }
1922 ComponentAnyTypeId::Component(id) => self.free_variables_component_type_id(id, set),
1923 }
1924 }
1925
1926 pub fn free_variables_component_defined_type_id(
1927 &self,
1928 id: ComponentDefinedTypeId,
1929 set: &mut IndexSet<ResourceId>,
1930 ) {
1931 match &self[id] {
1932 ComponentDefinedType::Primitive(_)
1933 | ComponentDefinedType::Flags(_)
1934 | ComponentDefinedType::Enum(_)
1935 | ComponentDefinedType::ErrorContext => {}
1936 ComponentDefinedType::Record(r) => {
1937 for ty in r.fields.values() {
1938 self.free_variables_valtype(ty, set);
1939 }
1940 }
1941 ComponentDefinedType::Tuple(r) => {
1942 for ty in r.types.iter() {
1943 self.free_variables_valtype(ty, set);
1944 }
1945 }
1946 ComponentDefinedType::Variant(r) => {
1947 for ty in r.cases.values() {
1948 if let Some(ty) = &ty.ty {
1949 self.free_variables_valtype(ty, set);
1950 }
1951 }
1952 }
1953 ComponentDefinedType::List(ty)
1954 | ComponentDefinedType::Option(ty)
1955 | ComponentDefinedType::Stream(ty) => {
1956 self.free_variables_valtype(ty, set);
1957 }
1958 ComponentDefinedType::Result { ok, err } => {
1959 if let Some(ok) = ok {
1960 self.free_variables_valtype(ok, set);
1961 }
1962 if let Some(err) = err {
1963 self.free_variables_valtype(err, set);
1964 }
1965 }
1966 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
1967 set.insert(id.resource());
1968 }
1969 ComponentDefinedType::Future(ty) => {
1970 if let Some(ty) = ty {
1971 self.free_variables_valtype(ty, set);
1972 }
1973 }
1974 }
1975 }
1976
1977 pub fn free_variables_component_type_id(
1978 &self,
1979 id: ComponentTypeId,
1980 set: &mut IndexSet<ResourceId>,
1981 ) {
1982 let i = &self[id];
1983 // Recurse on the imports/exports of components, but remove the
1984 // imported and defined resources within the component itself.
1985 //
1986 // Technically this needs to add all the free variables of the
1987 // exports, remove the defined resources, then add the free
1988 // variables of imports, then remove the imported resources. Given
1989 // prior validation of component types, however, the defined
1990 // and imported resources are disjoint and imports can't refer to
1991 // defined resources, so doing this all in one go should be
1992 // equivalent.
1993 for ty in i.imports.values().chain(i.exports.values()) {
1994 self.free_variables_component_entity(ty, set);
1995 }
1996 for (id, _path) in i.imported_resources.iter().chain(&i.defined_resources) {
1997 set.swap_remove(id);
1998 }
1999 }
2000
2001 pub fn free_variables_component_instance_type_id(
2002 &self,
2003 id: ComponentInstanceTypeId,
2004 set: &mut IndexSet<ResourceId>,
2005 ) {
2006 let i = &self[id];
2007 // Like components, add in all the free variables of referenced
2008 // types but then remove those defined by this component instance
2009 // itself.
2010 for ty in i.exports.values() {
2011 self.free_variables_component_entity(ty, set);
2012 }
2013 for id in i.defined_resources.iter() {
2014 set.swap_remove(id);
2015 }
2016 }
2017
2018 pub fn free_variables_component_func_type_id(
2019 &self,
2020 id: ComponentFuncTypeId,
2021 set: &mut IndexSet<ResourceId>,
2022 ) {
2023 let i = &self[id];
2024 for ty in i
2025 .params
2026 .iter()
2027 .map(|(_, ty)| ty)
2028 .chain(i.results.iter().map(|(_, ty)| ty))
2029 {
2030 self.free_variables_valtype(ty, set);
2031 }
2032 }
2033
2034 /// Same as `free_variables_type_id`, but for `ComponentEntityType`.
2035 pub fn free_variables_component_entity(
2036 &self,
2037 ty: &ComponentEntityType,
2038 set: &mut IndexSet<ResourceId>,
2039 ) {
2040 match ty {
2041 ComponentEntityType::Module(_) => {}
2042 ComponentEntityType::Func(id) => self.free_variables_component_func_type_id(*id, set),
2043 ComponentEntityType::Instance(id) => {
2044 self.free_variables_component_instance_type_id(*id, set)
2045 }
2046 ComponentEntityType::Component(id) => self.free_variables_component_type_id(*id, set),
2047 ComponentEntityType::Type { created, .. } => {
2048 self.free_variables_any_type_id(*created, set);
2049 }
2050 ComponentEntityType::Value(ty) => self.free_variables_valtype(ty, set),
2051 }
2052 }
2053
2054 /// Same as `free_variables_type_id`, but for `ComponentValType`.
2055 fn free_variables_valtype(&self, ty: &ComponentValType, set: &mut IndexSet<ResourceId>) {
2056 match ty {
2057 ComponentValType::Primitive(_) => {}
2058 ComponentValType::Type(id) => self.free_variables_component_defined_type_id(*id, set),
2059 }
2060 }
2061
2062 /// Returns whether the type `id` is "named" where named types are presented
2063 /// via the provided `set`.
2064 ///
2065 /// This requires that `id` is a `Defined` type.
2066 pub(crate) fn type_named_type_id(
2067 &self,
2068 id: ComponentDefinedTypeId,
2069 set: &Set<ComponentAnyTypeId>,
2070 ) -> bool {
2071 let ty = &self[id];
2072 match ty {
2073 // Primitives are always considered named
2074 ComponentDefinedType::Primitive(_) | ComponentDefinedType::ErrorContext => true,
2075
2076 // These structures are never allowed to be anonymous, so they
2077 // themselves must be named.
2078 ComponentDefinedType::Flags(_)
2079 | ComponentDefinedType::Enum(_)
2080 | ComponentDefinedType::Record(_)
2081 | ComponentDefinedType::Variant(_) => set.contains(&ComponentAnyTypeId::from(id)),
2082
2083 // All types below here are allowed to be anonymous, but their
2084 // own components must be appropriately named.
2085 ComponentDefinedType::Tuple(r) => {
2086 r.types.iter().all(|t| self.type_named_valtype(t, set))
2087 }
2088 ComponentDefinedType::Result { ok, err } => {
2089 ok.as_ref()
2090 .map(|t| self.type_named_valtype(t, set))
2091 .unwrap_or(true)
2092 && err
2093 .as_ref()
2094 .map(|t| self.type_named_valtype(t, set))
2095 .unwrap_or(true)
2096 }
2097 ComponentDefinedType::List(ty)
2098 | ComponentDefinedType::Option(ty)
2099 | ComponentDefinedType::Stream(ty) => self.type_named_valtype(ty, set),
2100
2101 // own/borrow themselves don't have to be named, but the resource
2102 // they refer to must be named.
2103 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2104 set.contains(&ComponentAnyTypeId::from(*id))
2105 }
2106
2107 ComponentDefinedType::Future(ty) => ty
2108 .as_ref()
2109 .map(|ty| self.type_named_valtype(ty, set))
2110 .unwrap_or(true),
2111 }
2112 }
2113
2114 pub(crate) fn type_named_valtype(
2115 &self,
2116 ty: &ComponentValType,
2117 set: &Set<ComponentAnyTypeId>,
2118 ) -> bool {
2119 match ty {
2120 ComponentValType::Primitive(_) => true,
2121 ComponentValType::Type(id) => self.type_named_type_id(*id, set),
2122 }
2123 }
2124}
2125
2126/// A helper trait to provide the functionality necessary to resources within a
2127/// type.
2128///
2129/// This currently exists to abstract over `TypeAlloc` and `SubtypeArena` which
2130/// both need to perform remapping operations.
2131pub trait Remap
2132where
2133 Self: Index<ComponentTypeId, Output = ComponentType>,
2134 Self: Index<ComponentDefinedTypeId, Output = ComponentDefinedType>,
2135 Self: Index<ComponentInstanceTypeId, Output = ComponentInstanceType>,
2136 Self: Index<ComponentFuncTypeId, Output = ComponentFuncType>,
2137{
2138 /// Pushes a new anonymous type within this object, returning an identifier
2139 /// which can be used to refer to it.
2140 fn push_ty<T>(&mut self, ty: T) -> T::Id
2141 where
2142 T: TypeData;
2143
2144 /// Apply `map` to the keys of `tmp`, setting `*any_changed = true` if any
2145 /// keys were remapped.
2146 fn map_map(
2147 tmp: &mut IndexMap<ResourceId, Vec<usize>>,
2148 any_changed: &mut bool,
2149 map: &Remapping,
2150 ) {
2151 for (id, path) in mem::take(tmp) {
2152 let id = match map.resources.get(&id) {
2153 Some(id) => {
2154 *any_changed = true;
2155 *id
2156 }
2157 None => id,
2158 };
2159 tmp.insert(id, path);
2160 }
2161 }
2162
2163 /// If `any_changed` is true, push `ty`, update `map` to point `id` to the
2164 /// new type ID, set `id` equal to the new type ID, and return `true`.
2165 /// Otherwise, update `map` to point `id` to itself and return `false`.
2166 fn insert_if_any_changed<T>(
2167 &mut self,
2168 map: &mut Remapping,
2169 any_changed: bool,
2170 id: &mut T::Id,
2171 ty: T,
2172 ) -> bool
2173 where
2174 T: TypeData,
2175 T::Id: Into<ComponentAnyTypeId>,
2176 {
2177 let new = if any_changed { self.push_ty(ty) } else { *id };
2178 map.types.insert((*id).into(), new.into());
2179 let changed = *id != new;
2180 *id = new;
2181 changed
2182 }
2183
2184 /// Recursively search for any resource types reachable from `id`, updating
2185 /// it and `map` if any are found and remapped, returning `true` iff at last
2186 /// one is remapped.
2187 fn remap_component_any_type_id(
2188 &mut self,
2189 id: &mut ComponentAnyTypeId,
2190 map: &mut Remapping,
2191 ) -> bool {
2192 match id {
2193 ComponentAnyTypeId::Resource(id) => self.remap_resource_id(id, map),
2194 ComponentAnyTypeId::Defined(id) => self.remap_component_defined_type_id(id, map),
2195 ComponentAnyTypeId::Func(id) => self.remap_component_func_type_id(id, map),
2196 ComponentAnyTypeId::Instance(id) => self.remap_component_instance_type_id(id, map),
2197 ComponentAnyTypeId::Component(id) => self.remap_component_type_id(id, map),
2198 }
2199 }
2200
2201 /// If `map` indicates `id` should be remapped, update it and return `true`.
2202 /// Otherwise, do nothing and return `false`.
2203 fn remap_resource_id(&mut self, id: &mut AliasableResourceId, map: &Remapping) -> bool {
2204 if let Some(changed) = map.remap_id(id) {
2205 return changed;
2206 }
2207
2208 match map.resources.get(&id.resource()) {
2209 None => false,
2210 Some(new_id) => {
2211 *id.resource_mut() = *new_id;
2212 true
2213 }
2214 }
2215 }
2216
2217 /// Recursively search for any resource types reachable from `id`, updating
2218 /// it and `map` if any are found and remapped, returning `true` iff at last
2219 /// one is remapped.
2220 fn remap_component_type_id(&mut self, id: &mut ComponentTypeId, map: &mut Remapping) -> bool {
2221 if let Some(changed) = map.remap_id(id) {
2222 return changed;
2223 }
2224
2225 let mut any_changed = false;
2226 let mut ty = self[*id].clone();
2227 for ty in ty.imports.values_mut().chain(ty.exports.values_mut()) {
2228 any_changed |= self.remap_component_entity(ty, map);
2229 }
2230 for (id, _) in ty
2231 .imported_resources
2232 .iter_mut()
2233 .chain(&mut ty.defined_resources)
2234 {
2235 if let Some(new) = map.resources.get(id) {
2236 *id = *new;
2237 any_changed = true;
2238 }
2239 }
2240 Self::map_map(&mut ty.explicit_resources, &mut any_changed, map);
2241 self.insert_if_any_changed(map, any_changed, id, ty)
2242 }
2243
2244 /// Recursively search for any resource types reachable from `id`, updating
2245 /// it and `map` if any are found and remapped, returning `true` iff at last
2246 /// one is remapped.
2247 fn remap_component_defined_type_id(
2248 &mut self,
2249 id: &mut ComponentDefinedTypeId,
2250 map: &mut Remapping,
2251 ) -> bool {
2252 if let Some(changed) = map.remap_id(id) {
2253 return changed;
2254 }
2255
2256 let mut any_changed = false;
2257 let mut tmp = self[*id].clone();
2258 match &mut tmp {
2259 ComponentDefinedType::Primitive(_)
2260 | ComponentDefinedType::Flags(_)
2261 | ComponentDefinedType::Enum(_)
2262 | ComponentDefinedType::ErrorContext => {}
2263 ComponentDefinedType::Record(r) => {
2264 for ty in r.fields.values_mut() {
2265 any_changed |= self.remap_valtype(ty, map);
2266 }
2267 }
2268 ComponentDefinedType::Tuple(r) => {
2269 for ty in r.types.iter_mut() {
2270 any_changed |= self.remap_valtype(ty, map);
2271 }
2272 }
2273 ComponentDefinedType::Variant(r) => {
2274 for ty in r.cases.values_mut() {
2275 if let Some(ty) = &mut ty.ty {
2276 any_changed |= self.remap_valtype(ty, map);
2277 }
2278 }
2279 }
2280 ComponentDefinedType::List(ty)
2281 | ComponentDefinedType::Option(ty)
2282 | ComponentDefinedType::Stream(ty) => {
2283 any_changed |= self.remap_valtype(ty, map);
2284 }
2285 ComponentDefinedType::Result { ok, err } => {
2286 if let Some(ok) = ok {
2287 any_changed |= self.remap_valtype(ok, map);
2288 }
2289 if let Some(err) = err {
2290 any_changed |= self.remap_valtype(err, map);
2291 }
2292 }
2293 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
2294 any_changed |= self.remap_resource_id(id, map);
2295 }
2296 ComponentDefinedType::Future(ty) => {
2297 if let Some(ty) = ty {
2298 any_changed |= self.remap_valtype(ty, map);
2299 }
2300 }
2301 }
2302 self.insert_if_any_changed(map, any_changed, id, tmp)
2303 }
2304
2305 /// Recursively search for any resource types reachable from `id`, updating
2306 /// it and `map` if any are found and remapped, returning `true` iff at last
2307 /// one is remapped.
2308 fn remap_component_instance_type_id(
2309 &mut self,
2310 id: &mut ComponentInstanceTypeId,
2311 map: &mut Remapping,
2312 ) -> bool {
2313 if let Some(changed) = map.remap_id(id) {
2314 return changed;
2315 }
2316
2317 let mut any_changed = false;
2318 let mut tmp = self[*id].clone();
2319 for ty in tmp.exports.values_mut() {
2320 any_changed |= self.remap_component_entity(ty, map);
2321 }
2322 for id in tmp.defined_resources.iter_mut() {
2323 if let Some(new) = map.resources.get(id) {
2324 *id = *new;
2325 any_changed = true;
2326 }
2327 }
2328 Self::map_map(&mut tmp.explicit_resources, &mut any_changed, map);
2329 self.insert_if_any_changed(map, any_changed, id, tmp)
2330 }
2331
2332 /// Recursively search for any resource types reachable from `id`, updating
2333 /// it and `map` if any are found and remapped, returning `true` iff at last
2334 /// one is remapped.
2335 fn remap_component_func_type_id(
2336 &mut self,
2337 id: &mut ComponentFuncTypeId,
2338 map: &mut Remapping,
2339 ) -> bool {
2340 if let Some(changed) = map.remap_id(id) {
2341 return changed;
2342 }
2343
2344 let mut any_changed = false;
2345 let mut tmp = self[*id].clone();
2346 for ty in tmp
2347 .params
2348 .iter_mut()
2349 .map(|(_, ty)| ty)
2350 .chain(tmp.results.iter_mut().map(|(_, ty)| ty))
2351 {
2352 any_changed |= self.remap_valtype(ty, map);
2353 }
2354 self.insert_if_any_changed(map, any_changed, id, tmp)
2355 }
2356
2357 /// Same as `remap_type_id`, but works with `ComponentEntityType`.
2358 fn remap_component_entity(
2359 &mut self,
2360 ty: &mut ComponentEntityType,
2361 map: &mut Remapping,
2362 ) -> bool {
2363 match ty {
2364 ComponentEntityType::Module(_) => {
2365 // Can't reference resources.
2366 false
2367 }
2368 ComponentEntityType::Func(id) => self.remap_component_func_type_id(id, map),
2369 ComponentEntityType::Instance(id) => self.remap_component_instance_type_id(id, map),
2370 ComponentEntityType::Component(id) => self.remap_component_type_id(id, map),
2371 ComponentEntityType::Type {
2372 referenced,
2373 created,
2374 } => {
2375 let mut changed = self.remap_component_any_type_id(referenced, map);
2376 if *referenced == *created {
2377 *created = *referenced;
2378 } else {
2379 changed |= self.remap_component_any_type_id(created, map);
2380 }
2381 changed
2382 }
2383 ComponentEntityType::Value(ty) => self.remap_valtype(ty, map),
2384 }
2385 }
2386
2387 /// Same as `remap_type_id`, but works with `ComponentValType`.
2388 fn remap_valtype(&mut self, ty: &mut ComponentValType, map: &mut Remapping) -> bool {
2389 match ty {
2390 ComponentValType::Primitive(_) => false,
2391 ComponentValType::Type(id) => self.remap_component_defined_type_id(id, map),
2392 }
2393 }
2394}
2395
2396/// Utility for mapping equivalent `ResourceId`s to each other and (when paired with the `Remap` trait)
2397/// non-destructively edit type lists to reflect those mappings.
2398#[derive(Debug, Default)]
2399pub struct Remapping {
2400 /// A mapping from old resource ID to new resource ID.
2401 pub(crate) resources: Map<ResourceId, ResourceId>,
2402
2403 /// A mapping filled in during the remapping process which records how a
2404 /// type was remapped, if applicable. This avoids remapping multiple
2405 /// references to the same type and instead only processing it once.
2406 types: Map<ComponentAnyTypeId, ComponentAnyTypeId>,
2407}
2408
2409impl Remap for TypeAlloc {
2410 fn push_ty<T>(&mut self, ty: T) -> T::Id
2411 where
2412 T: TypeData,
2413 {
2414 <TypeList>::push(self, ty)
2415 }
2416}
2417
2418impl Remapping {
2419 /// Add a mapping from the specified old resource ID to the new resource ID
2420 pub fn add(&mut self, old: ResourceId, new: ResourceId) {
2421 self.resources.insert(old, new);
2422 }
2423
2424 /// Clear the type cache while leaving the resource mappings intact.
2425 pub fn reset_type_cache(&mut self) {
2426 self.types.clear()
2427 }
2428
2429 fn remap_id<T>(&self, id: &mut T) -> Option<bool>
2430 where
2431 T: Copy + Into<ComponentAnyTypeId> + TryFrom<ComponentAnyTypeId>,
2432 T::Error: core::fmt::Debug,
2433 {
2434 let old: ComponentAnyTypeId = (*id).into();
2435 let new = self.types.get(&old)?;
2436 if *new == old {
2437 Some(false)
2438 } else {
2439 *id = T::try_from(*new).expect("should never remap across different kinds");
2440 Some(true)
2441 }
2442 }
2443}
2444
2445/// Helper structure used to perform subtyping computations.
2446///
2447/// This type is used whenever a subtype needs to be tested in one direction or
2448/// the other. The methods of this type are the various entry points for
2449/// subtyping.
2450///
2451/// Internally this contains arenas for two lists of types. The `a` arena is
2452/// intended to be used for lookup of the first argument to all of the methods
2453/// below, and the `b` arena is used for lookup of the second argument.
2454///
2455/// Arenas here are used specifically for component-based subtyping queries. In
2456/// these situations new types must be created based on substitution mappings,
2457/// but the types all have temporary lifetimes. Everything in these arenas is
2458/// thrown away once the subtyping computation has finished.
2459///
2460/// Note that this subtyping context also explicitly supports being created
2461/// from to different lists `a` and `b` originally, for testing subtyping
2462/// between two different components for example.
2463pub struct SubtypeCx<'a> {
2464 /// Lookup arena for first type argument
2465 pub a: SubtypeArena<'a>,
2466 /// Lookup arena for second type argument
2467 pub b: SubtypeArena<'a>,
2468}
2469
2470impl<'a> SubtypeCx<'a> {
2471 /// Create a new instance with the specified type lists
2472 pub fn new_with_refs(a: TypesRef<'a>, b: TypesRef<'a>) -> SubtypeCx<'a> {
2473 Self::new(a.list, b.list)
2474 }
2475
2476 pub(crate) fn new(a: &'a TypeList, b: &'a TypeList) -> SubtypeCx<'a> {
2477 SubtypeCx {
2478 a: SubtypeArena::new(a),
2479 b: SubtypeArena::new(b),
2480 }
2481 }
2482
2483 /// Swap the type lists
2484 pub fn swap(&mut self) {
2485 mem::swap(&mut self.a, &mut self.b);
2486 }
2487
2488 /// Executes the closure `f`, resetting the internal arenas to their
2489 /// original size after the closure finishes.
2490 ///
2491 /// This enables `f` to modify the internal arenas while relying on all
2492 /// changes being discarded after the closure finishes.
2493 fn with_checkpoint<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
2494 let a = self.a.list.checkpoint();
2495 let b = self.b.list.checkpoint();
2496 let result = f(self);
2497 self.a.list.reset_to_checkpoint(a);
2498 self.b.list.reset_to_checkpoint(b);
2499 result
2500 }
2501
2502 /// Tests whether `a` is a subtype of `b`.
2503 ///
2504 /// Errors are reported at the `offset` specified.
2505 pub fn component_entity_type(
2506 &mut self,
2507 a: &ComponentEntityType,
2508 b: &ComponentEntityType,
2509 offset: usize,
2510 ) -> Result<()> {
2511 use ComponentEntityType::*;
2512
2513 match (a, b) {
2514 (Module(a), Module(b)) => self.module_type(*a, *b, offset),
2515 (Module(_), b) => bail!(offset, "expected {}, found module", b.desc()),
2516
2517 (Func(a), Func(b)) => self.component_func_type(*a, *b, offset),
2518 (Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
2519
2520 (Value(a), Value(b)) => self.component_val_type(a, b, offset),
2521 (Value(_), b) => bail!(offset, "expected {}, found value", b.desc()),
2522
2523 (Type { referenced: a, .. }, Type { referenced: b, .. }) => {
2524 self.component_any_type_id(*a, *b, offset)
2525 }
2526 (Type { .. }, b) => bail!(offset, "expected {}, found type", b.desc()),
2527
2528 (Instance(a), Instance(b)) => self.component_instance_type(*a, *b, offset),
2529 (Instance(_), b) => bail!(offset, "expected {}, found instance", b.desc()),
2530
2531 (Component(a), Component(b)) => self.component_type(*a, *b, offset),
2532 (Component(_), b) => bail!(offset, "expected {}, found component", b.desc()),
2533 }
2534 }
2535
2536 /// Tests whether `a` is a subtype of `b`.
2537 ///
2538 /// Errors are reported at the `offset` specified.
2539 pub fn component_type(
2540 &mut self,
2541 a: ComponentTypeId,
2542 b: ComponentTypeId,
2543 offset: usize,
2544 ) -> Result<()> {
2545 // Components are ... tricky. They follow the same basic
2546 // structure as core wasm modules, but they also have extra
2547 // logic to handle resource types. Resources are effectively
2548 // abstract types so this is sort of where an ML module system
2549 // in the component model becomes a reality.
2550 //
2551 // This also leverages the `open_instance_type` method below
2552 // heavily which internally has its own quite large suite of
2553 // logic. More-or-less what's happening here is:
2554 //
2555 // 1. Pretend that the imports of B are given as values to the
2556 // imports of A. If A didn't import anything, for example,
2557 // that's great and the subtyping definitely passes there.
2558 // This operation produces a mapping of all the resources of
2559 // A's imports to resources in B's imports.
2560 //
2561 // 2. This mapping is applied to all of A's exports. This means
2562 // that all exports of A referring to A's imported resources
2563 // now instead refer to B's. Note, though that A's exports
2564 // still refer to its own defined resources.
2565 //
2566 // 3. The same `open_instance_type` method used during the
2567 // first step is used again, but this time on the exports
2568 // in the reverse direction. This performs a similar
2569 // operation, though, by creating a mapping from B's
2570 // defined resources to A's defined resources. The map
2571 // itself is discarded as it's not needed.
2572 //
2573 // The order that everything passed here is intentional, but
2574 // also subtle. I personally think of it as
2575 // `open_instance_type` takes a list of things to satisfy a
2576 // signature and produces a mapping of resources in the
2577 // signature to those provided in the list of things. The
2578 // order of operations then goes:
2579 //
2580 // * Someone thinks they have a component of type B, but they
2581 // actually have a component of type A (e.g. due to this
2582 // subtype check passing).
2583 // * This person provides the imports of B and that must be
2584 // sufficient to satisfy the imports of A. This is the first
2585 // `open_instance_type` check.
2586 // * Now though the resources provided by B are substituted
2587 // into A's exports since that's what was provided.
2588 // * A's exports are then handed back to the original person,
2589 // and these exports must satisfy the signature required by B
2590 // since that's what they're expecting.
2591 // * This is the second `open_instance_type` which, to get
2592 // resource types to line up, will map from A's defined
2593 // resources to B's defined resources.
2594 //
2595 // If all that passes then the resources should all line up
2596 // perfectly. Any misalignment is reported as a subtyping
2597 // error.
2598 let b_imports = self.b[b]
2599 .imports
2600 .iter()
2601 .map(|(name, ty)| (name.clone(), *ty))
2602 .collect();
2603 self.swap();
2604 let mut import_mapping =
2605 self.open_instance_type(&b_imports, a, ExternKind::Import, offset)?;
2606 self.swap();
2607 self.with_checkpoint(|this| {
2608 let mut a_exports = this.a[a]
2609 .exports
2610 .iter()
2611 .map(|(name, ty)| (name.clone(), *ty))
2612 .collect::<IndexMap<_, _>>();
2613 for ty in a_exports.values_mut() {
2614 this.a.remap_component_entity(ty, &mut import_mapping);
2615 }
2616 this.open_instance_type(&a_exports, b, ExternKind::Export, offset)?;
2617 Ok(())
2618 })
2619 }
2620
2621 /// Tests whether `a` is a subtype of `b`.
2622 ///
2623 /// Errors are reported at the `offset` specified.
2624 pub fn component_instance_type(
2625 &mut self,
2626 a_id: ComponentInstanceTypeId,
2627 b_id: ComponentInstanceTypeId,
2628 offset: usize,
2629 ) -> Result<()> {
2630 // For instance type subtyping, all exports in the other
2631 // instance type must be present in this instance type's
2632 // exports (i.e. it can export *more* than what this instance
2633 // type needs).
2634 let a = &self.a[a_id];
2635 let b = &self.b[b_id];
2636
2637 let mut exports = Vec::with_capacity(b.exports.len());
2638 for (k, b) in b.exports.iter() {
2639 match a.exports.get(k) {
2640 Some(a) => exports.push((*a, *b)),
2641 None => bail!(offset, "missing expected export `{k}`"),
2642 }
2643 }
2644 for (i, (a, b)) in exports.iter().enumerate() {
2645 let err = match self.component_entity_type(a, b, offset) {
2646 Ok(()) => continue,
2647 Err(e) => e,
2648 };
2649 // On failure attach the name of this export as context to
2650 // the error message to leave a breadcrumb trail.
2651 let (name, _) = self.b[b_id].exports.get_index(i).unwrap();
2652 return Err(err.with_context(|| format!("type mismatch in instance export `{name}`")));
2653 }
2654 Ok(())
2655 }
2656
2657 /// Tests whether `a` is a subtype of `b`.
2658 ///
2659 /// Errors are reported at the `offset` specified.
2660 pub fn component_func_type(
2661 &mut self,
2662 a: ComponentFuncTypeId,
2663 b: ComponentFuncTypeId,
2664 offset: usize,
2665 ) -> Result<()> {
2666 let a = &self.a[a];
2667 let b = &self.b[b];
2668
2669 // Note that this intentionally diverges from the upstream
2670 // specification in terms of subtyping. This is a full
2671 // type-equality check which ensures that the structure of `a`
2672 // exactly matches the structure of `b`. The rationale for this
2673 // is:
2674 //
2675 // * Primarily in Wasmtime subtyping based on function types is
2676 // not implemented. This includes both subtyping a host
2677 // import and additionally handling subtyping as functions
2678 // cross component boundaries. The host import subtyping (or
2679 // component export subtyping) is not clear how to handle at
2680 // all at this time. The subtyping of functions between
2681 // components can more easily be handled by extending the
2682 // `fact` compiler, but that hasn't been done yet.
2683 //
2684 // * The upstream specification is currently pretty
2685 // intentionally vague precisely what subtyping is allowed.
2686 // Implementing a strict check here is intended to be a
2687 // conservative starting point for the component model which
2688 // can be extended in the future if necessary.
2689 //
2690 // * The interaction with subtyping on bindings generation, for
2691 // example, is a tricky problem that doesn't have a clear
2692 // answer at this time. Effectively this is more rationale
2693 // for being conservative in the first pass of the component
2694 // model.
2695 //
2696 // So, in conclusion, the test here (and other places that
2697 // reference this comment) is for exact type equality with no
2698 // differences.
2699 if a.params.len() != b.params.len() {
2700 bail!(
2701 offset,
2702 "expected {} parameters, found {}",
2703 b.params.len(),
2704 a.params.len(),
2705 );
2706 }
2707 if a.results.len() != b.results.len() {
2708 bail!(
2709 offset,
2710 "expected {} results, found {}",
2711 b.results.len(),
2712 a.results.len(),
2713 );
2714 }
2715 for ((an, a), (bn, b)) in a.params.iter().zip(b.params.iter()) {
2716 if an != bn {
2717 bail!(offset, "expected parameter named `{bn}`, found `{an}`");
2718 }
2719 self.component_val_type(a, b, offset)
2720 .with_context(|| format!("type mismatch in function parameter `{an}`"))?;
2721 }
2722 for ((an, a), (bn, b)) in a.results.iter().zip(b.results.iter()) {
2723 if an != bn {
2724 bail!(offset, "mismatched result names");
2725 }
2726 self.component_val_type(a, b, offset)
2727 .with_context(|| "type mismatch with result type")?;
2728 }
2729 Ok(())
2730 }
2731
2732 /// Tests whether `a` is a subtype of `b`.
2733 ///
2734 /// Errors are reported at the `offset` specified.
2735 pub fn module_type(
2736 &mut self,
2737 a: ComponentCoreModuleTypeId,
2738 b: ComponentCoreModuleTypeId,
2739 offset: usize,
2740 ) -> Result<()> {
2741 // For module type subtyping, all exports in the other module
2742 // type must be present in this module type's exports (i.e. it
2743 // can export *more* than what this module type needs).
2744 // However, for imports, the check is reversed (i.e. it is okay
2745 // to import *less* than what this module type needs).
2746 self.swap();
2747 let a_imports = &self.b[a].imports;
2748 let b_imports = &self.a[b].imports;
2749 for (k, a) in a_imports {
2750 match b_imports.get(k) {
2751 Some(b) => self
2752 .entity_type(b, a, offset)
2753 .with_context(|| format!("type mismatch in import `{}::{}`", k.0, k.1))?,
2754 None => bail!(offset, "missing expected import `{}::{}`", k.0, k.1),
2755 }
2756 }
2757 self.swap();
2758 let a = &self.a[a];
2759 let b = &self.b[b];
2760 for (k, b) in b.exports.iter() {
2761 match a.exports.get(k) {
2762 Some(a) => self
2763 .entity_type(a, b, offset)
2764 .with_context(|| format!("type mismatch in export `{k}`"))?,
2765 None => bail!(offset, "missing expected export `{k}`"),
2766 }
2767 }
2768 Ok(())
2769 }
2770
2771 /// Tests whether `a` is a subtype of `b`.
2772 ///
2773 /// Errors are reported at the `offset` specified.
2774 pub fn component_any_type_id(
2775 &mut self,
2776 a: ComponentAnyTypeId,
2777 b: ComponentAnyTypeId,
2778 offset: usize,
2779 ) -> Result<()> {
2780 match (a, b) {
2781 (ComponentAnyTypeId::Resource(a), ComponentAnyTypeId::Resource(b)) => {
2782 if a.resource() == b.resource() {
2783 Ok(())
2784 } else {
2785 bail!(
2786 offset,
2787 "resource types are not the same ({:?} vs. {:?})",
2788 a.resource(),
2789 b.resource()
2790 )
2791 }
2792 }
2793 (ComponentAnyTypeId::Resource(_), b) => {
2794 bail!(offset, "expected {}, found resource", b.desc())
2795 }
2796 (ComponentAnyTypeId::Defined(a), ComponentAnyTypeId::Defined(b)) => {
2797 self.component_defined_type(a, b, offset)
2798 }
2799 (ComponentAnyTypeId::Defined(_), b) => {
2800 bail!(offset, "expected {}, found defined type", b.desc())
2801 }
2802
2803 (ComponentAnyTypeId::Func(a), ComponentAnyTypeId::Func(b)) => {
2804 self.component_func_type(a, b, offset)
2805 }
2806 (ComponentAnyTypeId::Func(_), b) => {
2807 bail!(offset, "expected {}, found func type", b.desc())
2808 }
2809
2810 (ComponentAnyTypeId::Instance(a), ComponentAnyTypeId::Instance(b)) => {
2811 self.component_instance_type(a, b, offset)
2812 }
2813 (ComponentAnyTypeId::Instance(_), b) => {
2814 bail!(offset, "expected {}, found instance type", b.desc())
2815 }
2816
2817 (ComponentAnyTypeId::Component(a), ComponentAnyTypeId::Component(b)) => {
2818 self.component_type(a, b, offset)
2819 }
2820 (ComponentAnyTypeId::Component(_), b) => {
2821 bail!(offset, "expected {}, found component type", b.desc())
2822 }
2823 }
2824 }
2825
2826 /// The building block for subtyping checks when components are
2827 /// instantiated and when components are tested if they're subtypes of each
2828 /// other.
2829 ///
2830 /// This method takes a number of arguments:
2831 ///
2832 /// * `a` - this is a list of typed items which can be thought of as
2833 /// concrete values to test against `b`.
2834 /// * `b` - this `TypeId` must point to `Type::Component`.
2835 /// * `kind` - indicates whether the `imports` or `exports` of `b` are
2836 /// being tested against for the values in `a`.
2837 /// * `offset` - the binary offset at which to report errors if one happens.
2838 ///
2839 /// This will attempt to determine if the items in `a` satisfy the
2840 /// signature required by the `kind` items of `b`. For example component
2841 /// instantiation will have `a` as the list of arguments provided to
2842 /// instantiation, `b` is the component being instantiated, and `kind` is
2843 /// `ExternKind::Import`.
2844 ///
2845 /// This function, if successful, will return a mapping of the resources in
2846 /// `b` to the resources in `a` provided. This mapping is guaranteed to
2847 /// contain all the resources for `b` (all imported resources for
2848 /// `ExternKind::Import` or all defined resources for `ExternKind::Export`).
2849 pub fn open_instance_type(
2850 &mut self,
2851 a: &IndexMap<String, ComponentEntityType>,
2852 b: ComponentTypeId,
2853 kind: ExternKind,
2854 offset: usize,
2855 ) -> Result<Remapping> {
2856 // First, determine the mapping from resources in `b` to those supplied
2857 // by arguments in `a`.
2858 //
2859 // This loop will iterate over all the appropriate resources in `b`
2860 // and find the corresponding resource in `args`. The exact lists
2861 // in use here depend on the `kind` provided. This necessarily requires
2862 // a sequence of string lookups to find the corresponding items in each
2863 // list.
2864 //
2865 // The path to each resource in `resources` is precomputed as a list of
2866 // indexes. The first index is into `b`'s list of `entities`, and gives
2867 // the name that `b` assigns to the resource. Each subsequent index,
2868 // if present, means that this resource was present through a layer of
2869 // an instance type, and the index is into the instance type's exports.
2870 // More information about this can be found on
2871 // `ComponentState::imported_resources`.
2872 //
2873 // This loop will follow the list of indices for each resource and, at
2874 // the same time, walk through the arguments supplied to instantiating
2875 // the `component_type`. This means that within `component_type`
2876 // index-based lookups are performed while in `args` name-based
2877 // lookups are performed.
2878 //
2879 // Note that here it's possible that `args` doesn't actually supply the
2880 // correct type of import for each item since argument checking has
2881 // not proceeded yet. These type errors, however, aren't handled by
2882 // this loop and are deferred below to the main subtyping check. That
2883 // means that `mapping` won't necessarily have a mapping for all
2884 // imported resources into `component_type`, but that should be ok.
2885 let component_type = &self.b[b];
2886 let entities = match kind {
2887 ExternKind::Import => &component_type.imports,
2888 ExternKind::Export => &component_type.exports,
2889 };
2890 let resources = match kind {
2891 ExternKind::Import => &component_type.imported_resources,
2892 ExternKind::Export => &component_type.defined_resources,
2893 };
2894 let mut mapping = Remapping::default();
2895 'outer: for (resource, path) in resources.iter() {
2896 // Lookup the first path item in `imports` and the corresponding
2897 // entry in `args` by name.
2898 let (name, ty) = entities.get_index(path[0]).unwrap();
2899 let mut ty = *ty;
2900 let mut arg = a.get(name);
2901
2902 // Lookup all the subsequent `path` entries, if any, by index in
2903 // `ty` and by name in `arg`. Type errors in `arg` are skipped over
2904 // entirely.
2905 for i in path.iter().skip(1).copied() {
2906 let id = match ty {
2907 ComponentEntityType::Instance(id) => id,
2908 _ => unreachable!(),
2909 };
2910 let (name, next_ty) = self.b[id].exports.get_index(i).unwrap();
2911 ty = *next_ty;
2912 arg = match arg {
2913 Some(ComponentEntityType::Instance(id)) => self.a[*id].exports.get(name),
2914 _ => continue 'outer,
2915 };
2916 }
2917
2918 // Double-check that `ty`, the leaf type of `component_type`, is
2919 // indeed the expected resource.
2920 if cfg!(debug_assertions) {
2921 let id = match ty {
2922 ComponentEntityType::Type { created, .. } => match created {
2923 ComponentAnyTypeId::Resource(id) => id.resource(),
2924 _ => unreachable!(),
2925 },
2926 _ => unreachable!(),
2927 };
2928 assert_eq!(id, *resource);
2929 }
2930
2931 // The leaf of `arg` should be a type which is a resource. If not
2932 // it's skipped and this'll wind up generating an error later on in
2933 // subtype checking below.
2934 if let Some(ComponentEntityType::Type { created, .. }) = arg {
2935 if let ComponentAnyTypeId::Resource(r) = created {
2936 mapping.resources.insert(*resource, r.resource());
2937 }
2938 }
2939 }
2940
2941 // Now that a mapping from the resources in `b` to the resources in `a`
2942 // has been determined it's possible to perform the actual subtype
2943 // check.
2944 //
2945 // This subtype check notably needs to ensure that all resource types
2946 // line up. To achieve this the `mapping` previously calculated is used
2947 // to perform a substitution on each component entity type.
2948 //
2949 // The first loop here performs a name lookup to create a list of
2950 // values from `a` to expected items in `b`. Once the list is created
2951 // the substitution check is performed on each element.
2952 let mut to_typecheck = Vec::new();
2953 for (name, expected) in entities.iter() {
2954 match a.get(name) {
2955 Some(arg) => to_typecheck.push((*arg, *expected)),
2956 None => bail!(offset, "missing {} named `{name}`", kind.desc()),
2957 }
2958 }
2959 let mut type_map = Map::default();
2960 for (i, (actual, expected)) in to_typecheck.into_iter().enumerate() {
2961 let result = self.with_checkpoint(|this| {
2962 let mut expected = expected;
2963 this.b.remap_component_entity(&mut expected, &mut mapping);
2964 mapping.types.clear();
2965 this.component_entity_type(&actual, &expected, offset)
2966 });
2967 let err = match result {
2968 Ok(()) => {
2969 // On a successful type-check record a mapping of
2970 // type-to-type in `type_map` for any type imports that were
2971 // satisfied. This is then used afterwards when performing
2972 // type substitution to remap all component-local types to
2973 // those that were provided in the imports.
2974 self.register_type_renamings(actual, expected, &mut type_map);
2975 continue;
2976 }
2977 Err(e) => e,
2978 };
2979
2980 // If an error happens then attach the name of the entity to the
2981 // error message using the `i` iteration counter.
2982 let component_type = &self.b[b];
2983 let entities = match kind {
2984 ExternKind::Import => &component_type.imports,
2985 ExternKind::Export => &component_type.exports,
2986 };
2987 let (name, _) = entities.get_index(i).unwrap();
2988 return Err(err.with_context(|| format!("type mismatch for {} `{name}`", kind.desc())));
2989 }
2990 mapping.types = type_map;
2991 Ok(mapping)
2992 }
2993
2994 pub(crate) fn entity_type(&self, a: &EntityType, b: &EntityType, offset: usize) -> Result<()> {
2995 macro_rules! limits_match {
2996 ($a:expr, $b:expr) => {{
2997 let a = $a;
2998 let b = $b;
2999 a.initial >= b.initial
3000 && match b.maximum {
3001 Some(b_max) => match a.maximum {
3002 Some(a_max) => a_max <= b_max,
3003 None => false,
3004 },
3005 None => true,
3006 }
3007 }};
3008 }
3009
3010 match (a, b) {
3011 (EntityType::Func(a), EntityType::Func(b)) => {
3012 self.core_func_type(self.a[*a].unwrap_func(), self.b[*b].unwrap_func(), offset)
3013 }
3014 (EntityType::Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3015 (EntityType::Table(a), EntityType::Table(b)) => {
3016 if a.element_type != b.element_type {
3017 bail!(
3018 offset,
3019 "expected table element type {}, found {}",
3020 b.element_type,
3021 a.element_type,
3022 )
3023 }
3024 if limits_match!(a, b) {
3025 Ok(())
3026 } else {
3027 bail!(offset, "mismatch in table limits")
3028 }
3029 }
3030 (EntityType::Table(_), b) => bail!(offset, "expected {}, found table", b.desc()),
3031 (EntityType::Memory(a), EntityType::Memory(b)) => {
3032 if a.shared != b.shared {
3033 bail!(offset, "mismatch in the shared flag for memories")
3034 }
3035 if a.memory64 != b.memory64 {
3036 bail!(offset, "mismatch in index type used for memories")
3037 }
3038 if limits_match!(a, b) {
3039 Ok(())
3040 } else {
3041 bail!(offset, "mismatch in memory limits")
3042 }
3043 }
3044 (EntityType::Memory(_), b) => bail!(offset, "expected {}, found memory", b.desc()),
3045 (EntityType::Global(a), EntityType::Global(b)) => {
3046 if a.mutable != b.mutable {
3047 bail!(offset, "global types differ in mutability")
3048 }
3049 if a.content_type == b.content_type {
3050 Ok(())
3051 } else {
3052 bail!(
3053 offset,
3054 "expected global type {}, found {}",
3055 b.content_type,
3056 a.content_type,
3057 )
3058 }
3059 }
3060 (EntityType::Global(_), b) => bail!(offset, "expected {}, found global", b.desc()),
3061 (EntityType::Tag(a), EntityType::Tag(b)) => {
3062 self.core_func_type(self.a[*a].unwrap_func(), self.b[*b].unwrap_func(), offset)
3063 }
3064 (EntityType::Tag(_), b) => bail!(offset, "expected {}, found tag", b.desc()),
3065 }
3066 }
3067
3068 fn core_func_type(&self, a: &FuncType, b: &FuncType, offset: usize) -> Result<()> {
3069 if a == b {
3070 Ok(())
3071 } else {
3072 bail!(
3073 offset,
3074 "expected: {}\n\
3075 found: {}",
3076 b.desc(),
3077 a.desc(),
3078 )
3079 }
3080 }
3081
3082 pub(crate) fn component_val_type(
3083 &self,
3084 a: &ComponentValType,
3085 b: &ComponentValType,
3086 offset: usize,
3087 ) -> Result<()> {
3088 match (a, b) {
3089 (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
3090 self.primitive_val_type(*a, *b, offset)
3091 }
3092 (ComponentValType::Type(a), ComponentValType::Type(b)) => {
3093 self.component_defined_type(*a, *b, offset)
3094 }
3095 (ComponentValType::Primitive(a), ComponentValType::Type(b)) => match &self.b[*b] {
3096 ComponentDefinedType::Primitive(b) => self.primitive_val_type(*a, *b, offset),
3097 b => bail!(offset, "expected {}, found {a}", b.desc()),
3098 },
3099 (ComponentValType::Type(a), ComponentValType::Primitive(b)) => match &self.a[*a] {
3100 ComponentDefinedType::Primitive(a) => self.primitive_val_type(*a, *b, offset),
3101 a => bail!(offset, "expected {b}, found {}", a.desc()),
3102 },
3103 }
3104 }
3105
3106 fn component_defined_type(
3107 &self,
3108 a: ComponentDefinedTypeId,
3109 b: ComponentDefinedTypeId,
3110 offset: usize,
3111 ) -> Result<()> {
3112 use ComponentDefinedType::*;
3113
3114 // Note that the implementation of subtyping here diverges from the
3115 // upstream specification intentionally, see the documentation on
3116 // function subtyping for more information.
3117 match (&self.a[a], &self.b[b]) {
3118 (Primitive(a), Primitive(b)) => self.primitive_val_type(*a, *b, offset),
3119 (Primitive(a), b) => bail!(offset, "expected {}, found {a}", b.desc()),
3120 (Record(a), Record(b)) => {
3121 if a.fields.len() != b.fields.len() {
3122 bail!(
3123 offset,
3124 "expected {} fields, found {}",
3125 b.fields.len(),
3126 a.fields.len(),
3127 );
3128 }
3129
3130 for ((aname, a), (bname, b)) in a.fields.iter().zip(b.fields.iter()) {
3131 if aname != bname {
3132 bail!(offset, "expected field name `{bname}`, found `{aname}`");
3133 }
3134 self.component_val_type(a, b, offset)
3135 .with_context(|| format!("type mismatch in record field `{aname}`"))?;
3136 }
3137 Ok(())
3138 }
3139 (Record(_), b) => bail!(offset, "expected {}, found record", b.desc()),
3140 (Variant(a), Variant(b)) => {
3141 if a.cases.len() != b.cases.len() {
3142 bail!(
3143 offset,
3144 "expected {} cases, found {}",
3145 b.cases.len(),
3146 a.cases.len(),
3147 );
3148 }
3149 for ((aname, a), (bname, b)) in a.cases.iter().zip(b.cases.iter()) {
3150 if aname != bname {
3151 bail!(offset, "expected case named `{bname}`, found `{aname}`");
3152 }
3153 match (&a.ty, &b.ty) {
3154 (Some(a), Some(b)) => self
3155 .component_val_type(a, b, offset)
3156 .with_context(|| format!("type mismatch in variant case `{aname}`"))?,
3157 (None, None) => {}
3158 (None, Some(_)) => {
3159 bail!(offset, "expected case `{aname}` to have a type, found none")
3160 }
3161 (Some(_), None) => bail!(offset, "expected case `{aname}` to have no type"),
3162 }
3163 }
3164 Ok(())
3165 }
3166 (Variant(_), b) => bail!(offset, "expected {}, found variant", b.desc()),
3167 (List(a), List(b)) | (Option(a), Option(b)) => self.component_val_type(a, b, offset),
3168 (List(_), b) => bail!(offset, "expected {}, found list", b.desc()),
3169 (Option(_), b) => bail!(offset, "expected {}, found option", b.desc()),
3170 (Tuple(a), Tuple(b)) => {
3171 if a.types.len() != b.types.len() {
3172 bail!(
3173 offset,
3174 "expected {} types, found {}",
3175 b.types.len(),
3176 a.types.len(),
3177 );
3178 }
3179 for (i, (a, b)) in a.types.iter().zip(b.types.iter()).enumerate() {
3180 self.component_val_type(a, b, offset)
3181 .with_context(|| format!("type mismatch in tuple field {i}"))?;
3182 }
3183 Ok(())
3184 }
3185 (Tuple(_), b) => bail!(offset, "expected {}, found tuple", b.desc()),
3186 (at @ Flags(a), Flags(b)) | (at @ Enum(a), Enum(b)) => {
3187 let desc = match at {
3188 Flags(_) => "flags",
3189 _ => "enum",
3190 };
3191 if a.len() == b.len() && a.iter().eq(b.iter()) {
3192 Ok(())
3193 } else {
3194 bail!(offset, "mismatch in {desc} elements")
3195 }
3196 }
3197 (Flags(_), b) => bail!(offset, "expected {}, found flags", b.desc()),
3198 (Enum(_), b) => bail!(offset, "expected {}, found enum", b.desc()),
3199 (Result { ok: ao, err: ae }, Result { ok: bo, err: be }) => {
3200 match (ao, bo) {
3201 (None, None) => {}
3202 (Some(a), Some(b)) => self
3203 .component_val_type(a, b, offset)
3204 .with_context(|| "type mismatch in ok variant")?,
3205 (None, Some(_)) => bail!(offset, "expected ok type, but found none"),
3206 (Some(_), None) => bail!(offset, "expected ok type to not be present"),
3207 }
3208 match (ae, be) {
3209 (None, None) => {}
3210 (Some(a), Some(b)) => self
3211 .component_val_type(a, b, offset)
3212 .with_context(|| "type mismatch in err variant")?,
3213 (None, Some(_)) => bail!(offset, "expected err type, but found none"),
3214 (Some(_), None) => bail!(offset, "expected err type to not be present"),
3215 }
3216 Ok(())
3217 }
3218 (Result { .. }, b) => bail!(offset, "expected {}, found result", b.desc()),
3219 (Own(a), Own(b)) | (Borrow(a), Borrow(b)) => {
3220 if a.resource() == b.resource() {
3221 Ok(())
3222 } else {
3223 bail!(offset, "resource types are not the same")
3224 }
3225 }
3226 (Own(_), b) => bail!(offset, "expected {}, found own", b.desc()),
3227 (Borrow(_), b) => bail!(offset, "expected {}, found borrow", b.desc()),
3228 (Future(a), Future(b)) => match (a, b) {
3229 (None, None) => Ok(()),
3230 (Some(a), Some(b)) => self
3231 .component_val_type(a, b, offset)
3232 .with_context(|| "type mismatch in future"),
3233 (None, Some(_)) => bail!(offset, "expected future type, but found none"),
3234 (Some(_), None) => bail!(offset, "expected future type to not be present"),
3235 },
3236 (Future(_), b) => bail!(offset, "expected {}, found future", b.desc()),
3237 (Stream(a), Stream(b)) => self
3238 .component_val_type(a, b, offset)
3239 .with_context(|| "type mismatch in stream"),
3240 (Stream(_), b) => bail!(offset, "expected {}, found stream", b.desc()),
3241 (ErrorContext, ErrorContext) => Ok(()),
3242 (ErrorContext, b) => bail!(offset, "expected {}, found error-context", b.desc()),
3243 }
3244 }
3245
3246 fn primitive_val_type(
3247 &self,
3248 a: PrimitiveValType,
3249 b: PrimitiveValType,
3250 offset: usize,
3251 ) -> Result<()> {
3252 // Note that this intentionally diverges from the upstream specification
3253 // at this time and only considers exact equality for subtyping
3254 // relationships.
3255 //
3256 // More information can be found in the subtyping implementation for
3257 // component functions.
3258 if a == b {
3259 Ok(())
3260 } else {
3261 bail!(offset, "expected primitive `{b}` found primitive `{a}`")
3262 }
3263 }
3264
3265 fn register_type_renamings(
3266 &self,
3267 actual: ComponentEntityType,
3268 expected: ComponentEntityType,
3269 type_map: &mut Map<ComponentAnyTypeId, ComponentAnyTypeId>,
3270 ) {
3271 match (expected, actual) {
3272 (
3273 ComponentEntityType::Type {
3274 created: expected, ..
3275 },
3276 ComponentEntityType::Type {
3277 created: actual, ..
3278 },
3279 ) => {
3280 let prev = type_map.insert(expected, actual);
3281 assert!(prev.is_none());
3282 }
3283 (ComponentEntityType::Instance(expected), ComponentEntityType::Instance(actual)) => {
3284 let actual = &self.a[actual];
3285 for (name, expected) in self.b[expected].exports.iter() {
3286 let actual = actual.exports[name];
3287 self.register_type_renamings(actual, *expected, type_map);
3288 }
3289 }
3290 _ => {}
3291 }
3292 }
3293}
3294
3295/// A helper typed used purely during subtyping as part of `SubtypeCx`.
3296///
3297/// This takes a `types` list as input which is the "base" of the ids that can
3298/// be indexed through this arena. All future types pushed into this, if any,
3299/// are stored in `self.list`.
3300///
3301/// This is intended to have arena-like behavior where everything pushed onto
3302/// `self.list` is thrown away after a subtyping computation is performed. All
3303/// new types pushed into this arena are purely temporary.
3304pub struct SubtypeArena<'a> {
3305 types: &'a TypeList,
3306 list: TypeList,
3307}
3308
3309impl<'a> SubtypeArena<'a> {
3310 fn new(types: &'a TypeList) -> SubtypeArena<'a> {
3311 SubtypeArena {
3312 types,
3313 list: TypeList::default(),
3314 }
3315 }
3316}
3317
3318impl<T> Index<T> for SubtypeArena<'_>
3319where
3320 T: TypeIdentifier,
3321{
3322 type Output = T::Data;
3323
3324 fn index(&self, id: T) -> &T::Data {
3325 let index: usize = id.index();
3326 if index < T::list(self.types).len() {
3327 &self.types[id]
3328 } else {
3329 let temp_index: usize = index - T::list(self.types).len();
3330 let temp_index: u32 = u32::try_from(temp_index).unwrap();
3331 let temp_id: T = T::from_index(temp_index);
3332 &self.list[temp_id]
3333 }
3334 }
3335}
3336
3337impl Remap for SubtypeArena<'_> {
3338 fn push_ty<T>(&mut self, ty: T) -> T::Id
3339 where
3340 T: TypeData,
3341 {
3342 let index: usize = T::Id::list(&self.list).len() + T::Id::list(self.types).len();
3343 let index: u32 = u32::try_from(index).unwrap();
3344 self.list.push(ty);
3345 T::Id::from_index(index)
3346 }
3347}
3348
3349/// Helper trait for adding contextual information to an error, modeled after
3350/// `anyhow::Context`.
3351pub(crate) trait Context {
3352 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
3353 where
3354 S: Into<String>;
3355}
3356
3357impl<T> Context for Result<T> {
3358 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
3359 where
3360 S: Into<String>,
3361 {
3362 match self {
3363 Ok(val: T) => Ok(val),
3364 Err(e: BinaryReaderError) => Err(e.with_context(context)),
3365 }
3366 }
3367}
3368
3369impl Context for BinaryReaderError {
3370 fn with_context<S>(mut self, context: impl FnOnce() -> S) -> Self
3371 where
3372 S: Into<String>,
3373 {
3374 self.add_context(context().into());
3375 self
3376 }
3377}
3378