wasmparser/validator/
component.rs

1//! State relating to validating a WebAssembly component.
2
3use super::{
4    check_max,
5    component_types::{
6        Abi, AliasableResourceId, ComponentAnyTypeId, ComponentCoreInstanceTypeId,
7        ComponentCoreModuleTypeId, ComponentCoreTypeId, ComponentDefinedType,
8        ComponentDefinedTypeId, ComponentEntityType, ComponentFuncType, ComponentFuncTypeId,
9        ComponentInstanceType, ComponentInstanceTypeId, ComponentType, ComponentTypeId,
10        ComponentValType, Context, CoreInstanceTypeKind, InstanceType, ModuleType, RecordType,
11        Remap, Remapping, ResourceId, SubtypeCx, TupleType, VariantCase, VariantType,
12    },
13    core::{InternRecGroup, Module},
14    types::{CoreTypeId, EntityType, TypeAlloc, TypeInfo, TypeList},
15};
16use crate::collections::index_map::Entry;
17use crate::limits::*;
18use crate::prelude::*;
19use crate::validator::names::{ComponentName, ComponentNameKind, KebabStr, KebabString};
20use crate::{
21    BinaryReaderError, CanonicalFunction, CanonicalOption, ComponentExportName,
22    ComponentExternalKind, ComponentOuterAliasKind, ComponentTypeRef, CompositeInnerType,
23    ExternalKind, FuncType, GlobalType, InstantiationArgKind, MemoryType, PackedIndex, RefType,
24    Result, SubType, TableType, TypeBounds, ValType, WasmFeatures,
25};
26use core::mem;
27
28fn to_kebab_str<'a>(s: &'a str, desc: &str, offset: usize) -> Result<&'a KebabStr> {
29    match KebabStr::new(s) {
30        Some(s) => Ok(s),
31        None => {
32            if s.is_empty() {
33                bail!(offset, "{desc} name cannot be empty");
34            }
35
36            bail!(offset, "{desc} name `{s}` is not in kebab case");
37        }
38    }
39}
40
41pub(crate) struct ComponentState {
42    /// Whether this state is a concrete component, an instance type, or a
43    /// component type.
44    kind: ComponentKind,
45    features: WasmFeatures,
46
47    // Core index spaces
48    pub core_types: Vec<ComponentCoreTypeId>,
49    pub core_funcs: Vec<CoreTypeId>,
50    pub core_tags: Vec<CoreTypeId>,
51    pub core_modules: Vec<ComponentCoreModuleTypeId>,
52    pub core_instances: Vec<ComponentCoreInstanceTypeId>,
53    pub core_memories: Vec<MemoryType>,
54    pub core_tables: Vec<TableType>,
55    pub core_globals: Vec<GlobalType>,
56
57    // Component index spaces
58    pub types: Vec<ComponentAnyTypeId>,
59    pub funcs: Vec<ComponentFuncTypeId>,
60    pub values: Vec<(ComponentValType, bool)>,
61    pub instances: Vec<ComponentInstanceTypeId>,
62    pub components: Vec<ComponentTypeId>,
63
64    pub imports: IndexMap<String, ComponentEntityType>,
65    pub import_names: IndexSet<ComponentName>,
66    pub exports: IndexMap<String, ComponentEntityType>,
67    pub export_names: IndexSet<ComponentName>,
68
69    has_start: bool,
70    type_info: TypeInfo,
71
72    /// A mapping of imported resources in this component.
73    ///
74    /// This mapping represents all "type variables" imported into the
75    /// component, or resources. This could be resources imported directly as
76    /// a top-level type import or additionally transitively through other
77    /// imported instances.
78    ///
79    /// The mapping element here is a "path" which is a list of indexes into
80    /// the import map that will be generated for this component. Each index
81    /// is an index into an `IndexMap`, and each list is guaranteed to have at
82    /// least one element.
83    ///
84    /// An example of this map is:
85    ///
86    /// ```wasm
87    /// (component
88    ///     ;; [0] - the first import
89    ///     (import "r" (type (sub resource)))
90    ///
91    ///     ;; [1] - the second import
92    ///     (import "r2" (type (sub resource)))
93    ///
94    ///     (import "i" (instance
95    ///         ;; [2, 0] - the third import, and the first export the instance
96    ///         (export "r3" (type (sub resource)))
97    ///         ;; [2, 1] - the third import, and the second export the instance
98    ///         (export "r4" (type (sub resource)))
99    ///     ))
100    ///
101    ///     ;; ...
102    /// )
103    /// ```
104    ///
105    /// The `Vec<usize>` here can be thought of as `Vec<String>` but a
106    /// (hopefully) more efficient representation.
107    ///
108    /// Finally note that this map is listed as an "append only" map because all
109    /// insertions into it should always succeed. Any insertion which overlaps
110    /// with a previous entry indicates a bug in the validator which needs to be
111    /// corrected via other means.
112    //
113    // TODO: make these `SkolemResourceId` and then go fix all the compile
114    // errors, don't add skolem things into the type area
115    imported_resources: IndexMapAppendOnly<ResourceId, Vec<usize>>,
116
117    /// A mapping of "defined" resources in this component, or those which
118    /// are defined within the instantiation of this component.
119    ///
120    /// Defined resources, as the name implies, can sort of be thought of as
121    /// "these are defined within the component". Note though that the means by
122    /// which a local definition can occur are not simply those defined in the
123    /// component but also in its transitively instantiated components
124    /// internally. This means that this set closes over many transitive
125    /// internal items in addition to those defined immediately in the component
126    /// itself.
127    ///
128    /// The `Option<ValType>` in this mapping is whether or not the underlying
129    /// representation of the resource is known to this component. Immediately
130    /// defined resources, for example, will have `Some(I32)` here. Resources
131    /// that come from transitively defined components, for example, will have
132    /// `None`. In the type context all entries here are `None`.
133    ///
134    /// Note that like `imported_resources` all insertions into this map are
135    /// expected to succeed to it's declared as append-only.
136    defined_resources: IndexMapAppendOnly<ResourceId, Option<ValType>>,
137
138    /// A mapping of explicitly exported resources from this component in
139    /// addition to the path that they're exported at.
140    ///
141    /// For more information on the path here see the documentation for
142    /// `imported_resources`. Note that the indexes here index into the
143    /// list of exports of this component.
144    explicit_resources: IndexMap<ResourceId, Vec<usize>>,
145
146    /// The set of types which are considered "exported" from this component.
147    ///
148    /// This is added to whenever a type export is found, or an instance export
149    /// which itself contains a type export. This additionally includes all
150    /// imported types since those are suitable for export as well.
151    ///
152    /// This set is consulted whenever an exported item is added since all
153    /// referenced types must be members of this set.
154    exported_types: Set<ComponentAnyTypeId>,
155
156    /// Same as `exported_types`, but for imports.
157    imported_types: Set<ComponentAnyTypeId>,
158
159    /// The set of top-level resource exports and their names.
160    ///
161    /// This context is used to validate method names such as `[method]foo.bar`
162    /// to ensure that `foo` is an exported resource and that the type mentioned
163    /// in a function type is actually named `foo`.
164    ///
165    /// Note that imports/exports have disjoint contexts to ensure that they're
166    /// validated correctly. Namely you can't retroactively attach methods to an
167    /// import, for example.
168    toplevel_exported_resources: ComponentNameContext,
169
170    /// Same as `toplevel_exported_resources`, but for imports.
171    toplevel_imported_resources: ComponentNameContext,
172}
173
174#[derive(Copy, Clone, Debug, PartialEq, Eq)]
175pub enum ComponentKind {
176    Component,
177    InstanceType,
178    ComponentType,
179}
180
181/// Helper context used to track information about resource names for method
182/// name validation.
183#[derive(Default)]
184struct ComponentNameContext {
185    /// A map from a resource type id to an index in the `all_resource_names`
186    /// set for the name of that resource.
187    resource_name_map: Map<AliasableResourceId, usize>,
188
189    /// All known resource names in this context, used to validate static method
190    /// names to by ensuring that static methods' resource names are somewhere
191    /// in this set.
192    all_resource_names: IndexSet<String>,
193}
194
195#[derive(Debug, Copy, Clone)]
196pub enum ExternKind {
197    Import,
198    Export,
199}
200
201impl ExternKind {
202    pub fn desc(&self) -> &'static str {
203        match self {
204            ExternKind::Import => "import",
205            ExternKind::Export => "export",
206        }
207    }
208}
209
210#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
211pub(crate) enum StringEncoding {
212    #[default]
213    Utf8,
214    Utf16,
215    CompactUtf16,
216}
217
218impl core::fmt::Display for StringEncoding {
219    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
220        f.write_str(match self {
221            Self::Utf8 => "utf8",
222            Self::Utf16 => "utf16",
223            Self::CompactUtf16 => "latin1-utf16",
224        })
225    }
226}
227
228#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
229pub(crate) enum Concurrency {
230    /// Synchronous.
231    #[default]
232    Sync,
233
234    /// Asynchronous.
235    Async {
236        /// When present, this is the function index of the async callback. When
237        /// omitted, we are either using stack-switching based asynchrony or are
238        /// in an operation that does not support the `callback` option (like
239        /// lowering).
240        callback: Option<u32>,
241    },
242}
243
244impl Concurrency {
245    pub(crate) fn is_sync(&self) -> bool {
246        matches!(self, Self::Sync)
247    }
248
249    pub(crate) fn is_async(&self) -> bool {
250        !self.is_sync()
251    }
252}
253
254#[derive(Clone, Copy)]
255pub(crate) struct CanonicalOptions {
256    pub(crate) string_encoding: StringEncoding,
257    pub(crate) memory: Option<u32>,
258    pub(crate) realloc: Option<u32>,
259    pub(crate) post_return: Option<u32>,
260    pub(crate) concurrency: Concurrency,
261    pub(crate) core_type: Option<CoreTypeId>,
262    pub(crate) gc: bool,
263}
264
265impl CanonicalOptions {
266    pub(crate) fn require_sync(&self, offset: usize, where_: &str) -> Result<&Self> {
267        if !self.concurrency.is_sync() {
268            bail!(offset, "cannot specify `async` option on `{where_}`")
269        }
270        Ok(self)
271    }
272
273    pub(crate) fn require_memory(&self, offset: usize) -> Result<&Self> {
274        if self.memory.is_none() {
275            bail!(offset, "canonical option `memory` is required");
276        }
277        Ok(self)
278    }
279
280    pub(crate) fn require_realloc(&self, offset: usize) -> Result<&Self> {
281        // Memory is always required when `realloc` is required.
282        self.require_memory(offset)?;
283
284        if self.realloc.is_none() {
285            bail!(offset, "canonical option `realloc` is required")
286        }
287
288        Ok(self)
289    }
290
291    pub(crate) fn require_memory_if(
292        &self,
293        offset: usize,
294        when: impl Fn() -> bool,
295    ) -> Result<&Self> {
296        if self.memory.is_none() && when() {
297            self.require_memory(offset)?;
298        }
299        Ok(self)
300    }
301
302    pub(crate) fn require_realloc_if(
303        &self,
304        offset: usize,
305        when: impl Fn() -> bool,
306    ) -> Result<&Self> {
307        if self.realloc.is_none() && when() {
308            self.require_realloc(offset)?;
309        }
310        Ok(self)
311    }
312
313    pub(crate) fn check_lower(&self, offset: usize) -> Result<&Self> {
314        if self.post_return.is_some() {
315            bail!(
316                offset,
317                "canonical option `post-return` cannot be specified for lowerings"
318            );
319        }
320
321        if let Concurrency::Async { callback: Some(_) } = self.concurrency {
322            bail!(
323                offset,
324                "canonical option `callback` cannot be specified for lowerings"
325            );
326        }
327
328        if self.gc && self.core_type.is_none() {
329            bail!(
330                offset,
331                "cannot specify `gc` without also specifying a `core-type` for lowerings"
332            )
333        }
334
335        Ok(self)
336    }
337
338    pub(crate) fn check_lift(
339        &mut self,
340        types: &TypeList,
341        state: &ComponentState,
342        core_ty_id: CoreTypeId,
343        offset: usize,
344    ) -> Result<&Self> {
345        debug_assert!(matches!(
346            types[core_ty_id].composite_type.inner,
347            CompositeInnerType::Func(_)
348        ));
349
350        if let Some(idx) = self.post_return {
351            let post_return_func_ty = types[state.core_function_at(idx, offset)?].unwrap_func();
352            let core_ty = types[core_ty_id].unwrap_func();
353            if post_return_func_ty.params() != core_ty.results()
354                || !post_return_func_ty.results().is_empty()
355            {
356                bail!(
357                    offset,
358                    "canonical option `post-return` uses a core function with an incorrect signature"
359                );
360            }
361        }
362
363        match self.concurrency {
364            Concurrency::Sync => {}
365
366            Concurrency::Async { callback: None } if !state.features.cm_async_stackful() => {
367                bail!(
368                    offset,
369                    "requires the component model async stackful feature"
370                )
371            }
372            Concurrency::Async { callback: None } => {}
373
374            Concurrency::Async {
375                callback: Some(idx),
376            } => {
377                let func_ty = types[state.core_function_at(idx, offset)?].unwrap_func();
378                if func_ty.params() != [ValType::I32; 3] && func_ty.params() != [ValType::I32] {
379                    return Err(BinaryReaderError::new(
380                        "canonical option `callback` uses a core function with an incorrect signature",
381                        offset,
382                    ));
383                }
384            }
385        }
386
387        if self.core_type.is_some() {
388            bail!(
389                offset,
390                "canonical option `core-type` is not allowed in `canon lift`"
391            )
392        }
393        self.core_type = Some(core_ty_id);
394
395        Ok(self)
396    }
397
398    pub(crate) fn check_core_type(
399        &self,
400        types: &mut TypeAlloc,
401        actual: FuncType,
402        offset: usize,
403    ) -> Result<CoreTypeId> {
404        if let Some(declared_id) = self.core_type {
405            let declared = types[declared_id].unwrap_func();
406
407            if actual.params() != declared.params() {
408                bail!(
409                    offset,
410                    "declared core type has `{:?}` parameter types, but actual lowering has \
411                     `{:?}` parameter types",
412                    declared.params(),
413                    actual.params(),
414                );
415            }
416
417            if actual.results() != declared.results() {
418                bail!(
419                    offset,
420                    "declared core type has `{:?}` result types, but actual lowering has \
421                     `{:?}` result types",
422                    declared.results(),
423                    actual.results(),
424                );
425            }
426
427            Ok(declared_id)
428        } else {
429            Ok(types.intern_func_type(actual, offset))
430        }
431    }
432}
433
434impl ComponentState {
435    pub fn new(kind: ComponentKind, features: WasmFeatures) -> Self {
436        Self {
437            kind,
438            features,
439            core_types: Default::default(),
440            core_modules: Default::default(),
441            core_instances: Default::default(),
442            core_funcs: Default::default(),
443            core_memories: Default::default(),
444            core_tables: Default::default(),
445            core_globals: Default::default(),
446            core_tags: Default::default(),
447            types: Default::default(),
448            funcs: Default::default(),
449            values: Default::default(),
450            instances: Default::default(),
451            components: Default::default(),
452            imports: Default::default(),
453            exports: Default::default(),
454            import_names: Default::default(),
455            export_names: Default::default(),
456            has_start: Default::default(),
457            type_info: TypeInfo::new(),
458            imported_resources: Default::default(),
459            defined_resources: Default::default(),
460            explicit_resources: Default::default(),
461            exported_types: Default::default(),
462            imported_types: Default::default(),
463            toplevel_exported_resources: Default::default(),
464            toplevel_imported_resources: Default::default(),
465        }
466    }
467
468    pub fn type_count(&self) -> usize {
469        self.core_types.len() + self.types.len()
470    }
471
472    pub fn instance_count(&self) -> usize {
473        self.core_instances.len() + self.instances.len()
474    }
475
476    pub fn function_count(&self) -> usize {
477        self.core_funcs.len() + self.funcs.len()
478    }
479
480    pub fn add_core_type(
481        components: &mut [Self],
482        ty: crate::CoreType,
483        types: &mut TypeAlloc,
484        offset: usize,
485        check_limit: bool,
486    ) -> Result<()> {
487        let current = components.last_mut().unwrap();
488        if check_limit {
489            check_max(current.type_count(), 1, MAX_WASM_TYPES, "types", offset)?;
490        }
491        match ty {
492            crate::CoreType::Rec(rec) => {
493                current.canonicalize_and_intern_rec_group(types, rec, offset)?;
494            }
495            crate::CoreType::Module(decls) => {
496                let mod_ty = Self::create_module_type(components, decls.into_vec(), types, offset)?;
497                let id = ComponentCoreTypeId::Module(types.push_ty(mod_ty));
498                components.last_mut().unwrap().core_types.push(id);
499            }
500        }
501
502        Ok(())
503    }
504
505    pub fn add_core_module(
506        &mut self,
507        module: &Module,
508        types: &mut TypeAlloc,
509        offset: usize,
510    ) -> Result<()> {
511        let imports = module.imports_for_module_type(offset)?;
512
513        // We have to clone the module's imports and exports here
514        // because we cannot take the data out of the `MaybeOwned`
515        // as it might be shared with a function validator.
516        let mod_ty = ModuleType {
517            info: TypeInfo::core(module.type_size),
518            imports,
519            exports: module.exports.clone(),
520        };
521
522        let mod_id = types.push_ty(mod_ty);
523        self.core_modules.push(mod_id);
524
525        Ok(())
526    }
527
528    pub fn add_core_instance(
529        &mut self,
530        instance: crate::Instance,
531        types: &mut TypeAlloc,
532        offset: usize,
533    ) -> Result<()> {
534        let instance = match instance {
535            crate::Instance::Instantiate { module_index, args } => {
536                self.instantiate_core_module(module_index, args.into_vec(), types, offset)?
537            }
538            crate::Instance::FromExports(exports) => {
539                self.instantiate_core_exports(exports.into_vec(), types, offset)?
540            }
541        };
542
543        self.core_instances.push(instance);
544
545        Ok(())
546    }
547
548    pub fn add_type(
549        components: &mut Vec<Self>,
550        ty: crate::ComponentType,
551        types: &mut TypeAlloc,
552        offset: usize,
553        check_limit: bool,
554    ) -> Result<()> {
555        assert!(!components.is_empty());
556
557        fn current(components: &mut Vec<ComponentState>) -> &mut ComponentState {
558            components.last_mut().unwrap()
559        }
560
561        let id = match ty {
562            crate::ComponentType::Defined(ty) => {
563                let ty = current(components).create_defined_type(ty, types, offset)?;
564                types.push(ty).into()
565            }
566            crate::ComponentType::Func(ty) => {
567                let ty = current(components).create_function_type(ty, types, offset)?;
568                types.push(ty).into()
569            }
570            crate::ComponentType::Component(decls) => {
571                let ty = Self::create_component_type(components, decls.into_vec(), types, offset)?;
572                types.push(ty).into()
573            }
574            crate::ComponentType::Instance(decls) => {
575                let ty = Self::create_instance_type(components, decls.into_vec(), types, offset)?;
576                types.push(ty).into()
577            }
578            crate::ComponentType::Resource { rep, dtor } => {
579                let component = current(components);
580
581                // Resource types cannot be declared in a type context, only
582                // within a component context.
583                if component.kind != ComponentKind::Component {
584                    bail!(
585                        offset,
586                        "resources can only be defined within a concrete component"
587                    );
588                }
589
590                // Current MVP restriction of the component model.
591                if rep != ValType::I32 {
592                    bail!(offset, "resources can only be represented by `i32`");
593                }
594
595                // If specified validate that the destructor is both a valid
596                // function and has the correct signature.
597                if let Some(dtor) = dtor {
598                    let ty = component.core_function_at(dtor, offset)?;
599                    let ty = types[ty].composite_type.unwrap_func();
600                    if ty.params() != [rep] || ty.results() != [] {
601                        bail!(
602                            offset,
603                            "core function {dtor} has wrong signature for a destructor"
604                        );
605                    }
606                }
607
608                // As this is the introduction of a resource create a fresh new
609                // identifier for the resource. This is then added into the
610                // list of defined resources for this component, notably with a
611                // rep listed to enable getting access to various intrinsics
612                // such as `resource.rep`.
613                let id = types.alloc_resource_id();
614                component.defined_resources.insert(id.resource(), Some(rep));
615                id.into()
616            }
617        };
618
619        let current = current(components);
620        if check_limit {
621            check_max(current.type_count(), 1, MAX_WASM_TYPES, "types", offset)?;
622        }
623        current.types.push(id);
624
625        Ok(())
626    }
627
628    pub fn add_import(
629        &mut self,
630        import: crate::ComponentImport,
631        types: &mut TypeAlloc,
632        offset: usize,
633    ) -> Result<()> {
634        let mut entity = self.check_type_ref(&import.ty, types, offset)?;
635        self.add_entity(
636            &mut entity,
637            Some((import.name.0, ExternKind::Import)),
638            types,
639            offset,
640        )?;
641        self.toplevel_imported_resources.validate_extern(
642            import.name.0,
643            ExternKind::Import,
644            &entity,
645            types,
646            offset,
647            &mut self.import_names,
648            &mut self.imports,
649            &mut self.type_info,
650            &self.features,
651        )?;
652        Ok(())
653    }
654
655    fn add_entity(
656        &mut self,
657        ty: &mut ComponentEntityType,
658        name_and_kind: Option<(&str, ExternKind)>,
659        types: &mut TypeAlloc,
660        offset: usize,
661    ) -> Result<()> {
662        let kind = name_and_kind.map(|(_, k)| k);
663        let (len, max, desc) = match ty {
664            ComponentEntityType::Module(id) => {
665                self.core_modules.push(*id);
666                (self.core_modules.len(), MAX_WASM_MODULES, "modules")
667            }
668            ComponentEntityType::Component(id) => {
669                self.components.push(*id);
670                (self.components.len(), MAX_WASM_COMPONENTS, "components")
671            }
672            ComponentEntityType::Instance(id) => {
673                match kind {
674                    Some(ExternKind::Import) => self.prepare_instance_import(id, types),
675                    Some(ExternKind::Export) => self.prepare_instance_export(id, types),
676                    None => {}
677                }
678                self.instances.push(*id);
679                (self.instance_count(), MAX_WASM_INSTANCES, "instances")
680            }
681            ComponentEntityType::Func(id) => {
682                self.funcs.push(*id);
683                (self.function_count(), MAX_WASM_FUNCTIONS, "functions")
684            }
685            ComponentEntityType::Value(ty) => {
686                self.check_value_support(offset)?;
687                let value_used = match kind {
688                    Some(ExternKind::Import) | None => false,
689                    Some(ExternKind::Export) => true,
690                };
691                self.values.push((*ty, value_used));
692                (self.values.len(), MAX_WASM_VALUES, "values")
693            }
694            ComponentEntityType::Type {
695                created,
696                referenced,
697            } => {
698                self.types.push(*created);
699
700                // Extra logic here for resources being imported and exported.
701                // Note that if `created` is the same as `referenced` then this
702                // is the original introduction of the resource which is where
703                // `self.{imported,defined}_resources` are updated.
704                if let ComponentAnyTypeId::Resource(id) = *created {
705                    match kind {
706                        Some(ExternKind::Import) => {
707                            // A fresh new resource is being imported into a
708                            // component. This arises from the import section of
709                            // a component or from the import declaration in a
710                            // component type. In both cases a new imported
711                            // resource is injected with a fresh new identifier
712                            // into our state.
713                            if created == referenced {
714                                self.imported_resources
715                                    .insert(id.resource(), vec![self.imports.len()]);
716                            }
717                        }
718
719                        Some(ExternKind::Export) => {
720                            // A fresh resource is being exported from this
721                            // component. This arises as part of the
722                            // declaration of a component type, for example. In
723                            // this situation brand new resource identifier is
724                            // allocated and a definition is added, unlike the
725                            // import case where an imported resource is added.
726                            // Notably the representation of this new resource
727                            // is unknown so it's listed as `None`.
728                            if created == referenced {
729                                self.defined_resources.insert(id.resource(), None);
730                            }
731
732                            // If this is a type export of a resource type then
733                            // update the `explicit_resources` list. A new
734                            // export path is about to be created for this
735                            // resource and this keeps track of that.
736                            self.explicit_resources
737                                .insert(id.resource(), vec![self.exports.len()]);
738                        }
739
740                        None => {}
741                    }
742                }
743                (self.types.len(), MAX_WASM_TYPES, "types")
744            }
745        };
746
747        check_max(len, 0, max, desc, offset)?;
748
749        // Before returning perform the final validation of the type of the item
750        // being imported/exported. This will ensure that everything is
751        // appropriately named with respect to type definitions, resources, etc.
752        if let Some((name, kind)) = name_and_kind {
753            if !self.validate_and_register_named_types(Some(name), kind, ty, types) {
754                bail!(
755                    offset,
756                    "{} not valid to be used as {}",
757                    ty.desc(),
758                    kind.desc()
759                );
760            }
761        }
762        Ok(())
763    }
764
765    /// Validates that the `ty` referenced only refers to named types internally
766    /// and then inserts anything necessary, if applicable, to the defined sets
767    /// within this component.
768    ///
769    /// This function will validate that `ty` only refers to named types. For
770    /// example if it's a record then all of its fields must refer to named
771    /// types. This consults either `self.imported_types` or
772    /// `self.exported_types` as specified by `kind`. Note that this is not
773    /// inherently recursive itself but it ends up being recursive since if
774    /// recursive members were named then all their components must also be
775    /// named. Consequently this check stops at the "one layer deep" position,
776    /// or more accurately the position where types must be named (e.g. tuples
777    /// aren't required to be named).
778    fn validate_and_register_named_types(
779        &mut self,
780        toplevel_name: Option<&str>,
781        kind: ExternKind,
782        ty: &ComponentEntityType,
783        types: &TypeAlloc,
784    ) -> bool {
785        if let ComponentEntityType::Type { created, .. } = ty {
786            // If this is a top-level resource then register it in the
787            // appropriate context so later validation of method-like-names
788            // works out.
789            if let Some(name) = toplevel_name {
790                if let ComponentAnyTypeId::Resource(id) = *created {
791                    let cx = match kind {
792                        ExternKind::Import => &mut self.toplevel_imported_resources,
793                        ExternKind::Export => &mut self.toplevel_exported_resources,
794                    };
795                    cx.register(name, id);
796                }
797            }
798        }
799
800        match self.kind {
801            ComponentKind::Component | ComponentKind::ComponentType => {}
802            ComponentKind::InstanceType => return true,
803        }
804        let set = match kind {
805            ExternKind::Import => &self.imported_types,
806            ExternKind::Export => &self.exported_types,
807        };
808        match ty {
809            // When a type is imported or exported than any recursive type
810            // referred to by that import/export must additionally be exported
811            // or imported. Here this walks the "first layer" of the type which
812            // delegates to `TypeAlloc::type_named_type_id` to determine whether
813            // the components of the type being named here are indeed all they
814            // themselves named.
815            ComponentEntityType::Type {
816                created,
817                referenced,
818            } => {
819                if !self.all_valtypes_named(types, *referenced, set) {
820                    return false;
821                }
822                match kind {
823                    // Imported types are both valid for import and valid for
824                    // export.
825                    ExternKind::Import => {
826                        self.imported_types.insert(*created);
827                        self.exported_types.insert(*created);
828                    }
829                    ExternKind::Export => {
830                        self.exported_types.insert(*created);
831                    }
832                }
833
834                true
835            }
836
837            // Instances are slightly nuanced here. The general idea is that if
838            // an instance is imported, then any type exported by the instance
839            // is then also exported. Additionally for exports. To get this to
840            // work out this arm will recursively call
841            // `validate_and_register_named_types` which means that types are
842            // inserted into `self.{imported,exported}_types` as-we-go rather
843            // than all at once.
844            //
845            // This then recursively validates that all items in the instance
846            // itself are valid to import/export, recursive instances are
847            // captured, and everything is appropriately added to the right
848            // imported/exported set.
849            ComponentEntityType::Instance(i) => types[*i]
850                .exports
851                .iter()
852                .all(|(_name, ty)| self.validate_and_register_named_types(None, kind, ty, types)),
853
854            // All types referred to by a function must be named.
855            ComponentEntityType::Func(id) => self.all_valtypes_named_in_func(types, *id, set),
856
857            ComponentEntityType::Value(ty) => types.type_named_valtype(ty, set),
858
859            // Components/modules are always "closed" or "standalone" and don't
860            // need validation with respect to their named types.
861            ComponentEntityType::Component(_) | ComponentEntityType::Module(_) => true,
862        }
863    }
864
865    fn all_valtypes_named(
866        &self,
867        types: &TypeAlloc,
868        id: ComponentAnyTypeId,
869        set: &Set<ComponentAnyTypeId>,
870    ) -> bool {
871        match id {
872            // Resource types, in isolation, are always valid to import or
873            // export since they're either attached to an import or being
874            // exported.
875            //
876            // Note that further validation of this happens in `finish`, too.
877            ComponentAnyTypeId::Resource(_) => true,
878
879            // Component types are validated as they are constructed,
880            // so all component types are valid to export if they've
881            // already been constructed.
882            ComponentAnyTypeId::Component(_) => true,
883
884            ComponentAnyTypeId::Defined(id) => self.all_valtypes_named_in_defined(types, id, set),
885            ComponentAnyTypeId::Func(id) => self.all_valtypes_named_in_func(types, id, set),
886            ComponentAnyTypeId::Instance(id) => self.all_valtypes_named_in_instance(types, id, set),
887        }
888    }
889
890    fn all_valtypes_named_in_instance(
891        &self,
892        types: &TypeAlloc,
893        id: ComponentInstanceTypeId,
894        set: &Set<ComponentAnyTypeId>,
895    ) -> bool {
896        // Instances must recursively have all referenced types named.
897        let ty = &types[id];
898        ty.exports.values().all(|ty| match ty {
899            ComponentEntityType::Module(_) => true,
900            ComponentEntityType::Func(id) => self.all_valtypes_named_in_func(types, *id, set),
901            ComponentEntityType::Type { created: id, .. } => {
902                self.all_valtypes_named(types, *id, set)
903            }
904            ComponentEntityType::Value(ComponentValType::Type(id)) => {
905                self.all_valtypes_named_in_defined(types, *id, set)
906            }
907            ComponentEntityType::Instance(id) => {
908                self.all_valtypes_named_in_instance(types, *id, set)
909            }
910            ComponentEntityType::Component(_)
911            | ComponentEntityType::Value(ComponentValType::Primitive(_)) => return true,
912        })
913    }
914
915    fn all_valtypes_named_in_defined(
916        &self,
917        types: &TypeAlloc,
918        id: ComponentDefinedTypeId,
919        set: &Set<ComponentAnyTypeId>,
920    ) -> bool {
921        let ty = &types[id];
922        match ty {
923            // These types do not contain anything which must be
924            // named.
925            ComponentDefinedType::Primitive(_)
926            | ComponentDefinedType::Flags(_)
927            | ComponentDefinedType::Enum(_) => true,
928
929            // Referenced types of all these aggregates must all be
930            // named.
931            ComponentDefinedType::Record(r) => {
932                r.fields.values().all(|t| types.type_named_valtype(t, set))
933            }
934            ComponentDefinedType::Tuple(r) => {
935                r.types.iter().all(|t| types.type_named_valtype(t, set))
936            }
937            ComponentDefinedType::Variant(r) => r
938                .cases
939                .values()
940                .filter_map(|t| t.ty.as_ref())
941                .all(|t| types.type_named_valtype(t, set)),
942            ComponentDefinedType::Result { ok, err } => {
943                ok.as_ref()
944                    .map(|t| types.type_named_valtype(t, set))
945                    .unwrap_or(true)
946                    && err
947                        .as_ref()
948                        .map(|t| types.type_named_valtype(t, set))
949                        .unwrap_or(true)
950            }
951            ComponentDefinedType::List(ty)
952            | ComponentDefinedType::FixedSizeList(ty, _)
953            | ComponentDefinedType::Option(ty) => types.type_named_valtype(ty, set),
954
955            // The resource referred to by own/borrow must be named.
956            ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
957                set.contains(&ComponentAnyTypeId::from(*id))
958            }
959
960            ComponentDefinedType::Future(ty) => ty
961                .as_ref()
962                .map(|ty| types.type_named_valtype(ty, set))
963                .unwrap_or(true),
964            ComponentDefinedType::Stream(ty) => ty
965                .as_ref()
966                .map(|ty| types.type_named_valtype(ty, set))
967                .unwrap_or(true),
968        }
969    }
970
971    fn all_valtypes_named_in_func(
972        &self,
973        types: &TypeAlloc,
974        id: ComponentFuncTypeId,
975        set: &Set<ComponentAnyTypeId>,
976    ) -> bool {
977        let ty = &types[id];
978        // Function types must have all their parameters/results named.
979        ty.params
980            .iter()
981            .map(|(_, ty)| ty)
982            .chain(&ty.result)
983            .all(|ty| types.type_named_valtype(ty, set))
984    }
985
986    /// Updates the type `id` specified, an identifier for a component instance
987    /// type, to be imported into this component.
988    ///
989    /// Importing an instance type into a component specially handles the
990    /// defined resources registered in the instance type. Notably all
991    /// defined resources are "freshened" into brand new type variables and
992    /// these new variables are substituted within the type. This is what
993    /// creates a new `TypeId` and may update the `id` specified.
994    ///
995    /// One side effect of this operation, for example, is that if an instance
996    /// type is used twice to import two different instances then the instances
997    /// do not share resource types despite sharing the same original instance
998    /// type.
999    fn prepare_instance_import(&mut self, id: &mut ComponentInstanceTypeId, types: &mut TypeAlloc) {
1000        let ty = &types[*id];
1001
1002        // No special treatment for imports of instances which themselves have
1003        // no defined resources
1004        if ty.defined_resources.is_empty() {
1005            return;
1006        }
1007
1008        let mut new_ty = ComponentInstanceType {
1009            // Copied from the input verbatim
1010            info: ty.info,
1011
1012            // Copied over as temporary storage for now, and both of these are
1013            // filled out and expanded below.
1014            exports: ty.exports.clone(),
1015            explicit_resources: ty.explicit_resources.clone(),
1016
1017            // Explicitly discard this field since the
1018            // defined resources are lifted into `self`
1019            defined_resources: Default::default(),
1020        };
1021
1022        // Create brand new resources for all defined ones in the instance.
1023        let resources = (0..ty.defined_resources.len())
1024            .map(|_| types.alloc_resource_id())
1025            .collect::<IndexSet<_>>();
1026
1027        // Build a map from the defined resources in `ty` to those in `new_ty`.
1028        //
1029        // As part of this same loop the new resources, which were previously
1030        // defined in `ty`, now become imported variables in `self`. Their
1031        // path for where they're imported is updated as well with
1032        // `self.next_import_index` as the import-to-be soon.
1033        let mut mapping = Remapping::default();
1034        let ty = &types[*id];
1035        for (old, new) in ty.defined_resources.iter().zip(&resources) {
1036            let prev = mapping.resources.insert(*old, new.resource());
1037            assert!(prev.is_none());
1038
1039            let mut base = vec![self.imports.len()];
1040            base.extend(ty.explicit_resources[old].iter().copied());
1041            self.imported_resources.insert(new.resource(), base);
1042        }
1043
1044        // Using the old-to-new resource mapping perform a substitution on
1045        // the `exports` and `explicit_resources` fields of `new_ty`
1046        for ty in new_ty.exports.values_mut() {
1047            types.remap_component_entity(ty, &mut mapping);
1048        }
1049        for (id, path) in mem::take(&mut new_ty.explicit_resources) {
1050            let id = *mapping.resources.get(&id).unwrap_or(&id);
1051            new_ty.explicit_resources.insert(id, path);
1052        }
1053
1054        // Now that `new_ty` is complete finish its registration and then
1055        // update `id` on the way out.
1056        *id = types.push_ty(new_ty);
1057    }
1058
1059    /// Prepares an instance type, pointed to `id`, for being exported as a
1060    /// concrete instance from `self`.
1061    ///
1062    /// This will internally perform any resource "freshening" as required and
1063    /// then additionally update metadata within `self` about resources being
1064    /// exported or defined.
1065    fn prepare_instance_export(&mut self, id: &mut ComponentInstanceTypeId, types: &mut TypeAlloc) {
1066        // Exports of an instance mean that the enclosing context
1067        // is inheriting the resources that the instance
1068        // encapsulates. This means that the instance type
1069        // recorded for this export will itself have no
1070        // defined resources.
1071        let ty = &types[*id];
1072
1073        // Check to see if `defined_resources` is non-empty, and if so then
1074        // "freshen" all the resources and inherit them to our own defined
1075        // resources, updating `id` in the process.
1076        //
1077        // Note though that this specifically is not rewriting the resources of
1078        // exported instances. The `defined_resources` set on instance types is
1079        // a little subtle (see its documentation for more info), but the
1080        // general idea is that for a concrete instance it's always empty. Only
1081        // for instance type definitions does it ever have elements in it.
1082        //
1083        // That means that if this set is non-empty then what's happening is
1084        // that we're in a type context an exporting an instance of a previously
1085        // specified type. In this case all resources are required to be
1086        // "freshened" to ensure that multiple exports of the same type all
1087        // export different types of resources.
1088        //
1089        // And finally note that this operation empties out the
1090        // `defined_resources` set of the type that is registered for the
1091        // instance, as this export is modeled as producing a concrete instance.
1092        if !ty.defined_resources.is_empty() {
1093            let mut new_ty = ty.clone();
1094            let mut mapping = Remapping::default();
1095            for old in mem::take(&mut new_ty.defined_resources) {
1096                let new = types.alloc_resource_id();
1097                mapping.resources.insert(old, new.resource());
1098                self.defined_resources.insert(new.resource(), None);
1099            }
1100            for ty in new_ty.exports.values_mut() {
1101                types.remap_component_entity(ty, &mut mapping);
1102            }
1103            for (id, path) in mem::take(&mut new_ty.explicit_resources) {
1104                let id = mapping.resources.get(&id).copied().unwrap_or(id);
1105                new_ty.explicit_resources.insert(id, path);
1106            }
1107            *id = types.push_ty(new_ty);
1108        }
1109
1110        // Any explicit resources in the instance are now additionally explicit
1111        // in this component since it's exported.
1112        //
1113        // The path to each explicit resources gets one element prepended which
1114        // is `self.next_export_index`, the index of the export about to be
1115        // generated.
1116        let ty = &types[*id];
1117        for (id, path) in ty.explicit_resources.iter() {
1118            let mut new_path = vec![self.exports.len()];
1119            new_path.extend(path);
1120            self.explicit_resources.insert(*id, new_path);
1121        }
1122    }
1123
1124    pub fn add_export(
1125        &mut self,
1126        name: ComponentExportName<'_>,
1127        mut ty: ComponentEntityType,
1128        types: &mut TypeAlloc,
1129        offset: usize,
1130        check_limit: bool,
1131    ) -> Result<()> {
1132        if check_limit {
1133            check_max(self.exports.len(), 1, MAX_WASM_EXPORTS, "exports", offset)?;
1134        }
1135        self.add_entity(&mut ty, Some((name.0, ExternKind::Export)), types, offset)?;
1136        self.toplevel_exported_resources.validate_extern(
1137            name.0,
1138            ExternKind::Export,
1139            &ty,
1140            types,
1141            offset,
1142            &mut self.export_names,
1143            &mut self.exports,
1144            &mut self.type_info,
1145            &self.features,
1146        )?;
1147        Ok(())
1148    }
1149
1150    pub fn canonical_function(
1151        &mut self,
1152        func: CanonicalFunction,
1153        types: &mut TypeAlloc,
1154        offset: usize,
1155    ) -> Result<()> {
1156        match func {
1157            CanonicalFunction::Lift {
1158                core_func_index,
1159                type_index,
1160                options,
1161            } => self.lift_function(core_func_index, type_index, &options, types, offset),
1162            CanonicalFunction::Lower {
1163                func_index,
1164                options,
1165            } => self.lower_function(func_index, &options, types, offset),
1166            CanonicalFunction::ResourceNew { resource } => {
1167                self.resource_new(resource, types, offset)
1168            }
1169            CanonicalFunction::ResourceDrop { resource } => {
1170                self.resource_drop(resource, types, offset)
1171            }
1172            CanonicalFunction::ResourceDropAsync { resource } => {
1173                self.resource_drop_async(resource, types, offset)
1174            }
1175            CanonicalFunction::ResourceRep { resource } => {
1176                self.resource_rep(resource, types, offset)
1177            }
1178            CanonicalFunction::ThreadSpawnRef { func_ty_index } => {
1179                self.thread_spawn_ref(func_ty_index, types, offset)
1180            }
1181            CanonicalFunction::ThreadSpawnIndirect {
1182                func_ty_index,
1183                table_index,
1184            } => self.thread_spawn_indirect(func_ty_index, table_index, types, offset),
1185            CanonicalFunction::ThreadAvailableParallelism => {
1186                self.thread_available_parallelism(types, offset)
1187            }
1188            CanonicalFunction::BackpressureSet => self.backpressure_set(types, offset),
1189            CanonicalFunction::BackpressureInc => self.backpressure_inc(types, offset),
1190            CanonicalFunction::BackpressureDec => self.backpressure_dec(types, offset),
1191            CanonicalFunction::TaskReturn { result, options } => {
1192                self.task_return(&result, &options, types, offset)
1193            }
1194            CanonicalFunction::TaskCancel => self.task_cancel(types, offset),
1195            CanonicalFunction::ContextGet(i) => self.context_get(i, types, offset),
1196            CanonicalFunction::ContextSet(i) => self.context_set(i, types, offset),
1197            CanonicalFunction::ThreadYield { cancellable } => {
1198                self.thread_yield(cancellable, types, offset)
1199            }
1200            CanonicalFunction::SubtaskDrop => self.subtask_drop(types, offset),
1201            CanonicalFunction::SubtaskCancel { async_ } => {
1202                self.subtask_cancel(async_, types, offset)
1203            }
1204            CanonicalFunction::StreamNew { ty } => self.stream_new(ty, types, offset),
1205            CanonicalFunction::StreamRead { ty, options } => {
1206                self.stream_read(ty, &options, types, offset)
1207            }
1208            CanonicalFunction::StreamWrite { ty, options } => {
1209                self.stream_write(ty, &options, types, offset)
1210            }
1211            CanonicalFunction::StreamCancelRead { ty, async_ } => {
1212                self.stream_cancel_read(ty, async_, types, offset)
1213            }
1214            CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1215                self.stream_cancel_write(ty, async_, types, offset)
1216            }
1217            CanonicalFunction::StreamDropReadable { ty } => {
1218                self.stream_drop_readable(ty, types, offset)
1219            }
1220            CanonicalFunction::StreamDropWritable { ty } => {
1221                self.stream_drop_writable(ty, types, offset)
1222            }
1223            CanonicalFunction::FutureNew { ty } => self.future_new(ty, types, offset),
1224            CanonicalFunction::FutureRead { ty, options } => {
1225                self.future_read(ty, &options, types, offset)
1226            }
1227            CanonicalFunction::FutureWrite { ty, options } => {
1228                self.future_write(ty, options.into_vec(), types, offset)
1229            }
1230            CanonicalFunction::FutureCancelRead { ty, async_ } => {
1231                self.future_cancel_read(ty, async_, types, offset)
1232            }
1233            CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1234                self.future_cancel_write(ty, async_, types, offset)
1235            }
1236            CanonicalFunction::FutureDropReadable { ty } => {
1237                self.future_drop_readable(ty, types, offset)
1238            }
1239            CanonicalFunction::FutureDropWritable { ty } => {
1240                self.future_drop_writable(ty, types, offset)
1241            }
1242            CanonicalFunction::ErrorContextNew { options } => {
1243                self.error_context_new(options.into_vec(), types, offset)
1244            }
1245            CanonicalFunction::ErrorContextDebugMessage { options } => {
1246                self.error_context_debug_message(options.into_vec(), types, offset)
1247            }
1248            CanonicalFunction::ErrorContextDrop => self.error_context_drop(types, offset),
1249            CanonicalFunction::WaitableSetNew => self.waitable_set_new(types, offset),
1250            CanonicalFunction::WaitableSetWait {
1251                cancellable,
1252                memory,
1253            } => self.waitable_set_wait(cancellable, memory, types, offset),
1254            CanonicalFunction::WaitableSetPoll {
1255                cancellable,
1256                memory,
1257            } => self.waitable_set_poll(cancellable, memory, types, offset),
1258            CanonicalFunction::WaitableSetDrop => self.waitable_set_drop(types, offset),
1259            CanonicalFunction::WaitableJoin => self.waitable_join(types, offset),
1260            CanonicalFunction::ThreadIndex => self.thread_index(types, offset),
1261            CanonicalFunction::ThreadNewIndirect {
1262                func_ty_index,
1263                table_index,
1264            } => self.thread_new_indirect(func_ty_index, table_index, types, offset),
1265            CanonicalFunction::ThreadSwitchTo { cancellable } => {
1266                self.thread_switch_to(cancellable, types, offset)
1267            }
1268            CanonicalFunction::ThreadSuspend { cancellable } => {
1269                self.thread_suspend(cancellable, types, offset)
1270            }
1271            CanonicalFunction::ThreadResumeLater => self.thread_resume_later(types, offset),
1272
1273            CanonicalFunction::ThreadYieldTo { cancellable } => {
1274                self.thread_yield_to(cancellable, types, offset)
1275            }
1276        }
1277    }
1278
1279    fn lift_function(
1280        &mut self,
1281        core_func_index: u32,
1282        type_index: u32,
1283        options: &[CanonicalOption],
1284        types: &mut TypeAlloc,
1285        offset: usize,
1286    ) -> Result<()> {
1287        let ty = self.function_type_at(type_index, types, offset)?;
1288        let core_ty_id = self.core_function_at(core_func_index, offset)?;
1289
1290        // Lifting a function is for an export, so match the expected canonical ABI
1291        // export signature
1292        let mut options = self.check_options(types, options, offset)?;
1293        options.check_lift(types, self, core_ty_id, offset)?;
1294        let func_ty = ty.lower(types, &options, Abi::Lift, offset)?;
1295        let lowered_core_ty_id = func_ty.intern(types, offset);
1296
1297        if core_ty_id == lowered_core_ty_id {
1298            self.funcs
1299                .push(self.types[type_index as usize].unwrap_func());
1300            return Ok(());
1301        }
1302
1303        let ty = types[core_ty_id].unwrap_func();
1304        let lowered_ty = types[lowered_core_ty_id].unwrap_func();
1305
1306        if lowered_ty.params() != ty.params() {
1307            bail!(
1308                offset,
1309                "lowered parameter types `{:?}` do not match parameter types `{:?}` of \
1310                     core function {core_func_index}",
1311                lowered_ty.params(),
1312                ty.params()
1313            );
1314        }
1315
1316        if lowered_ty.results() != ty.results() {
1317            bail!(
1318                offset,
1319                "lowered result types `{:?}` do not match result types `{:?}` of \
1320                     core function {core_func_index}",
1321                lowered_ty.results(),
1322                ty.results()
1323            );
1324        }
1325
1326        // Otherwise, must be different rec groups or subtyping (which isn't
1327        // supported yet) or something.
1328        bail!(
1329            offset,
1330            "lowered function type `{:?}` does not match type `{:?}` of \
1331                 core function {core_func_index}",
1332            types[lowered_core_ty_id],
1333            types[core_ty_id],
1334        );
1335    }
1336
1337    fn lower_function(
1338        &mut self,
1339        func_index: u32,
1340        options: &[CanonicalOption],
1341        types: &mut TypeAlloc,
1342        offset: usize,
1343    ) -> Result<()> {
1344        let ty = &types[self.function_at(func_index, offset)?];
1345
1346        // Lowering a function is for an import, so use a function type that matches
1347        // the expected canonical ABI import signature.
1348        let options = self.check_options(types, options, offset)?;
1349        options.check_lower(offset)?;
1350        let func_ty = ty.lower(types, &options, Abi::Lower, offset)?;
1351        let ty_id = func_ty.intern(types, offset);
1352
1353        self.core_funcs.push(ty_id);
1354        Ok(())
1355    }
1356
1357    fn resource_new(&mut self, resource: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1358        let rep = self.check_local_resource(resource, types, offset)?;
1359        let id = types.intern_func_type(FuncType::new([rep], [ValType::I32]), offset);
1360        self.core_funcs.push(id);
1361        Ok(())
1362    }
1363
1364    fn resource_drop(&mut self, resource: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1365        self.resource_at(resource, types, offset)?;
1366        let id = types.intern_func_type(FuncType::new([ValType::I32], []), offset);
1367        self.core_funcs.push(id);
1368        Ok(())
1369    }
1370
1371    fn resource_drop_async(
1372        &mut self,
1373        resource: u32,
1374        types: &mut TypeAlloc,
1375        offset: usize,
1376    ) -> Result<()> {
1377        if !self.features.cm_async_builtins() {
1378            bail!(
1379                offset,
1380                "`resource.drop` as `async` requires the component model async builtins feature"
1381            )
1382        }
1383        self.resource_at(resource, types, offset)?;
1384        let id = types.intern_func_type(FuncType::new([ValType::I32], []), offset);
1385        self.core_funcs.push(id);
1386        Ok(())
1387    }
1388
1389    fn resource_rep(&mut self, resource: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1390        let rep = self.check_local_resource(resource, types, offset)?;
1391        let id = types.intern_func_type(FuncType::new([ValType::I32], [rep]), offset);
1392        self.core_funcs.push(id);
1393        Ok(())
1394    }
1395
1396    fn backpressure_set(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1397        if !self.features.cm_async() {
1398            bail!(
1399                offset,
1400                "`backpressure.set` requires the component model async feature"
1401            )
1402        }
1403
1404        self.core_funcs
1405            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
1406        Ok(())
1407    }
1408
1409    fn backpressure_inc(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1410        if !self.features.cm_async() {
1411            bail!(
1412                offset,
1413                "`backpressure.inc` requires the component model async feature"
1414            )
1415        }
1416
1417        self.core_funcs
1418            .push(types.intern_func_type(FuncType::new([], []), offset));
1419        Ok(())
1420    }
1421
1422    fn backpressure_dec(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1423        if !self.features.cm_async() {
1424            bail!(
1425                offset,
1426                "`backpressure.dec` requires the component model async feature"
1427            )
1428        }
1429
1430        self.core_funcs
1431            .push(types.intern_func_type(FuncType::new([], []), offset));
1432        Ok(())
1433    }
1434
1435    fn task_return(
1436        &mut self,
1437        result: &Option<crate::ComponentValType>,
1438        options: &[CanonicalOption],
1439        types: &mut TypeAlloc,
1440        offset: usize,
1441    ) -> Result<()> {
1442        if !self.features.cm_async() {
1443            bail!(
1444                offset,
1445                "`task.return` requires the component model async feature"
1446            )
1447        }
1448
1449        let func_ty = ComponentFuncType {
1450            info: TypeInfo::new(),
1451            params: result
1452                .iter()
1453                .map(|ty| {
1454                    Ok((
1455                        KebabString::new("v").unwrap(),
1456                        match ty {
1457                            crate::ComponentValType::Primitive(ty) => {
1458                                ComponentValType::Primitive(*ty)
1459                            }
1460                            crate::ComponentValType::Type(index) => {
1461                                ComponentValType::Type(self.defined_type_at(*index, offset)?)
1462                            }
1463                        },
1464                    ))
1465                })
1466                .collect::<Result<_>>()?,
1467            result: None,
1468        };
1469
1470        let options = self.check_options(types, options, offset)?;
1471        if options.realloc.is_some() {
1472            bail!(offset, "cannot specify `realloc` option on `task.return`")
1473        }
1474        if options.post_return.is_some() {
1475            bail!(
1476                offset,
1477                "cannot specify `post-return` option on `task.return`"
1478            )
1479        }
1480        options.check_lower(offset)?;
1481        options.require_sync(offset, "task.return")?;
1482
1483        let func_ty = func_ty.lower(types, &options, Abi::Lower, offset)?;
1484        let ty_id = func_ty.intern(types, offset);
1485
1486        self.core_funcs.push(ty_id);
1487        Ok(())
1488    }
1489
1490    fn task_cancel(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1491        if !self.features.cm_async() {
1492            bail!(
1493                offset,
1494                "`task.cancel` requires the component model async feature"
1495            )
1496        }
1497
1498        self.core_funcs
1499            .push(types.intern_func_type(FuncType::new([], []), offset));
1500        Ok(())
1501    }
1502
1503    fn validate_context_immediate(
1504        &self,
1505        immediate: u32,
1506        operation: &str,
1507        offset: usize,
1508    ) -> Result<()> {
1509        if !self.features.cm_threading() && immediate > 0 {
1510            bail!(offset, "`{operation}` immediate must be zero: {immediate}")
1511        } else if immediate > 1 {
1512            bail!(
1513                offset,
1514                "`{operation}` immediate must be zero or one: {immediate}"
1515            )
1516        }
1517        Ok(())
1518    }
1519
1520    fn context_get(&mut self, i: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1521        if !self.features.cm_async() {
1522            bail!(
1523                offset,
1524                "`context.get` requires the component model async feature"
1525            )
1526        }
1527        self.validate_context_immediate(i, "context.get", offset)?;
1528
1529        self.core_funcs
1530            .push(types.intern_func_type(FuncType::new([], [ValType::I32]), offset));
1531        Ok(())
1532    }
1533
1534    fn context_set(&mut self, i: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1535        if !self.features.cm_async() {
1536            bail!(
1537                offset,
1538                "`context.set` requires the component model async feature"
1539            )
1540        }
1541        self.validate_context_immediate(i, "context.set", offset)?;
1542
1543        self.core_funcs
1544            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
1545        Ok(())
1546    }
1547
1548    fn thread_yield(
1549        &mut self,
1550        cancellable: bool,
1551        types: &mut TypeAlloc,
1552        offset: usize,
1553    ) -> Result<()> {
1554        if !self.features.cm_async() {
1555            bail!(
1556                offset,
1557                "`thread.yield` requires the component model async feature"
1558            )
1559        }
1560        if cancellable && !self.features.cm_async_stackful() {
1561            bail!(
1562                offset,
1563                "cancellable `thread.yield` requires the component model async stackful feature"
1564            )
1565        }
1566
1567        self.core_funcs
1568            .push(types.intern_func_type(FuncType::new([], [ValType::I32]), offset));
1569        Ok(())
1570    }
1571
1572    fn subtask_drop(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1573        if !self.features.cm_async() {
1574            bail!(
1575                offset,
1576                "`subtask.drop` requires the component model async feature"
1577            )
1578        }
1579
1580        self.core_funcs
1581            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
1582        Ok(())
1583    }
1584
1585    fn subtask_cancel(&mut self, async_: bool, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1586        if !self.features.cm_async() {
1587            bail!(
1588                offset,
1589                "`subtask.cancel` requires the component model async feature"
1590            )
1591        }
1592        if async_ && !self.features.cm_async_builtins() {
1593            bail!(
1594                offset,
1595                "async `subtask.cancel` requires the component model async builtins feature"
1596            )
1597        }
1598
1599        self.core_funcs
1600            .push(types.intern_func_type(FuncType::new([ValType::I32], [ValType::I32]), offset));
1601        Ok(())
1602    }
1603
1604    fn stream_new(&mut self, ty: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1605        if !self.features.cm_async() {
1606            bail!(
1607                offset,
1608                "`stream.new` requires the component model async feature"
1609            )
1610        }
1611
1612        let ty = self.defined_type_at(ty, offset)?;
1613        let ComponentDefinedType::Stream(_) = &types[ty] else {
1614            bail!(offset, "`stream.new` requires a stream type")
1615        };
1616
1617        self.core_funcs
1618            .push(types.intern_func_type(FuncType::new([], [ValType::I64]), offset));
1619        Ok(())
1620    }
1621
1622    fn stream_read(
1623        &mut self,
1624        ty: u32,
1625        options: &[CanonicalOption],
1626        types: &mut TypeAlloc,
1627        offset: usize,
1628    ) -> Result<()> {
1629        if !self.features.cm_async() {
1630            bail!(
1631                offset,
1632                "`stream.read` requires the component model async feature"
1633            )
1634        }
1635
1636        let ty = self.defined_type_at(ty, offset)?;
1637        let ComponentDefinedType::Stream(elem_ty) = &types[ty] else {
1638            bail!(offset, "`stream.read` requires a stream type")
1639        };
1640
1641        let ty_id = self
1642            .check_options(types, options, offset)?
1643            .require_memory(offset)?
1644            .require_realloc_if(offset, || elem_ty.is_some_and(|ty| ty.contains_ptr(types)))?
1645            .check_lower(offset)?
1646            .check_core_type(
1647                types,
1648                FuncType::new([ValType::I32; 3], [ValType::I32]),
1649                offset,
1650            )?;
1651
1652        self.core_funcs.push(ty_id);
1653        Ok(())
1654    }
1655
1656    fn stream_write(
1657        &mut self,
1658        ty: u32,
1659        options: &[CanonicalOption],
1660        types: &mut TypeAlloc,
1661        offset: usize,
1662    ) -> Result<()> {
1663        if !self.features.cm_async() {
1664            bail!(
1665                offset,
1666                "`stream.write` requires the component model async feature"
1667            )
1668        }
1669
1670        let ty = self.defined_type_at(ty, offset)?;
1671        let ComponentDefinedType::Stream(_) = &types[ty] else {
1672            bail!(offset, "`stream.write` requires a stream type")
1673        };
1674
1675        let ty_id = self
1676            .check_options(types, options, offset)?
1677            .require_memory(offset)?
1678            .check_lower(offset)?
1679            .check_core_type(
1680                types,
1681                FuncType::new([ValType::I32; 3], [ValType::I32]),
1682                offset,
1683            )?;
1684
1685        self.core_funcs.push(ty_id);
1686        Ok(())
1687    }
1688
1689    fn stream_cancel_read(
1690        &mut self,
1691        ty: u32,
1692        cancellable: bool,
1693        types: &mut TypeAlloc,
1694        offset: usize,
1695    ) -> Result<()> {
1696        if !self.features.cm_async() {
1697            bail!(
1698                offset,
1699                "`stream.cancel-read` requires the component model async feature"
1700            )
1701        }
1702        if cancellable && !self.features.cm_async_builtins() {
1703            bail!(
1704                offset,
1705                "async `stream.cancel-read` requires the component model async builtins feature"
1706            )
1707        }
1708
1709        let ty = self.defined_type_at(ty, offset)?;
1710        let ComponentDefinedType::Stream(_) = &types[ty] else {
1711            bail!(offset, "`stream.cancel-read` requires a stream type")
1712        };
1713
1714        self.core_funcs
1715            .push(types.intern_func_type(FuncType::new([ValType::I32], [ValType::I32]), offset));
1716        Ok(())
1717    }
1718
1719    fn stream_cancel_write(
1720        &mut self,
1721        ty: u32,
1722        cancellable: bool,
1723        types: &mut TypeAlloc,
1724        offset: usize,
1725    ) -> Result<()> {
1726        if !self.features.cm_async() {
1727            bail!(
1728                offset,
1729                "`stream.cancel-write` requires the component model async feature"
1730            )
1731        }
1732        if cancellable && !self.features.cm_async_builtins() {
1733            bail!(
1734                offset,
1735                "async `stream.cancel-write` requires the component model async builtins feature"
1736            )
1737        }
1738
1739        let ty = self.defined_type_at(ty, offset)?;
1740        let ComponentDefinedType::Stream(_) = &types[ty] else {
1741            bail!(offset, "`stream.cancel-write` requires a stream type")
1742        };
1743
1744        self.core_funcs
1745            .push(types.intern_func_type(FuncType::new([ValType::I32], [ValType::I32]), offset));
1746        Ok(())
1747    }
1748
1749    fn stream_drop_readable(
1750        &mut self,
1751        ty: u32,
1752        types: &mut TypeAlloc,
1753        offset: usize,
1754    ) -> Result<()> {
1755        if !self.features.cm_async() {
1756            bail!(
1757                offset,
1758                "`stream.drop-readable` requires the component model async feature"
1759            )
1760        }
1761
1762        let ty = self.defined_type_at(ty, offset)?;
1763        let ComponentDefinedType::Stream(_) = &types[ty] else {
1764            bail!(offset, "`stream.drop-readable` requires a stream type")
1765        };
1766
1767        self.core_funcs
1768            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
1769        Ok(())
1770    }
1771
1772    fn stream_drop_writable(
1773        &mut self,
1774        ty: u32,
1775        types: &mut TypeAlloc,
1776        offset: usize,
1777    ) -> Result<()> {
1778        if !self.features.cm_async() {
1779            bail!(
1780                offset,
1781                "`stream.drop-writable` requires the component model async feature"
1782            )
1783        }
1784
1785        let ty = self.defined_type_at(ty, offset)?;
1786        let ComponentDefinedType::Stream(_) = &types[ty] else {
1787            bail!(offset, "`stream.drop-writable` requires a stream type")
1788        };
1789
1790        self.core_funcs
1791            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
1792        Ok(())
1793    }
1794
1795    fn future_new(&mut self, ty: u32, types: &mut TypeAlloc, offset: usize) -> Result<()> {
1796        if !self.features.cm_async() {
1797            bail!(
1798                offset,
1799                "`future.new` requires the component model async feature"
1800            )
1801        }
1802
1803        let ty = self.defined_type_at(ty, offset)?;
1804        let ComponentDefinedType::Future(_) = &types[ty] else {
1805            bail!(offset, "`future.new` requires a future type")
1806        };
1807
1808        self.core_funcs
1809            .push(types.intern_func_type(FuncType::new([], [ValType::I64]), offset));
1810        Ok(())
1811    }
1812
1813    fn future_read(
1814        &mut self,
1815        ty: u32,
1816        options: &[CanonicalOption],
1817        types: &mut TypeAlloc,
1818        offset: usize,
1819    ) -> Result<()> {
1820        if !self.features.cm_async() {
1821            bail!(
1822                offset,
1823                "`future.read` requires the component model async feature"
1824            )
1825        }
1826
1827        let ty = self.defined_type_at(ty, offset)?;
1828        let ComponentDefinedType::Future(elem_ty) = &types[ty] else {
1829            bail!(offset, "`future.read` requires a future type")
1830        };
1831
1832        let ty_id = self
1833            .check_options(types, options, offset)?
1834            .require_memory_if(offset, || elem_ty.is_some())?
1835            .require_realloc_if(offset, || elem_ty.is_some_and(|ty| ty.contains_ptr(types)))?
1836            .check_lower(offset)?
1837            .check_core_type(
1838                types,
1839                FuncType::new([ValType::I32; 2], [ValType::I32]),
1840                offset,
1841            )?;
1842
1843        self.core_funcs.push(ty_id);
1844        Ok(())
1845    }
1846
1847    fn future_write(
1848        &mut self,
1849        ty: u32,
1850        options: Vec<CanonicalOption>,
1851        types: &mut TypeAlloc,
1852        offset: usize,
1853    ) -> Result<()> {
1854        if !self.features.cm_async() {
1855            bail!(
1856                offset,
1857                "`future.write` requires the component model async feature"
1858            )
1859        }
1860
1861        let ty = self.defined_type_at(ty, offset)?;
1862        let ComponentDefinedType::Future(elem_ty) = &types[ty] else {
1863            bail!(offset, "`future.write` requires a future type")
1864        };
1865
1866        let ty_id = self
1867            .check_options(types, &options, offset)?
1868            .require_memory_if(offset, || elem_ty.is_some())?
1869            .check_core_type(
1870                types,
1871                FuncType::new([ValType::I32; 2], [ValType::I32]),
1872                offset,
1873            )?;
1874
1875        self.core_funcs.push(ty_id);
1876        Ok(())
1877    }
1878
1879    fn future_cancel_read(
1880        &mut self,
1881        ty: u32,
1882        cancellable: bool,
1883        types: &mut TypeAlloc,
1884        offset: usize,
1885    ) -> Result<()> {
1886        if !self.features.cm_async() {
1887            bail!(
1888                offset,
1889                "`future.cancel-read` requires the component model async feature"
1890            )
1891        }
1892        if cancellable && !self.features.cm_async_builtins() {
1893            bail!(
1894                offset,
1895                "async `future.cancel-read` requires the component model async builtins feature"
1896            )
1897        }
1898
1899        let ty = self.defined_type_at(ty, offset)?;
1900        let ComponentDefinedType::Future(_) = &types[ty] else {
1901            bail!(offset, "`future.cancel-read` requires a future type")
1902        };
1903
1904        self.core_funcs
1905            .push(types.intern_func_type(FuncType::new([ValType::I32], [ValType::I32]), offset));
1906        Ok(())
1907    }
1908
1909    fn future_cancel_write(
1910        &mut self,
1911        ty: u32,
1912        cancellable: bool,
1913        types: &mut TypeAlloc,
1914        offset: usize,
1915    ) -> Result<()> {
1916        if !self.features.cm_async() {
1917            bail!(
1918                offset,
1919                "`future.cancel-write` requires the component model async feature"
1920            )
1921        }
1922        if cancellable && !self.features.cm_async_builtins() {
1923            bail!(
1924                offset,
1925                "async `future.cancel-write` requires the component model async builtins feature"
1926            )
1927        }
1928
1929        let ty = self.defined_type_at(ty, offset)?;
1930        let ComponentDefinedType::Future(_) = &types[ty] else {
1931            bail!(offset, "`future.cancel-write` requires a future type")
1932        };
1933
1934        self.core_funcs
1935            .push(types.intern_func_type(FuncType::new([ValType::I32], [ValType::I32]), offset));
1936        Ok(())
1937    }
1938
1939    fn future_drop_readable(
1940        &mut self,
1941        ty: u32,
1942        types: &mut TypeAlloc,
1943        offset: usize,
1944    ) -> Result<()> {
1945        if !self.features.cm_async() {
1946            bail!(
1947                offset,
1948                "`future.drop-readable` requires the component model async feature"
1949            )
1950        }
1951
1952        let ty = self.defined_type_at(ty, offset)?;
1953        let ComponentDefinedType::Future(_) = &types[ty] else {
1954            bail!(offset, "`future.drop-readable` requires a future type")
1955        };
1956
1957        self.core_funcs
1958            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
1959        Ok(())
1960    }
1961
1962    fn future_drop_writable(
1963        &mut self,
1964        ty: u32,
1965        types: &mut TypeAlloc,
1966        offset: usize,
1967    ) -> Result<()> {
1968        if !self.features.cm_async() {
1969            bail!(
1970                offset,
1971                "`future.drop-writable` requires the component model async feature"
1972            )
1973        }
1974
1975        let ty = self.defined_type_at(ty, offset)?;
1976        let ComponentDefinedType::Future(_) = &types[ty] else {
1977            bail!(offset, "`future.drop-writable` requires a future type")
1978        };
1979
1980        self.core_funcs
1981            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
1982        Ok(())
1983    }
1984
1985    fn error_context_new(
1986        &mut self,
1987        options: Vec<CanonicalOption>,
1988        types: &mut TypeAlloc,
1989        offset: usize,
1990    ) -> Result<()> {
1991        if !self.features.cm_error_context() {
1992            bail!(
1993                offset,
1994                "`error-context.new` requires the component model error-context feature"
1995            )
1996        }
1997
1998        let ty_id = self
1999            .check_options(types, &options, offset)?
2000            .require_memory(offset)?
2001            .require_sync(offset, "error-context.new")?
2002            .check_lower(offset)?
2003            .check_core_type(
2004                types,
2005                FuncType::new([ValType::I32; 2], [ValType::I32]),
2006                offset,
2007            )?;
2008
2009        self.core_funcs.push(ty_id);
2010        Ok(())
2011    }
2012
2013    fn error_context_debug_message(
2014        &mut self,
2015        options: Vec<CanonicalOption>,
2016        types: &mut TypeAlloc,
2017        offset: usize,
2018    ) -> Result<()> {
2019        if !self.features.cm_error_context() {
2020            bail!(
2021                offset,
2022                "`error-context.debug-message` requires the component model error-context feature"
2023            )
2024        }
2025
2026        let ty_id = self
2027            .check_options(types, &options, offset)?
2028            .require_memory(offset)?
2029            .require_realloc(offset)?
2030            .require_sync(offset, "error-context.debug-message")?
2031            .check_lower(offset)?
2032            .check_core_type(types, FuncType::new([ValType::I32; 2], []), offset)?;
2033
2034        self.core_funcs.push(ty_id);
2035        Ok(())
2036    }
2037
2038    fn error_context_drop(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
2039        if !self.features.cm_error_context() {
2040            bail!(
2041                offset,
2042                "`error-context.drop` requires the component model error-context feature"
2043            )
2044        }
2045
2046        self.core_funcs
2047            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
2048        Ok(())
2049    }
2050
2051    fn waitable_set_new(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
2052        if !self.features.cm_async() {
2053            bail!(
2054                offset,
2055                "`waitable-set.new` requires the component model async feature"
2056            )
2057        }
2058
2059        self.core_funcs
2060            .push(types.intern_func_type(FuncType::new([], [ValType::I32]), offset));
2061        Ok(())
2062    }
2063
2064    fn waitable_set_wait(
2065        &mut self,
2066        cancellable: bool,
2067        memory: u32,
2068        types: &mut TypeAlloc,
2069        offset: usize,
2070    ) -> Result<()> {
2071        if !self.features.cm_async() {
2072            bail!(
2073                offset,
2074                "`waitable-set.wait` requires the component model async feature"
2075            )
2076        }
2077        if cancellable && !self.features.cm_async_stackful() {
2078            bail!(
2079                offset,
2080                "cancellable `waitable-set.wait` requires the component model async stackful feature"
2081            )
2082        }
2083
2084        self.cabi_memory_at(memory, offset)?;
2085
2086        self.core_funcs
2087            .push(types.intern_func_type(FuncType::new([ValType::I32; 2], [ValType::I32]), offset));
2088        Ok(())
2089    }
2090
2091    fn waitable_set_poll(
2092        &mut self,
2093        cancellable: bool,
2094        memory: u32,
2095        types: &mut TypeAlloc,
2096        offset: usize,
2097    ) -> Result<()> {
2098        if !self.features.cm_async() {
2099            bail!(
2100                offset,
2101                "`waitable-set.poll` requires the component model async feature"
2102            )
2103        }
2104        if cancellable && !self.features.cm_async_stackful() {
2105            bail!(
2106                offset,
2107                "cancellable `waitable-set.poll` requires the component model async stackful feature"
2108            )
2109        }
2110
2111        self.cabi_memory_at(memory, offset)?;
2112
2113        self.core_funcs
2114            .push(types.intern_func_type(FuncType::new([ValType::I32; 2], [ValType::I32]), offset));
2115        Ok(())
2116    }
2117
2118    fn waitable_set_drop(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
2119        if !self.features.cm_async() {
2120            bail!(
2121                offset,
2122                "`waitable-set.drop` requires the component model async feature"
2123            )
2124        }
2125
2126        self.core_funcs
2127            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
2128        Ok(())
2129    }
2130
2131    fn waitable_join(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
2132        if !self.features.cm_async() {
2133            bail!(
2134                offset,
2135                "`waitable.join` requires the component model async feature"
2136            )
2137        }
2138
2139        self.core_funcs
2140            .push(types.intern_func_type(FuncType::new([ValType::I32; 2], []), offset));
2141        Ok(())
2142    }
2143
2144    fn thread_index(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
2145        if !self.features.cm_threading() {
2146            bail!(
2147                offset,
2148                "`thread.index` requires the component model threading feature"
2149            )
2150        }
2151
2152        self.core_funcs
2153            .push(types.intern_func_type(FuncType::new([], [ValType::I32]), offset));
2154        Ok(())
2155    }
2156
2157    fn thread_new_indirect(
2158        &mut self,
2159        func_ty_index: u32,
2160        table_index: u32,
2161        types: &mut TypeAlloc,
2162        offset: usize,
2163    ) -> Result<()> {
2164        if !self.features.cm_threading() {
2165            bail!(
2166                offset,
2167                "`thread.new_indirect` requires the component model threading feature"
2168            )
2169        }
2170
2171        let core_type_id = match self.core_type_at(func_ty_index, offset)? {
2172            ComponentCoreTypeId::Sub(c) => c,
2173            ComponentCoreTypeId::Module(_) => bail!(offset, "expected a core function type"),
2174        };
2175        let sub_ty = &types[core_type_id];
2176        match &sub_ty.composite_type.inner {
2177            CompositeInnerType::Func(func_ty) => {
2178                if func_ty.params() != [ValType::I32] {
2179                    bail!(
2180                        offset,
2181                        "start function must take a single `i32` argument (currently)"
2182                    );
2183                }
2184                if func_ty.results() != [] {
2185                    bail!(offset, "start function must not return any values");
2186                }
2187            }
2188            _ => bail!(offset, "start type must be a function"),
2189        }
2190
2191        let table = self.table_at(table_index, offset)?;
2192
2193        SubtypeCx::table_type(
2194            table,
2195            &TableType {
2196                initial: 0,
2197                maximum: None,
2198                table64: false,
2199                shared: false,
2200                element_type: RefType::FUNCREF,
2201            },
2202            offset,
2203        )
2204        .map_err(|mut e| {
2205            e.add_context("table is not a 32-bit table of (ref null (func))".into());
2206            e
2207        })?;
2208
2209        self.core_funcs.push(types.intern_func_type(
2210            FuncType::new([ValType::I32, ValType::I32], [ValType::I32]),
2211            offset,
2212        ));
2213        Ok(())
2214    }
2215
2216    fn thread_switch_to(
2217        &mut self,
2218        _cancellable: bool,
2219        types: &mut TypeAlloc,
2220        offset: usize,
2221    ) -> Result<()> {
2222        if !self.features.cm_threading() {
2223            bail!(
2224                offset,
2225                "`thread.switch_to` requires the component model threading feature"
2226            )
2227        }
2228
2229        self.core_funcs
2230            .push(types.intern_func_type(FuncType::new([ValType::I32], [ValType::I32]), offset));
2231        Ok(())
2232    }
2233
2234    fn thread_suspend(
2235        &mut self,
2236        _cancellable: bool,
2237        types: &mut TypeAlloc,
2238        offset: usize,
2239    ) -> Result<()> {
2240        if !self.features.cm_threading() {
2241            bail!(
2242                offset,
2243                "`thread.suspend` requires the component model threading feature"
2244            )
2245        }
2246        self.core_funcs
2247            .push(types.intern_func_type(FuncType::new([], [ValType::I32]), offset));
2248        Ok(())
2249    }
2250
2251    fn thread_resume_later(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
2252        if !self.features.cm_threading() {
2253            bail!(
2254                offset,
2255                "`thread.resume_later` requires the component model threading feature"
2256            )
2257        }
2258        self.core_funcs
2259            .push(types.intern_func_type(FuncType::new([ValType::I32], []), offset));
2260        Ok(())
2261    }
2262
2263    fn thread_yield_to(
2264        &mut self,
2265        _cancellable: bool,
2266        types: &mut TypeAlloc,
2267        offset: usize,
2268    ) -> Result<()> {
2269        if !self.features.cm_threading() {
2270            bail!(
2271                offset,
2272                "`thread.yield_to` requires the component model threading feature"
2273            )
2274        }
2275        self.core_funcs
2276            .push(types.intern_func_type(FuncType::new([ValType::I32], [ValType::I32]), offset));
2277        Ok(())
2278    }
2279
2280    fn check_local_resource(&self, idx: u32, types: &TypeList, offset: usize) -> Result<ValType> {
2281        let resource = self.resource_at(idx, types, offset)?;
2282        match self
2283            .defined_resources
2284            .get(&resource.resource())
2285            .and_then(|rep| *rep)
2286        {
2287            Some(ty) => Ok(ty),
2288            None => bail!(offset, "type {idx} is not a local resource"),
2289        }
2290    }
2291
2292    fn resource_at<'a>(
2293        &self,
2294        idx: u32,
2295        _types: &'a TypeList,
2296        offset: usize,
2297    ) -> Result<AliasableResourceId> {
2298        if let ComponentAnyTypeId::Resource(id) = self.component_type_at(idx, offset)? {
2299            return Ok(id);
2300        }
2301        bail!(offset, "type index {} is not a resource type", idx)
2302    }
2303
2304    fn thread_spawn_ref(
2305        &mut self,
2306        func_ty_index: u32,
2307        types: &mut TypeAlloc,
2308        offset: usize,
2309    ) -> Result<()> {
2310        if !self.features.shared_everything_threads() {
2311            bail!(
2312                offset,
2313                "`thread.spawn_ref` requires the shared-everything-threads proposal"
2314            )
2315        }
2316        let core_type_id = self.validate_spawn_type(func_ty_index, types, offset)?;
2317
2318        // Insert the core function.
2319        let packed_index = PackedIndex::from_id(core_type_id).ok_or_else(|| {
2320            format_err!(offset, "implementation limit: too many types in `TypeList`")
2321        })?;
2322        let start_func_ref = RefType::concrete(true, packed_index);
2323        let func_ty = FuncType::new([ValType::Ref(start_func_ref), ValType::I32], [ValType::I32]);
2324        let core_ty = SubType::func(func_ty, true);
2325        let id = types.intern_sub_type(core_ty, offset);
2326        self.core_funcs.push(id);
2327
2328        Ok(())
2329    }
2330
2331    fn thread_spawn_indirect(
2332        &mut self,
2333        func_ty_index: u32,
2334        table_index: u32,
2335        types: &mut TypeAlloc,
2336        offset: usize,
2337    ) -> Result<()> {
2338        if !self.features.shared_everything_threads() {
2339            bail!(
2340                offset,
2341                "`thread.spawn_indirect` requires the shared-everything-threads proposal"
2342            )
2343        }
2344        let _ = self.validate_spawn_type(func_ty_index, types, offset)?;
2345
2346        // Check this much like `call_indirect` (see
2347        // `OperatorValidatorTemp::check_call_indirect_ty`), but loosen the
2348        // table type restrictions to just a `funcref`. See the component model
2349        // for more details:
2350        // https://github.com/WebAssembly/component-model/blob/6e08e283/design/mvp/CanonicalABI.md#-canon-threadspawn_indirect.
2351        let table = self.table_at(table_index, offset)?;
2352
2353        SubtypeCx::table_type(
2354            table,
2355            &TableType {
2356                initial: 0,
2357                maximum: None,
2358                table64: false,
2359                shared: true,
2360                element_type: RefType::FUNCREF
2361                    .shared()
2362                    .expect("a funcref can always be shared"),
2363            },
2364            offset,
2365        )
2366        .map_err(|mut e| {
2367            e.add_context("table is not a 32-bit shared table of (ref null (shared func))".into());
2368            e
2369        })?;
2370
2371        // Insert the core function.
2372        let func_ty = FuncType::new([ValType::I32, ValType::I32], [ValType::I32]);
2373        let core_ty = SubType::func(func_ty, true);
2374        let id = types.intern_sub_type(core_ty, offset);
2375        self.core_funcs.push(id);
2376
2377        Ok(())
2378    }
2379
2380    /// Validates the type of a `thread.spawn*` instruction.
2381    ///
2382    /// This is currently limited to shared functions with the signature `[i32]
2383    /// -> []`. See component model [explanation] for more details.
2384    ///
2385    /// [explanation]: https://github.com/WebAssembly/component-model/blob/6e08e283/design/mvp/CanonicalABI.md#-canon-threadspawn_ref
2386    fn validate_spawn_type(
2387        &self,
2388        func_ty_index: u32,
2389        types: &TypeAlloc,
2390        offset: usize,
2391    ) -> Result<CoreTypeId> {
2392        let core_type_id = match self.core_type_at(func_ty_index, offset)? {
2393            ComponentCoreTypeId::Sub(c) => c,
2394            ComponentCoreTypeId::Module(_) => bail!(offset, "expected a core function type"),
2395        };
2396        let sub_ty = &types[core_type_id];
2397        if !sub_ty.composite_type.shared {
2398            bail!(offset, "spawn type must be shared");
2399        }
2400        match &sub_ty.composite_type.inner {
2401            CompositeInnerType::Func(func_ty) => {
2402                if func_ty.params() != [ValType::I32] {
2403                    bail!(
2404                        offset,
2405                        "spawn function must take a single `i32` argument (currently)"
2406                    );
2407                }
2408                if func_ty.results() != [] {
2409                    bail!(offset, "spawn function must not return any values");
2410                }
2411            }
2412            _ => bail!(offset, "spawn type must be a function"),
2413        }
2414        Ok(core_type_id)
2415    }
2416
2417    fn thread_available_parallelism(&mut self, types: &mut TypeAlloc, offset: usize) -> Result<()> {
2418        if !self.features.shared_everything_threads() {
2419            bail!(
2420                offset,
2421                "`thread.available_parallelism` requires the shared-everything-threads proposal"
2422            )
2423        }
2424
2425        let func_ty = FuncType::new([], [ValType::I32]);
2426        let core_ty = SubType::func(func_ty, true);
2427        let id = types.intern_sub_type(core_ty, offset);
2428        self.core_funcs.push(id);
2429
2430        Ok(())
2431    }
2432
2433    pub fn add_component(&mut self, component: ComponentType, types: &mut TypeAlloc) -> Result<()> {
2434        let id = types.push_ty(component);
2435        self.components.push(id);
2436        Ok(())
2437    }
2438
2439    pub fn add_instance(
2440        &mut self,
2441        instance: crate::ComponentInstance,
2442        types: &mut TypeAlloc,
2443        offset: usize,
2444    ) -> Result<()> {
2445        let instance = match instance {
2446            crate::ComponentInstance::Instantiate {
2447                component_index,
2448                args,
2449            } => self.instantiate_component(component_index, args.into_vec(), types, offset)?,
2450            crate::ComponentInstance::FromExports(exports) => {
2451                self.instantiate_component_exports(exports.into_vec(), types, offset)?
2452            }
2453        };
2454
2455        self.instances.push(instance);
2456
2457        Ok(())
2458    }
2459
2460    pub fn add_alias(
2461        components: &mut [Self],
2462        alias: crate::ComponentAlias,
2463        types: &mut TypeAlloc,
2464        offset: usize,
2465    ) -> Result<()> {
2466        match alias {
2467            crate::ComponentAlias::InstanceExport {
2468                instance_index,
2469                kind,
2470                name,
2471            } => components.last_mut().unwrap().alias_instance_export(
2472                instance_index,
2473                kind,
2474                name,
2475                types,
2476                offset,
2477            ),
2478            crate::ComponentAlias::CoreInstanceExport {
2479                instance_index,
2480                kind,
2481                name,
2482            } => components.last_mut().unwrap().alias_core_instance_export(
2483                instance_index,
2484                kind,
2485                name,
2486                types,
2487                offset,
2488            ),
2489            crate::ComponentAlias::Outer { kind, count, index } => match kind {
2490                ComponentOuterAliasKind::CoreModule => {
2491                    Self::alias_module(components, count, index, offset)
2492                }
2493                ComponentOuterAliasKind::CoreType => {
2494                    Self::alias_core_type(components, count, index, offset)
2495                }
2496                ComponentOuterAliasKind::Type => {
2497                    Self::alias_type(components, count, index, types, offset)
2498                }
2499                ComponentOuterAliasKind::Component => {
2500                    Self::alias_component(components, count, index, offset)
2501                }
2502            },
2503        }
2504    }
2505
2506    pub fn add_start(
2507        &mut self,
2508        func_index: u32,
2509        args: &[u32],
2510        results: u32,
2511        types: &mut TypeList,
2512        offset: usize,
2513    ) -> Result<()> {
2514        if !self.features.cm_values() {
2515            bail!(
2516                offset,
2517                "support for component model `value`s is not enabled"
2518            );
2519        }
2520        if self.has_start {
2521            return Err(BinaryReaderError::new(
2522                "component cannot have more than one start function",
2523                offset,
2524            ));
2525        }
2526
2527        let ft = &types[self.function_at(func_index, offset)?];
2528
2529        if ft.params.len() != args.len() {
2530            bail!(
2531                offset,
2532                "component start function requires {} arguments but was given {}",
2533                ft.params.len(),
2534                args.len()
2535            );
2536        }
2537
2538        if u32::from(ft.result.is_some()) != results {
2539            bail!(
2540                offset,
2541                "component start function has a result count of {results} \
2542                 but the function type has a result count of {type_results}",
2543                type_results = u32::from(ft.result.is_some()),
2544            );
2545        }
2546
2547        let cx = SubtypeCx::new(types, types);
2548        for (i, ((_, ty), arg)) in ft.params.iter().zip(args).enumerate() {
2549            // Ensure the value's type is a subtype of the parameter type
2550            cx.component_val_type(self.value_at(*arg, offset)?, ty, offset)
2551                .with_context(|| {
2552                    format!("value type mismatch for component start function argument {i}")
2553                })?;
2554        }
2555
2556        if let Some(ty) = ft.result {
2557            self.values.push((ty, false));
2558        }
2559
2560        self.has_start = true;
2561
2562        Ok(())
2563    }
2564
2565    fn check_options(
2566        &self,
2567        types: &TypeList,
2568        options: &[CanonicalOption],
2569        offset: usize,
2570    ) -> Result<CanonicalOptions> {
2571        fn display(option: CanonicalOption) -> &'static str {
2572            match option {
2573                CanonicalOption::UTF8 => "utf8",
2574                CanonicalOption::UTF16 => "utf16",
2575                CanonicalOption::CompactUTF16 => "latin1-utf16",
2576                CanonicalOption::Memory(_) => "memory",
2577                CanonicalOption::Realloc(_) => "realloc",
2578                CanonicalOption::PostReturn(_) => "post-return",
2579                CanonicalOption::Async => "async",
2580                CanonicalOption::Callback(_) => "callback",
2581                CanonicalOption::CoreType(_) => "core-type",
2582                CanonicalOption::Gc => "gc",
2583            }
2584        }
2585
2586        let mut encoding = None;
2587        let mut memory = None;
2588        let mut realloc = None;
2589        let mut post_return = None;
2590        let mut is_async = false;
2591        let mut callback = None;
2592        let mut core_type = None;
2593        let mut gc = false;
2594
2595        for option in options {
2596            match option {
2597                CanonicalOption::UTF8 | CanonicalOption::UTF16 | CanonicalOption::CompactUTF16 => {
2598                    match encoding {
2599                        Some(existing) => {
2600                            bail!(
2601                                offset,
2602                                "canonical encoding option `{existing}` conflicts with option `{}`",
2603                                display(*option),
2604                            )
2605                        }
2606                        None => {
2607                            encoding = Some(match option {
2608                                CanonicalOption::UTF8 => StringEncoding::Utf8,
2609                                CanonicalOption::UTF16 => StringEncoding::Utf16,
2610                                CanonicalOption::CompactUTF16 => StringEncoding::CompactUtf16,
2611                                _ => unreachable!(),
2612                            });
2613                        }
2614                    }
2615                }
2616                CanonicalOption::Memory(idx) => {
2617                    memory = match memory {
2618                        None => {
2619                            self.cabi_memory_at(*idx, offset)?;
2620                            Some(*idx)
2621                        }
2622                        Some(_) => {
2623                            return Err(BinaryReaderError::new(
2624                                "canonical option `memory` is specified more than once",
2625                                offset,
2626                            ));
2627                        }
2628                    }
2629                }
2630                CanonicalOption::Realloc(idx) => {
2631                    realloc = match realloc {
2632                        None => {
2633                            let ty_id = self.core_function_at(*idx, offset)?;
2634                            let func_ty = types[ty_id].unwrap_func();
2635                            if func_ty.params()
2636                                != [ValType::I32, ValType::I32, ValType::I32, ValType::I32]
2637                                || func_ty.results() != [ValType::I32]
2638                            {
2639                                return Err(BinaryReaderError::new(
2640                                    "canonical option `realloc` uses a core function with an incorrect signature",
2641                                    offset,
2642                                ));
2643                            }
2644                            Some(*idx)
2645                        }
2646                        Some(_) => {
2647                            return Err(BinaryReaderError::new(
2648                                "canonical option `realloc` is specified more than once",
2649                                offset,
2650                            ));
2651                        }
2652                    }
2653                }
2654                CanonicalOption::PostReturn(idx) => {
2655                    post_return = match post_return {
2656                        None => Some(*idx),
2657                        Some(_) => {
2658                            return Err(BinaryReaderError::new(
2659                                "canonical option `post-return` is specified more than once",
2660                                offset,
2661                            ));
2662                        }
2663                    }
2664                }
2665                CanonicalOption::Async => {
2666                    if is_async {
2667                        return Err(BinaryReaderError::new(
2668                            "canonical option `async` is specified more than once",
2669                            offset,
2670                        ));
2671                    } else {
2672                        if !self.features.cm_async() {
2673                            bail!(
2674                                offset,
2675                                "canonical option `async` requires the component model async feature"
2676                            );
2677                        }
2678
2679                        is_async = true;
2680                    }
2681                }
2682                CanonicalOption::Callback(idx) => {
2683                    callback = match callback {
2684                        None => Some(*idx),
2685                        Some(_) => {
2686                            return Err(BinaryReaderError::new(
2687                                "canonical option `callback` is specified more than once",
2688                                offset,
2689                            ));
2690                        }
2691                    }
2692                }
2693                CanonicalOption::CoreType(idx) => {
2694                    core_type = match core_type {
2695                        None => {
2696                            if !self.features.cm_gc() {
2697                                bail!(
2698                                    offset,
2699                                    "canonical option `core type` requires the component model gc feature"
2700                                )
2701                            }
2702                            let ty = match self.core_type_at(*idx, offset)? {
2703                                ComponentCoreTypeId::Sub(ty) => ty,
2704                                ComponentCoreTypeId::Module(_) => {
2705                                    return Err(BinaryReaderError::new(
2706                                        "canonical option `core type` must reference a core function \
2707                                     type",
2708                                        offset,
2709                                    ));
2710                                }
2711                            };
2712                            match &types[ty].composite_type.inner {
2713                                CompositeInnerType::Func(_) => {}
2714                                CompositeInnerType::Array(_)
2715                                | CompositeInnerType::Struct(_)
2716                                | CompositeInnerType::Cont(_) => {
2717                                    return Err(BinaryReaderError::new(
2718                                        "canonical option `core type` must reference a core function \
2719                                     type",
2720                                        offset,
2721                                    ));
2722                                }
2723                            }
2724                            Some(ty)
2725                        }
2726                        Some(_) => {
2727                            return Err(BinaryReaderError::new(
2728                                "canonical option `core type` is specified more than once",
2729                                offset,
2730                            ));
2731                        }
2732                    };
2733                }
2734                CanonicalOption::Gc => {
2735                    if gc {
2736                        return Err(BinaryReaderError::new(
2737                            "canonical option `gc` is specified more than once",
2738                            offset,
2739                        ));
2740                    }
2741                    if !self.features.cm_gc() {
2742                        return Err(BinaryReaderError::new(
2743                            "canonical option `gc` requires the `cm-gc` feature",
2744                            offset,
2745                        ));
2746                    }
2747                    gc = true;
2748                }
2749            }
2750        }
2751
2752        let string_encoding = encoding.unwrap_or_default();
2753
2754        let concurrency = match (is_async, callback, post_return.is_some()) {
2755            (false, Some(_), _) => {
2756                bail!(offset, "cannot specify callback without async")
2757            }
2758            (true, _, true) => {
2759                bail!(offset, "cannot specify post-return function in async")
2760            }
2761            (false, None, _) => Concurrency::Sync,
2762            (true, callback, false) => Concurrency::Async { callback },
2763        };
2764
2765        if !gc && core_type.is_some() {
2766            bail!(offset, "cannot specify `core-type` without `gc`")
2767        }
2768
2769        Ok(CanonicalOptions {
2770            string_encoding,
2771            memory,
2772            realloc,
2773            post_return,
2774            concurrency,
2775            core_type,
2776            gc,
2777        })
2778    }
2779
2780    fn check_type_ref(
2781        &mut self,
2782        ty: &ComponentTypeRef,
2783        types: &mut TypeAlloc,
2784        offset: usize,
2785    ) -> Result<ComponentEntityType> {
2786        Ok(match ty {
2787            ComponentTypeRef::Module(index) => {
2788                let id = self.core_type_at(*index, offset)?;
2789                match id {
2790                    ComponentCoreTypeId::Sub(_) => {
2791                        bail!(offset, "core type index {index} is not a module type")
2792                    }
2793                    ComponentCoreTypeId::Module(id) => ComponentEntityType::Module(id),
2794                }
2795            }
2796            ComponentTypeRef::Func(index) => {
2797                let id = self.component_type_at(*index, offset)?;
2798                match id {
2799                    ComponentAnyTypeId::Func(id) => ComponentEntityType::Func(id),
2800                    _ => bail!(offset, "type index {index} is not a function type"),
2801                }
2802            }
2803            ComponentTypeRef::Value(ty) => {
2804                self.check_value_support(offset)?;
2805                let ty = match ty {
2806                    crate::ComponentValType::Primitive(ty) => ComponentValType::Primitive(*ty),
2807                    crate::ComponentValType::Type(index) => {
2808                        ComponentValType::Type(self.defined_type_at(*index, offset)?)
2809                    }
2810                };
2811                ComponentEntityType::Value(ty)
2812            }
2813            ComponentTypeRef::Type(TypeBounds::Eq(index)) => {
2814                let referenced = self.component_type_at(*index, offset)?;
2815                let created = types.with_unique(referenced);
2816                ComponentEntityType::Type {
2817                    referenced,
2818                    created,
2819                }
2820            }
2821            ComponentTypeRef::Type(TypeBounds::SubResource) => {
2822                let id = types.alloc_resource_id();
2823                ComponentEntityType::Type {
2824                    referenced: id.into(),
2825                    created: id.into(),
2826                }
2827            }
2828            ComponentTypeRef::Instance(index) => {
2829                let id = self.component_type_at(*index, offset)?;
2830                match id {
2831                    ComponentAnyTypeId::Instance(id) => ComponentEntityType::Instance(id),
2832                    _ => bail!(offset, "type index {index} is not an instance type"),
2833                }
2834            }
2835            ComponentTypeRef::Component(index) => {
2836                let id = self.component_type_at(*index, offset)?;
2837                match id {
2838                    ComponentAnyTypeId::Component(id) => ComponentEntityType::Component(id),
2839                    _ => bail!(offset, "type index {index} is not a component type"),
2840                }
2841            }
2842        })
2843    }
2844
2845    pub fn export_to_entity_type(
2846        &mut self,
2847        export: &crate::ComponentExport,
2848        types: &mut TypeAlloc,
2849        offset: usize,
2850    ) -> Result<ComponentEntityType> {
2851        let actual = match export.kind {
2852            ComponentExternalKind::Module => {
2853                ComponentEntityType::Module(self.module_at(export.index, offset)?)
2854            }
2855            ComponentExternalKind::Func => {
2856                ComponentEntityType::Func(self.function_at(export.index, offset)?)
2857            }
2858            ComponentExternalKind::Value => {
2859                self.check_value_support(offset)?;
2860                ComponentEntityType::Value(*self.value_at(export.index, offset)?)
2861            }
2862            ComponentExternalKind::Type => {
2863                let referenced = self.component_type_at(export.index, offset)?;
2864                let created = types.with_unique(referenced);
2865                ComponentEntityType::Type {
2866                    referenced,
2867                    created,
2868                }
2869            }
2870            ComponentExternalKind::Instance => {
2871                ComponentEntityType::Instance(self.instance_at(export.index, offset)?)
2872            }
2873            ComponentExternalKind::Component => {
2874                ComponentEntityType::Component(self.component_at(export.index, offset)?)
2875            }
2876        };
2877
2878        let ascribed = match &export.ty {
2879            Some(ty) => self.check_type_ref(ty, types, offset)?,
2880            None => return Ok(actual),
2881        };
2882
2883        SubtypeCx::new(types, types)
2884            .component_entity_type(&actual, &ascribed, offset)
2885            .with_context(|| "ascribed type of export is not compatible with item's type")?;
2886
2887        Ok(ascribed)
2888    }
2889
2890    fn create_module_type(
2891        components: &[Self],
2892        decls: Vec<crate::ModuleTypeDeclaration>,
2893        types: &mut TypeAlloc,
2894        offset: usize,
2895    ) -> Result<ModuleType> {
2896        let mut state = Module::new(components[0].features);
2897
2898        for decl in decls {
2899            match decl {
2900                crate::ModuleTypeDeclaration::Type(rec) => {
2901                    state.add_types(rec, types, offset, true)?;
2902                }
2903                crate::ModuleTypeDeclaration::Export { name, mut ty } => {
2904                    let ty = state.check_type_ref(&mut ty, types, offset)?;
2905                    state.add_export(name, ty, offset, true, types)?;
2906                }
2907                crate::ModuleTypeDeclaration::OuterAlias { kind, count, index } => {
2908                    match kind {
2909                        crate::OuterAliasKind::Type => {
2910                            let ty = if count == 0 {
2911                                // Local alias, check the local module state
2912                                ComponentCoreTypeId::Sub(state.type_id_at(index, offset)?)
2913                            } else {
2914                                // Otherwise, check the enclosing component state
2915                                let component =
2916                                    Self::check_alias_count(components, count - 1, offset)?;
2917                                component.core_type_at(index, offset)?
2918                            };
2919
2920                            check_max(state.types.len(), 1, MAX_WASM_TYPES, "types", offset)?;
2921
2922                            match ty {
2923                                ComponentCoreTypeId::Sub(ty) => state.types.push(ty),
2924                                // TODO https://github.com/WebAssembly/component-model/issues/265
2925                                ComponentCoreTypeId::Module(_) => bail!(
2926                                    offset,
2927                                    "not implemented: aliasing core module types into a core \
2928                                     module's types index space"
2929                                ),
2930                            }
2931                        }
2932                    }
2933                }
2934                crate::ModuleTypeDeclaration::Import(import) => {
2935                    state.add_import(import, types, offset)?;
2936                }
2937            }
2938        }
2939
2940        let imports = state.imports_for_module_type(offset)?;
2941
2942        Ok(ModuleType {
2943            info: TypeInfo::core(state.type_size),
2944            imports,
2945            exports: state.exports,
2946        })
2947    }
2948
2949    fn create_component_type(
2950        components: &mut Vec<Self>,
2951        decls: Vec<crate::ComponentTypeDeclaration>,
2952        types: &mut TypeAlloc,
2953        offset: usize,
2954    ) -> Result<ComponentType> {
2955        let features = components[0].features;
2956        components.push(ComponentState::new(ComponentKind::ComponentType, features));
2957
2958        for decl in decls {
2959            match decl {
2960                crate::ComponentTypeDeclaration::CoreType(ty) => {
2961                    Self::add_core_type(components, ty, types, offset, true)?;
2962                }
2963                crate::ComponentTypeDeclaration::Type(ty) => {
2964                    Self::add_type(components, ty, types, offset, true)?;
2965                }
2966                crate::ComponentTypeDeclaration::Export { name, ty } => {
2967                    let current = components.last_mut().unwrap();
2968                    let ty = current.check_type_ref(&ty, types, offset)?;
2969                    current.add_export(name, ty, types, offset, true)?;
2970                }
2971                crate::ComponentTypeDeclaration::Import(import) => {
2972                    components
2973                        .last_mut()
2974                        .unwrap()
2975                        .add_import(import, types, offset)?;
2976                }
2977                crate::ComponentTypeDeclaration::Alias(alias) => {
2978                    Self::add_alias(components, alias, types, offset)?;
2979                }
2980            };
2981        }
2982
2983        components.pop().unwrap().finish(types, offset)
2984    }
2985
2986    fn create_instance_type(
2987        components: &mut Vec<Self>,
2988        decls: Vec<crate::InstanceTypeDeclaration>,
2989        types: &mut TypeAlloc,
2990        offset: usize,
2991    ) -> Result<ComponentInstanceType> {
2992        let features = components[0].features;
2993        components.push(ComponentState::new(ComponentKind::InstanceType, features));
2994
2995        for decl in decls {
2996            match decl {
2997                crate::InstanceTypeDeclaration::CoreType(ty) => {
2998                    Self::add_core_type(components, ty, types, offset, true)?;
2999                }
3000                crate::InstanceTypeDeclaration::Type(ty) => {
3001                    Self::add_type(components, ty, types, offset, true)?;
3002                }
3003                crate::InstanceTypeDeclaration::Export { name, ty } => {
3004                    let current = components.last_mut().unwrap();
3005                    let ty = current.check_type_ref(&ty, types, offset)?;
3006                    current.add_export(name, ty, types, offset, true)?;
3007                }
3008                crate::InstanceTypeDeclaration::Alias(alias) => {
3009                    Self::add_alias(components, alias, types, offset)?;
3010                }
3011            };
3012        }
3013
3014        let mut state = components.pop().unwrap();
3015
3016        assert!(state.imported_resources.is_empty());
3017
3018        Ok(ComponentInstanceType {
3019            info: state.type_info,
3020
3021            // The defined resources for this instance type are those listed on
3022            // the component state. The path to each defined resource is
3023            // guaranteed to live within the `explicit_resources` map since,
3024            // when in the type context, the introduction of any defined
3025            // resource must have been done with `(export "x" (type (sub
3026            // resource)))` which, in a sense, "fuses" the introduction of the
3027            // variable with the export. This means that all defined resources,
3028            // if any, should be guaranteed to have an `explicit_resources` path
3029            // listed.
3030            defined_resources: mem::take(&mut state.defined_resources)
3031                .into_iter()
3032                .map(|(id, rep)| {
3033                    assert!(rep.is_none());
3034                    id
3035                })
3036                .collect(),
3037
3038            // The map of what resources are explicitly exported and where
3039            // they're exported is plumbed through as-is.
3040            explicit_resources: mem::take(&mut state.explicit_resources),
3041
3042            exports: mem::take(&mut state.exports),
3043        })
3044    }
3045
3046    fn create_function_type(
3047        &self,
3048        ty: crate::ComponentFuncType,
3049        types: &TypeList,
3050        offset: usize,
3051    ) -> Result<ComponentFuncType> {
3052        let mut info = TypeInfo::new();
3053
3054        let mut set = Set::default();
3055        set.reserve(core::cmp::max(
3056            ty.params.len(),
3057            usize::from(ty.result.is_some()),
3058        ));
3059
3060        let params = ty
3061            .params
3062            .iter()
3063            .map(|(name, ty)| {
3064                let name: &KebabStr = to_kebab_str(name, "function parameter", offset)?;
3065                if !set.insert(name) {
3066                    bail!(
3067                        offset,
3068                        "function parameter name `{name}` conflicts with previous parameter name `{prev}`",
3069                        prev = set.get(&name).unwrap(),
3070                    );
3071                }
3072
3073                let ty = self.create_component_val_type(*ty, offset)?;
3074                info.combine(ty.info(types), offset)?;
3075                Ok((name.to_owned(), ty))
3076            })
3077            .collect::<Result<_>>()?;
3078
3079        set.clear();
3080
3081        let result = ty
3082            .result
3083            .map(|ty| {
3084                let ty = self.create_component_val_type(ty, offset)?;
3085                let ty_info = ty.info(types);
3086                if ty_info.contains_borrow() {
3087                    bail!(offset, "function result cannot contain a `borrow` type");
3088                }
3089                info.combine(ty.info(types), offset)?;
3090                Ok(ty)
3091            })
3092            .transpose()?;
3093
3094        Ok(ComponentFuncType {
3095            info,
3096            params,
3097            result,
3098        })
3099    }
3100
3101    fn instantiate_core_module(
3102        &self,
3103        module_index: u32,
3104        module_args: Vec<crate::InstantiationArg>,
3105        types: &mut TypeAlloc,
3106        offset: usize,
3107    ) -> Result<ComponentCoreInstanceTypeId> {
3108        fn insert_arg<'a>(
3109            name: &'a str,
3110            arg: &'a InstanceType,
3111            args: &mut IndexMap<&'a str, &'a InstanceType>,
3112            offset: usize,
3113        ) -> Result<()> {
3114            if args.insert(name, arg).is_some() {
3115                bail!(
3116                    offset,
3117                    "duplicate module instantiation argument named `{name}`"
3118                );
3119            }
3120
3121            Ok(())
3122        }
3123
3124        let module_type_id = self.module_at(module_index, offset)?;
3125        let mut args = IndexMap::default();
3126
3127        // Populate the arguments
3128        for module_arg in module_args {
3129            match module_arg.kind {
3130                InstantiationArgKind::Instance => {
3131                    let instance_type = &types[self.core_instance_at(module_arg.index, offset)?];
3132                    insert_arg(module_arg.name, instance_type, &mut args, offset)?;
3133                }
3134            }
3135        }
3136
3137        // Validate the arguments
3138        let module_type = &types[module_type_id];
3139        let cx = SubtypeCx::new(types, types);
3140        for ((module, name), expected) in module_type.imports.iter() {
3141            let instance = args.get(module.as_str()).ok_or_else(|| {
3142                format_err!(
3143                    offset,
3144                    "missing module instantiation argument named `{module}`"
3145                )
3146            })?;
3147
3148            let arg = instance
3149                .internal_exports(types)
3150                .get(name.as_str())
3151                .ok_or_else(|| {
3152                    format_err!(
3153                        offset,
3154                        "module instantiation argument `{module}` does not \
3155                         export an item named `{name}`",
3156                    )
3157                })?;
3158
3159            cx.entity_type(arg, expected, offset).with_context(|| {
3160                format!(
3161                    "type mismatch for export `{name}` of module \
3162                     instantiation argument `{module}`"
3163                )
3164            })?;
3165        }
3166
3167        let mut info = TypeInfo::new();
3168        for (_, ty) in module_type.exports.iter() {
3169            info.combine(ty.info(types), offset)?;
3170        }
3171
3172        Ok(types.push_ty(InstanceType {
3173            info,
3174            kind: CoreInstanceTypeKind::Instantiated(module_type_id),
3175        }))
3176    }
3177
3178    fn instantiate_component(
3179        &mut self,
3180        component_index: u32,
3181        component_args: Vec<crate::ComponentInstantiationArg>,
3182        types: &mut TypeAlloc,
3183        offset: usize,
3184    ) -> Result<ComponentInstanceTypeId> {
3185        let component_type_id = self.component_at(component_index, offset)?;
3186        let mut args = IndexMap::default();
3187
3188        // Populate the arguments
3189        for component_arg in component_args {
3190            let ty = match component_arg.kind {
3191                ComponentExternalKind::Module => {
3192                    ComponentEntityType::Module(self.module_at(component_arg.index, offset)?)
3193                }
3194                ComponentExternalKind::Component => {
3195                    ComponentEntityType::Component(self.component_at(component_arg.index, offset)?)
3196                }
3197                ComponentExternalKind::Instance => {
3198                    ComponentEntityType::Instance(self.instance_at(component_arg.index, offset)?)
3199                }
3200                ComponentExternalKind::Func => {
3201                    ComponentEntityType::Func(self.function_at(component_arg.index, offset)?)
3202                }
3203                ComponentExternalKind::Value => {
3204                    self.check_value_support(offset)?;
3205                    ComponentEntityType::Value(*self.value_at(component_arg.index, offset)?)
3206                }
3207                ComponentExternalKind::Type => {
3208                    let ty = self.component_type_at(component_arg.index, offset)?;
3209                    ComponentEntityType::Type {
3210                        referenced: ty,
3211                        created: ty,
3212                    }
3213                }
3214            };
3215            match args.entry(component_arg.name.to_string()) {
3216                Entry::Occupied(e) => {
3217                    bail!(
3218                        offset,
3219                        "instantiation argument `{name}` conflicts with previous argument `{prev}`",
3220                        prev = e.key(),
3221                        name = component_arg.name
3222                    );
3223                }
3224                Entry::Vacant(e) => {
3225                    e.insert(ty);
3226                }
3227            }
3228        }
3229
3230        // Here comes the fun part of the component model, we're instantiating
3231        // the component with type `component_type_id` with the `args`
3232        // specified. Easy enough!
3233        //
3234        // This operation, however, is one of the lynchpins of safety in the
3235        // component model. Additionally what this ends up implementing ranges
3236        // from "well just check the types are equal" to "let's have a
3237        // full-blown ML-style module type system in the component model". There
3238        // are primarily two major tricky pieces to the component model which
3239        // make this operation, instantiating components, hard:
3240        //
3241        // 1. Components can import and exports other components. This means
3242        //    that arguments to instantiation are along the lines of functions
3243        //    being passed to functions or similar. Effectively this means that
3244        //    the term "variance" comes into play with either contravariance
3245        //    or covariance depending on where you are in typechecking. This is
3246        //    one of the main rationales, however, that this check below is a
3247        //    check for subtyping as opposed to exact type equivalence. For
3248        //    example an instance that exports something is a subtype of an
3249        //    instance that exports nothing. Components get a bit trick since
3250        //    they both have imports and exports. My way of thinking about it
3251        //    is "who's asking for what". If you're asking for imports then
3252        //    I need to at least supply those imports, but I can possibly
3253        //    supply more. If you're asking for a thing which you'll give a set
3254        //    of imports, then I can give you something which takes less imports
3255        //    because what you give still suffices. (things like that). The
3256        //    real complication with components, however, comes with...
3257        //
3258        // 2. Resources. Resources in the component model are akin to "abstract
3259        //    types". They're not abstract in the sense that they have no
3260        //    representation, they're always backed by a 32-bit integer right
3261        //    now. Instead they're abstract in the sense that some components
3262        //    aren't allowed to understand the representation of a resource.
3263        //    For example if you import a resource you can't get the underlying
3264        //    internals of it. Furthermore the resource is strictly tracked
3265        //    within the component with `own` and `borrow` runtime semantics.
3266        //    The hardest part about resources, though, is handling them as
3267        //    part of instantiation and subtyping.
3268        //
3269        //    For example one major aspect of resources is that if a component
3270        //    exports a resource then each instantiation of the component
3271        //    produces a fresh resource type. This means that the type recorded
3272        //    for the instantiation here can't simply be "I instantiated
3273        //    component X" since in such a situation the type of all
3274        //    instantiations would be the same, which they aren't.
3275        //
3276        //    This sort of subtlety comes up quite frequently for resources.
3277        //    This file contains references to `imported_resources` and
3278        //    `defined_resources` for example which refer to the formal
3279        //    nature of components and their abstract variables. Specifically
3280        //    for instantiation though we're eventually faced with the problem
3281        //    of subtype checks where resource subtyping is defined as "does
3282        //    your id equal mine". Naively implemented that means anything with
3283        //    resources isn't subtypes of anything else since resource ids are
3284        //    unique between components. Instead what actually needs to happen
3285        //    is types need to be substituted.
3286        //
3287        // Much of the complexity here is not actually apparent here in this
3288        // literal one function. Instead it's spread out across validation
3289        // in this file and type-checking in the `types.rs` module. Note that
3290        // the "spread out" nature isn't because we're bad maintainers
3291        // (hopefully), but rather it's quite infectious how many parts need
3292        // to handle resources and account for defined/imported variables.
3293        //
3294        // For example only one subtyping method is called here where `args` is
3295        // passed in. This method is quite recursive in its nature though and
3296        // will internally touch all the fields that this file maintains to
3297        // end up putting into various bits and pieces of type information.
3298        //
3299        // Unfortunately there's probably not really a succinct way to read
3300        // this method and understand everything. If you've written ML module
3301        // type systems this will probably look quite familiar, but otherwise
3302        // the whole system is not really easily approachable at this time. It's
3303        // hoped in the future that there's a formalism to refer to which will
3304        // make things more clear as the code would be able to reference this
3305        // hypothetical formalism. Until that's the case, though, these
3306        // comments are hopefully enough when augmented with communication with
3307        // the authors.
3308
3309        let component_type = &types[component_type_id];
3310        let mut exports = component_type.exports.clone();
3311        let mut info = TypeInfo::new();
3312        for (_, ty) in component_type.exports.iter() {
3313            info.combine(ty.info(types), offset)?;
3314        }
3315
3316        // Perform the subtype check that `args` matches the imports of
3317        // `component_type_id`. The result of this subtype check is the
3318        // production of a mapping of resource types from the imports to the
3319        // arguments provided. This is a substitution map which is then used
3320        // below to perform a substitution into the exports of the instance
3321        // since the types of the exports are now in terms of whatever was
3322        // supplied as imports.
3323        let mut mapping = SubtypeCx::new(types, types).open_instance_type(
3324            &args,
3325            component_type_id,
3326            ExternKind::Import,
3327            offset,
3328        )?;
3329
3330        // Part of the instantiation of a component is that all of its
3331        // defined resources become "fresh" on each instantiation. This
3332        // means that each instantiation of a component gets brand new type
3333        // variables representing its defined resources, modeling that each
3334        // instantiation produces distinct types. The freshening is performed
3335        // here by allocating new ids and inserting them into `mapping`.
3336        //
3337        // Note that technically the `mapping` from subtyping should be applied
3338        // first and then the mapping for freshening should be applied
3339        // afterwards. The keys of the map from subtyping are the imported
3340        // resources from this component which are disjoint from its defined
3341        // resources. That means it should be possible to place everything
3342        // into one large map which maps from:
3343        //
3344        // * the component's imported resources go to whatever was explicitly
3345        //   supplied in the import map
3346        // * the component's defined resources go to fresh new resources
3347        //
3348        // These two remapping operations can then get folded into one by
3349        // placing everything in the same `mapping` and using that for a remap
3350        // only once.
3351        let fresh_defined_resources = (0..component_type.defined_resources.len())
3352            .map(|_| types.alloc_resource_id().resource())
3353            .collect::<IndexSet<_>>();
3354        let component_type = &types[component_type_id];
3355        for ((old, _path), new) in component_type
3356            .defined_resources
3357            .iter()
3358            .zip(&fresh_defined_resources)
3359        {
3360            let prev = mapping.resources.insert(*old, *new);
3361            assert!(prev.is_none());
3362        }
3363
3364        // Perform the remapping operation over all the exports that will be
3365        // listed for the final instance type. Note that this is performed
3366        // both for all the export types in addition to the explicitly exported
3367        // resources list.
3368        //
3369        // Note that this is a crucial step of the instantiation process which
3370        // is intentionally transforming the type of a component based on the
3371        // variables provided by imports and additionally ensuring that all
3372        // references to the component's defined resources are rebound to the
3373        // fresh ones introduced just above.
3374        for entity in exports.values_mut() {
3375            types.remap_component_entity(entity, &mut mapping);
3376        }
3377        let component_type = &types[component_type_id];
3378        let explicit_resources = component_type
3379            .explicit_resources
3380            .iter()
3381            .map(|(id, path)| {
3382                (
3383                    mapping.resources.get(id).copied().unwrap_or(*id),
3384                    path.clone(),
3385                )
3386            })
3387            .collect::<IndexMap<_, _>>();
3388
3389        // Technically in the last formalism that was consulted in writing this
3390        // implementation there are two further steps that are part of the
3391        // instantiation process:
3392        //
3393        // 1. The set of defined resources from the instance created, which are
3394        //    added to the outer component, is the subset of the instance's
3395        //    original defined resources and the free variables of the exports.
3396        //
3397        // 2. Each element of this subset is required to be "explicit in" the
3398        //    instance, or otherwise explicitly exported somewhere within the
3399        //    instance.
3400        //
3401        // With the syntactic structure of the component model, however, neither
3402        // of these conditions should be necessary. The main reason for this is
3403        // that this function is specifically dealing with instantiation of
3404        // components which should already have these properties validated
3405        // about them. Subsequently we shouldn't have to re-check them.
3406        //
3407        // In debug mode, however, do a sanity check.
3408        if cfg!(debug_assertions) {
3409            let mut free = IndexSet::default();
3410            for ty in exports.values() {
3411                types.free_variables_component_entity(ty, &mut free);
3412            }
3413            assert!(fresh_defined_resources.is_subset(&free));
3414            for resource in fresh_defined_resources.iter() {
3415                assert!(explicit_resources.contains_key(resource));
3416            }
3417        }
3418
3419        // And as the final step of the instantiation process all of the
3420        // new defined resources from this component instantiation are moved
3421        // onto `self`. Note that concrete instances never have defined
3422        // resources (see more comments in `instantiate_exports`) so the
3423        // `defined_resources` listing in the final type is always empty. This
3424        // represents how by having a concrete instance the definitions
3425        // referred to in that instance are now problems for the outer
3426        // component rather than the inner instance since the instance is bound
3427        // to the component.
3428        //
3429        // All defined resources here have no known representation, so they're
3430        // all listed with `None`. Also note that none of the resources were
3431        // exported yet so `self.explicit_resources` is not updated yet. If
3432        // this instance is exported, however, it'll consult the type's
3433        // `explicit_resources` array and use that appropriately.
3434        for resource in fresh_defined_resources {
3435            self.defined_resources.insert(resource, None);
3436        }
3437
3438        Ok(types.push_ty(ComponentInstanceType {
3439            info,
3440            defined_resources: Default::default(),
3441            explicit_resources,
3442            exports,
3443        }))
3444    }
3445
3446    fn instantiate_component_exports(
3447        &mut self,
3448        exports: Vec<crate::ComponentExport>,
3449        types: &mut TypeAlloc,
3450        offset: usize,
3451    ) -> Result<ComponentInstanceTypeId> {
3452        let mut info = TypeInfo::new();
3453        let mut inst_exports = IndexMap::default();
3454        let mut explicit_resources = IndexMap::default();
3455        let mut export_names = IndexSet::default();
3456
3457        // NB: It's intentional that this context is empty since no indices are
3458        // introduced in the bag-of-exports construct which means there's no
3459        // way syntactically to register something inside of this.
3460        let names = ComponentNameContext::default();
3461
3462        for export in exports {
3463            assert!(export.ty.is_none());
3464            let ty = match export.kind {
3465                ComponentExternalKind::Module => {
3466                    ComponentEntityType::Module(self.module_at(export.index, offset)?)
3467                }
3468                ComponentExternalKind::Component => {
3469                    ComponentEntityType::Component(self.component_at(export.index, offset)?)
3470                }
3471                ComponentExternalKind::Instance => {
3472                    let ty = self.instance_at(export.index, offset)?;
3473
3474                    // When an instance is exported from an instance then
3475                    // all explicitly exported resources on the sub-instance are
3476                    // now also listed as exported resources on the outer
3477                    // instance, just with one more element in their path.
3478                    explicit_resources.extend(types[ty].explicit_resources.iter().map(
3479                        |(id, path)| {
3480                            let mut new_path = vec![inst_exports.len()];
3481                            new_path.extend(path);
3482                            (*id, new_path)
3483                        },
3484                    ));
3485                    ComponentEntityType::Instance(ty)
3486                }
3487                ComponentExternalKind::Func => {
3488                    ComponentEntityType::Func(self.function_at(export.index, offset)?)
3489                }
3490                ComponentExternalKind::Value => {
3491                    self.check_value_support(offset)?;
3492                    ComponentEntityType::Value(*self.value_at(export.index, offset)?)
3493                }
3494                ComponentExternalKind::Type => {
3495                    let ty = self.component_type_at(export.index, offset)?;
3496                    // If this is an export of a resource type be sure to
3497                    // record that in the explicit list with the appropriate
3498                    // path because if this instance ends up getting used
3499                    // it'll count towards the "explicit in" check.
3500                    if let ComponentAnyTypeId::Resource(id) = ty {
3501                        explicit_resources.insert(id.resource(), vec![inst_exports.len()]);
3502                    }
3503                    ComponentEntityType::Type {
3504                        referenced: ty,
3505                        // The created type index here isn't used anywhere
3506                        // in index spaces because a "bag of exports"
3507                        // doesn't build up its own index spaces. Just fill
3508                        // in the same index here in this case as what's
3509                        // referenced.
3510                        created: ty,
3511                    }
3512                }
3513            };
3514
3515            names.validate_extern(
3516                export.name.0,
3517                ExternKind::Export,
3518                &ty,
3519                types,
3520                offset,
3521                &mut export_names,
3522                &mut inst_exports,
3523                &mut info,
3524                &self.features,
3525            )?;
3526        }
3527
3528        Ok(types.push_ty(ComponentInstanceType {
3529            info,
3530            explicit_resources,
3531            exports: inst_exports,
3532
3533            // NB: the list of defined resources for this instance itself
3534            // is always empty. Even if this instance exports resources,
3535            // it's empty.
3536            //
3537            // The reason for this is a bit subtle. The general idea, though, is
3538            // that the defined resources list here is only used for instance
3539            // types that are sort of "floating around" and haven't actually
3540            // been attached to something yet. For example when an instance type
3541            // is simply declared it can have defined resources introduced
3542            // through `(export "name" (type (sub resource)))`. These
3543            // definitions, however, are local to the instance itself and aren't
3544            // defined elsewhere.
3545            //
3546            // Here, though, no new definitions were introduced. The instance
3547            // created here is a "bag of exports" which could only refer to
3548            // preexisting items. This means that inherently no new resources
3549            // were created so there's nothing to put in this list. Any
3550            // resources referenced by the instance must be bound by the outer
3551            // component context or further above.
3552            //
3553            // Furthermore, however, actual instances of instances, which this
3554            // is, aren't allowed to have defined resources. Instead the
3555            // resources would have to be injected into the outer component
3556            // enclosing the instance. That means that even if bag-of-exports
3557            // could declare a new resource then the resource would be moved
3558            // from here to `self.defined_resources`. This doesn't exist at this
3559            // time, though, so this still remains empty and
3560            // `self.defined_resources` remains unperturbed.
3561            defined_resources: Default::default(),
3562        }))
3563    }
3564
3565    fn instantiate_core_exports(
3566        &mut self,
3567        exports: Vec<crate::Export>,
3568        types: &mut TypeAlloc,
3569        offset: usize,
3570    ) -> Result<ComponentCoreInstanceTypeId> {
3571        fn insert_export(
3572            types: &TypeList,
3573            name: &str,
3574            export: EntityType,
3575            exports: &mut IndexMap<String, EntityType>,
3576            info: &mut TypeInfo,
3577            offset: usize,
3578        ) -> Result<()> {
3579            info.combine(export.info(types), offset)?;
3580
3581            if exports.insert(name.to_string(), export).is_some() {
3582                bail!(
3583                    offset,
3584                    "duplicate instantiation export name `{name}` already defined",
3585                )
3586            }
3587
3588            Ok(())
3589        }
3590
3591        let mut info = TypeInfo::new();
3592        let mut inst_exports = IndexMap::default();
3593        for export in exports {
3594            match export.kind {
3595                ExternalKind::Func => {
3596                    insert_export(
3597                        types,
3598                        export.name,
3599                        EntityType::Func(self.core_function_at(export.index, offset)?),
3600                        &mut inst_exports,
3601                        &mut info,
3602                        offset,
3603                    )?;
3604                }
3605                ExternalKind::Table => insert_export(
3606                    types,
3607                    export.name,
3608                    EntityType::Table(*self.table_at(export.index, offset)?),
3609                    &mut inst_exports,
3610                    &mut info,
3611                    offset,
3612                )?,
3613                ExternalKind::Memory => insert_export(
3614                    types,
3615                    export.name,
3616                    EntityType::Memory(*self.memory_at(export.index, offset)?),
3617                    &mut inst_exports,
3618                    &mut info,
3619                    offset,
3620                )?,
3621                ExternalKind::Global => {
3622                    insert_export(
3623                        types,
3624                        export.name,
3625                        EntityType::Global(*self.global_at(export.index, offset)?),
3626                        &mut inst_exports,
3627                        &mut info,
3628                        offset,
3629                    )?;
3630                }
3631                ExternalKind::Tag => {
3632                    if !self.features.exceptions() {
3633                        bail!(offset, "exceptions proposal not enabled");
3634                    }
3635                    insert_export(
3636                        types,
3637                        export.name,
3638                        EntityType::Tag(self.tag_at(export.index, offset)?),
3639                        &mut inst_exports,
3640                        &mut info,
3641                        offset,
3642                    )?
3643                }
3644            }
3645        }
3646
3647        Ok(types.push_ty(InstanceType {
3648            info,
3649            kind: CoreInstanceTypeKind::Exports(inst_exports),
3650        }))
3651    }
3652
3653    fn alias_core_instance_export(
3654        &mut self,
3655        instance_index: u32,
3656        kind: ExternalKind,
3657        name: &str,
3658        types: &TypeList,
3659        offset: usize,
3660    ) -> Result<()> {
3661        macro_rules! push_module_export {
3662            ($expected:path, $collection:ident, $ty:literal) => {{
3663                match self.core_instance_export(instance_index, name, types, offset)? {
3664                    $expected(ty) => {
3665                        self.$collection.push(*ty);
3666                    }
3667                    _ => {
3668                        bail!(
3669                            offset,
3670                            "export `{name}` for core instance {instance_index} is not a {}",
3671                            $ty
3672                        )
3673                    }
3674                }
3675            }};
3676        }
3677
3678        match kind {
3679            ExternalKind::Func => {
3680                check_max(
3681                    self.function_count(),
3682                    1,
3683                    MAX_WASM_FUNCTIONS,
3684                    "functions",
3685                    offset,
3686                )?;
3687                push_module_export!(EntityType::Func, core_funcs, "function");
3688            }
3689            ExternalKind::Table => {
3690                check_max(
3691                    self.core_tables.len(),
3692                    1,
3693                    MAX_CORE_INDEX_SPACE_ITEMS,
3694                    "tables",
3695                    offset,
3696                )?;
3697                push_module_export!(EntityType::Table, core_tables, "table");
3698            }
3699            ExternalKind::Memory => {
3700                check_max(
3701                    self.core_memories.len(),
3702                    1,
3703                    MAX_CORE_INDEX_SPACE_ITEMS,
3704                    "memories",
3705                    offset,
3706                )?;
3707                push_module_export!(EntityType::Memory, core_memories, "memory");
3708            }
3709            ExternalKind::Global => {
3710                check_max(
3711                    self.core_globals.len(),
3712                    1,
3713                    MAX_CORE_INDEX_SPACE_ITEMS,
3714                    "globals",
3715                    offset,
3716                )?;
3717                push_module_export!(EntityType::Global, core_globals, "global");
3718            }
3719            ExternalKind::Tag => {
3720                if !self.features.exceptions() {
3721                    bail!(offset, "exceptions proposal not enabled");
3722                }
3723                check_max(
3724                    self.core_tags.len(),
3725                    1,
3726                    MAX_CORE_INDEX_SPACE_ITEMS,
3727                    "tags",
3728                    offset,
3729                )?;
3730                push_module_export!(EntityType::Tag, core_tags, "tag");
3731            }
3732        }
3733
3734        Ok(())
3735    }
3736
3737    fn alias_instance_export(
3738        &mut self,
3739        instance_index: u32,
3740        kind: ComponentExternalKind,
3741        name: &str,
3742        types: &mut TypeAlloc,
3743        offset: usize,
3744    ) -> Result<()> {
3745        if let ComponentExternalKind::Value = kind {
3746            self.check_value_support(offset)?;
3747        }
3748        let mut ty = match types[self.instance_at(instance_index, offset)?]
3749            .exports
3750            .get(name)
3751        {
3752            Some(ty) => *ty,
3753            None => bail!(
3754                offset,
3755                "instance {instance_index} has no export named `{name}`"
3756            ),
3757        };
3758
3759        let ok = match (&ty, kind) {
3760            (ComponentEntityType::Module(_), ComponentExternalKind::Module) => true,
3761            (ComponentEntityType::Module(_), _) => false,
3762            (ComponentEntityType::Component(_), ComponentExternalKind::Component) => true,
3763            (ComponentEntityType::Component(_), _) => false,
3764            (ComponentEntityType::Func(_), ComponentExternalKind::Func) => true,
3765            (ComponentEntityType::Func(_), _) => false,
3766            (ComponentEntityType::Instance(_), ComponentExternalKind::Instance) => true,
3767            (ComponentEntityType::Instance(_), _) => false,
3768            (ComponentEntityType::Value(_), ComponentExternalKind::Value) => true,
3769            (ComponentEntityType::Value(_), _) => false,
3770            (ComponentEntityType::Type { .. }, ComponentExternalKind::Type) => true,
3771            (ComponentEntityType::Type { .. }, _) => false,
3772        };
3773        if !ok {
3774            bail!(
3775                offset,
3776                "export `{name}` for instance {instance_index} is not a {}",
3777                kind.desc(),
3778            );
3779        }
3780
3781        self.add_entity(&mut ty, None, types, offset)?;
3782        Ok(())
3783    }
3784
3785    fn alias_module(components: &mut [Self], count: u32, index: u32, offset: usize) -> Result<()> {
3786        let component = Self::check_alias_count(components, count, offset)?;
3787        let ty = component.module_at(index, offset)?;
3788
3789        let current = components.last_mut().unwrap();
3790        check_max(
3791            current.core_modules.len(),
3792            1,
3793            MAX_WASM_MODULES,
3794            "modules",
3795            offset,
3796        )?;
3797
3798        current.core_modules.push(ty);
3799        Ok(())
3800    }
3801
3802    fn alias_component(
3803        components: &mut [Self],
3804        count: u32,
3805        index: u32,
3806        offset: usize,
3807    ) -> Result<()> {
3808        let component = Self::check_alias_count(components, count, offset)?;
3809        let ty = component.component_at(index, offset)?;
3810
3811        let current = components.last_mut().unwrap();
3812        check_max(
3813            current.components.len(),
3814            1,
3815            MAX_WASM_COMPONENTS,
3816            "components",
3817            offset,
3818        )?;
3819
3820        current.components.push(ty);
3821        Ok(())
3822    }
3823
3824    fn alias_core_type(
3825        components: &mut [Self],
3826        count: u32,
3827        index: u32,
3828        offset: usize,
3829    ) -> Result<()> {
3830        let component = Self::check_alias_count(components, count, offset)?;
3831        let ty = component.core_type_at(index, offset)?;
3832
3833        let current = components.last_mut().unwrap();
3834        check_max(current.type_count(), 1, MAX_WASM_TYPES, "types", offset)?;
3835
3836        current.core_types.push(ty);
3837
3838        Ok(())
3839    }
3840
3841    fn alias_type(
3842        components: &mut [Self],
3843        count: u32,
3844        index: u32,
3845        types: &mut TypeAlloc,
3846        offset: usize,
3847    ) -> Result<()> {
3848        let component = Self::check_alias_count(components, count, offset)?;
3849        let ty = component.component_type_at(index, offset)?;
3850
3851        // If `count` "crossed a component boundary", meaning that it went from
3852        // one component to another, then this must additionally verify that
3853        // `ty` has no free variables with respect to resources. This is
3854        // intended to preserve the property for components where each component
3855        // is an isolated unit that can theoretically be extracted from other
3856        // components. If resources from other components were allowed to leak
3857        // in then it would prevent that.
3858        //
3859        // This check is done by calculating the `pos` within `components` that
3860        // our target `component` above was selected at. Once this is acquired
3861        // the component to the "right" is checked, and if that's a component
3862        // then it's considered as crossing a component boundary meaning the
3863        // free variables check runs.
3864        //
3865        // The reason this works is that in the list of `ComponentState` types
3866        // it's guaranteed that any `is_type` components are contiguous at the
3867        // end of the array. This means that if state one level deeper than the
3868        // target of this alias is a `!is_type` component, then the target must
3869        // be a component as well. If the one-level deeper state `is_type` then
3870        // the target is either a type or a component, both of which are valid
3871        // (as aliases can reach the enclosing component and have as many free
3872        // variables as they want).
3873        let pos_after_component = components.len() - (count as usize);
3874        if let Some(component) = components.get(pos_after_component) {
3875            if component.kind == ComponentKind::Component {
3876                let mut free = IndexSet::default();
3877                types.free_variables_any_type_id(ty, &mut free);
3878                if !free.is_empty() {
3879                    bail!(
3880                        offset,
3881                        "cannot alias outer type which transitively refers \
3882                         to resources not defined in the current component"
3883                    );
3884                }
3885            }
3886        }
3887
3888        let current = components.last_mut().unwrap();
3889        check_max(current.type_count(), 1, MAX_WASM_TYPES, "types", offset)?;
3890
3891        current.types.push(ty);
3892
3893        Ok(())
3894    }
3895
3896    fn check_alias_count(components: &[Self], count: u32, offset: usize) -> Result<&Self> {
3897        let count = count as usize;
3898        if count >= components.len() {
3899            bail!(offset, "invalid outer alias count of {count}");
3900        }
3901
3902        Ok(&components[components.len() - count - 1])
3903    }
3904
3905    fn create_defined_type(
3906        &self,
3907        ty: crate::ComponentDefinedType,
3908        types: &TypeList,
3909        offset: usize,
3910    ) -> Result<ComponentDefinedType> {
3911        match ty {
3912            crate::ComponentDefinedType::Primitive(ty) => {
3913                if ty == crate::PrimitiveValType::ErrorContext && !self.features.cm_error_context()
3914                {
3915                    bail!(
3916                        offset,
3917                        "`error-context` requires the component model error-context feature"
3918                    )
3919                }
3920                Ok(ComponentDefinedType::Primitive(ty))
3921            }
3922            crate::ComponentDefinedType::Record(fields) => {
3923                self.create_record_type(fields.as_ref(), types, offset)
3924            }
3925            crate::ComponentDefinedType::Variant(cases) => {
3926                self.create_variant_type(cases.as_ref(), types, offset)
3927            }
3928            crate::ComponentDefinedType::List(ty) => Ok(ComponentDefinedType::List(
3929                self.create_component_val_type(ty, offset)?,
3930            )),
3931            crate::ComponentDefinedType::FixedSizeList(ty, elements) => {
3932                if !self.features.cm_fixed_size_list() {
3933                    bail!(
3934                        offset,
3935                        "Fixed size lists require the component model fixed size list feature"
3936                    )
3937                }
3938                if elements < 1 {
3939                    bail!(offset, "Fixed size lists must have more than zero elements")
3940                }
3941                Ok(ComponentDefinedType::FixedSizeList(
3942                    self.create_component_val_type(ty, offset)?,
3943                    elements,
3944                ))
3945            }
3946            crate::ComponentDefinedType::Tuple(tys) => {
3947                self.create_tuple_type(tys.as_ref(), types, offset)
3948            }
3949            crate::ComponentDefinedType::Flags(names) => {
3950                self.create_flags_type(names.as_ref(), offset)
3951            }
3952            crate::ComponentDefinedType::Enum(cases) => {
3953                self.create_enum_type(cases.as_ref(), offset)
3954            }
3955            crate::ComponentDefinedType::Option(ty) => Ok(ComponentDefinedType::Option(
3956                self.create_component_val_type(ty, offset)?,
3957            )),
3958            crate::ComponentDefinedType::Result { ok, err } => Ok(ComponentDefinedType::Result {
3959                ok: ok
3960                    .map(|ty| self.create_component_val_type(ty, offset))
3961                    .transpose()?,
3962                err: err
3963                    .map(|ty| self.create_component_val_type(ty, offset))
3964                    .transpose()?,
3965            }),
3966            crate::ComponentDefinedType::Own(idx) => Ok(ComponentDefinedType::Own(
3967                self.resource_at(idx, types, offset)?,
3968            )),
3969            crate::ComponentDefinedType::Borrow(idx) => Ok(ComponentDefinedType::Borrow(
3970                self.resource_at(idx, types, offset)?,
3971            )),
3972            crate::ComponentDefinedType::Future(ty) => {
3973                if !self.features.cm_async() {
3974                    bail!(
3975                        offset,
3976                        "`future` requires the component model async feature"
3977                    )
3978                }
3979                Ok(ComponentDefinedType::Future(
3980                    ty.map(|ty| self.create_component_val_type(ty, offset))
3981                        .transpose()?,
3982                ))
3983            }
3984            crate::ComponentDefinedType::Stream(ty) => {
3985                if !self.features.cm_async() {
3986                    bail!(
3987                        offset,
3988                        "`stream` requires the component model async feature"
3989                    )
3990                }
3991                Ok(ComponentDefinedType::Stream(
3992                    ty.map(|ty| self.create_component_val_type(ty, offset))
3993                        .transpose()?,
3994                ))
3995            }
3996        }
3997    }
3998
3999    fn create_record_type(
4000        &self,
4001        fields: &[(&str, crate::ComponentValType)],
4002        types: &TypeList,
4003        offset: usize,
4004    ) -> Result<ComponentDefinedType> {
4005        let mut info = TypeInfo::new();
4006        let mut field_map = IndexMap::default();
4007        field_map.reserve(fields.len());
4008
4009        if fields.is_empty() {
4010            bail!(offset, "record type must have at least one field");
4011        }
4012
4013        for (name, ty) in fields {
4014            let name = to_kebab_str(name, "record field", offset)?;
4015            let ty = self.create_component_val_type(*ty, offset)?;
4016
4017            match field_map.entry(name.to_owned()) {
4018                Entry::Occupied(e) => bail!(
4019                    offset,
4020                    "record field name `{name}` conflicts with previous field name `{prev}`",
4021                    prev = e.key()
4022                ),
4023                Entry::Vacant(e) => {
4024                    info.combine(ty.info(types), offset)?;
4025                    e.insert(ty);
4026                }
4027            }
4028        }
4029
4030        Ok(ComponentDefinedType::Record(RecordType {
4031            info,
4032            fields: field_map,
4033        }))
4034    }
4035
4036    fn create_variant_type(
4037        &self,
4038        cases: &[crate::VariantCase],
4039        types: &TypeList,
4040        offset: usize,
4041    ) -> Result<ComponentDefinedType> {
4042        let mut info = TypeInfo::new();
4043        let mut case_map: IndexMap<KebabString, VariantCase> = IndexMap::default();
4044        case_map.reserve(cases.len());
4045
4046        if cases.is_empty() {
4047            bail!(offset, "variant type must have at least one case");
4048        }
4049
4050        if cases.len() > u32::MAX as usize {
4051            return Err(BinaryReaderError::new(
4052                "variant type cannot be represented with a 32-bit discriminant value",
4053                offset,
4054            ));
4055        }
4056
4057        for (i, case) in cases.iter().enumerate() {
4058            if let Some(refines) = case.refines {
4059                if refines >= i as u32 {
4060                    return Err(BinaryReaderError::new(
4061                        "variant case can only refine a previously defined case",
4062                        offset,
4063                    ));
4064                }
4065            }
4066
4067            let name = to_kebab_str(case.name, "variant case", offset)?;
4068
4069            let ty = case
4070                .ty
4071                .map(|ty| self.create_component_val_type(ty, offset))
4072                .transpose()?;
4073
4074            match case_map.entry(name.to_owned()) {
4075                Entry::Occupied(e) => bail!(
4076                    offset,
4077                    "variant case name `{name}` conflicts with previous case name `{prev}`",
4078                    name = case.name,
4079                    prev = e.key()
4080                ),
4081                Entry::Vacant(e) => {
4082                    if let Some(ty) = ty {
4083                        info.combine(ty.info(types), offset)?;
4084                    }
4085
4086                    // Safety: the use of `KebabStr::new_unchecked` here is safe because the string
4087                    // was already verified to be kebab case.
4088                    e.insert(VariantCase {
4089                        ty,
4090                        refines: case
4091                            .refines
4092                            .map(|i| KebabStr::new_unchecked(cases[i as usize].name).to_owned()),
4093                    });
4094                }
4095            }
4096        }
4097
4098        Ok(ComponentDefinedType::Variant(VariantType {
4099            info,
4100            cases: case_map,
4101        }))
4102    }
4103
4104    fn create_tuple_type(
4105        &self,
4106        tys: &[crate::ComponentValType],
4107        types: &TypeList,
4108        offset: usize,
4109    ) -> Result<ComponentDefinedType> {
4110        let mut info = TypeInfo::new();
4111        if tys.is_empty() {
4112            bail!(offset, "tuple type must have at least one type");
4113        }
4114        let types = tys
4115            .iter()
4116            .map(|ty| {
4117                let ty = self.create_component_val_type(*ty, offset)?;
4118                info.combine(ty.info(types), offset)?;
4119                Ok(ty)
4120            })
4121            .collect::<Result<_>>()?;
4122
4123        Ok(ComponentDefinedType::Tuple(TupleType { info, types }))
4124    }
4125
4126    fn create_flags_type(&self, names: &[&str], offset: usize) -> Result<ComponentDefinedType> {
4127        let mut names_set = IndexSet::default();
4128        names_set.reserve(names.len());
4129
4130        if names.is_empty() {
4131            bail!(offset, "flags must have at least one entry");
4132        }
4133
4134        if names.len() > 32 {
4135            bail!(offset, "cannot have more than 32 flags");
4136        }
4137
4138        for name in names {
4139            let name = to_kebab_str(name, "flag", offset)?;
4140            if !names_set.insert(name.to_owned()) {
4141                bail!(
4142                    offset,
4143                    "flag name `{name}` conflicts with previous flag name `{prev}`",
4144                    prev = names_set.get(name).unwrap()
4145                );
4146            }
4147        }
4148
4149        Ok(ComponentDefinedType::Flags(names_set))
4150    }
4151
4152    fn create_enum_type(&self, cases: &[&str], offset: usize) -> Result<ComponentDefinedType> {
4153        if cases.len() > u32::MAX as usize {
4154            return Err(BinaryReaderError::new(
4155                "enumeration type cannot be represented with a 32-bit discriminant value",
4156                offset,
4157            ));
4158        }
4159
4160        if cases.is_empty() {
4161            bail!(offset, "enum type must have at least one variant");
4162        }
4163
4164        let mut tags = IndexSet::default();
4165        tags.reserve(cases.len());
4166
4167        for tag in cases {
4168            let tag = to_kebab_str(tag, "enum tag", offset)?;
4169            if !tags.insert(tag.to_owned()) {
4170                bail!(
4171                    offset,
4172                    "enum tag name `{tag}` conflicts with previous tag name `{prev}`",
4173                    prev = tags.get(tag).unwrap()
4174                );
4175            }
4176        }
4177
4178        Ok(ComponentDefinedType::Enum(tags))
4179    }
4180
4181    fn create_component_val_type(
4182        &self,
4183        ty: crate::ComponentValType,
4184        offset: usize,
4185    ) -> Result<ComponentValType> {
4186        Ok(match ty {
4187            crate::ComponentValType::Primitive(pt) => ComponentValType::Primitive(pt),
4188            crate::ComponentValType::Type(idx) => {
4189                ComponentValType::Type(self.defined_type_at(idx, offset)?)
4190            }
4191        })
4192    }
4193
4194    pub fn core_type_at(&self, idx: u32, offset: usize) -> Result<ComponentCoreTypeId> {
4195        self.core_types
4196            .get(idx as usize)
4197            .copied()
4198            .ok_or_else(|| format_err!(offset, "unknown type {idx}: type index out of bounds"))
4199    }
4200
4201    pub fn component_type_at(&self, idx: u32, offset: usize) -> Result<ComponentAnyTypeId> {
4202        self.types
4203            .get(idx as usize)
4204            .copied()
4205            .ok_or_else(|| format_err!(offset, "unknown type {idx}: type index out of bounds"))
4206    }
4207
4208    fn function_type_at<'a>(
4209        &self,
4210        idx: u32,
4211        types: &'a TypeList,
4212        offset: usize,
4213    ) -> Result<&'a ComponentFuncType> {
4214        let id = self.component_type_at(idx, offset)?;
4215        match id {
4216            ComponentAnyTypeId::Func(id) => Ok(&types[id]),
4217            _ => bail!(offset, "type index {idx} is not a function type"),
4218        }
4219    }
4220
4221    fn function_at(&self, idx: u32, offset: usize) -> Result<ComponentFuncTypeId> {
4222        self.funcs.get(idx as usize).copied().ok_or_else(|| {
4223            format_err!(
4224                offset,
4225                "unknown function {idx}: function index out of bounds"
4226            )
4227        })
4228    }
4229
4230    fn component_at(&self, idx: u32, offset: usize) -> Result<ComponentTypeId> {
4231        self.components.get(idx as usize).copied().ok_or_else(|| {
4232            format_err!(
4233                offset,
4234                "unknown component {idx}: component index out of bounds"
4235            )
4236        })
4237    }
4238
4239    fn instance_at(&self, idx: u32, offset: usize) -> Result<ComponentInstanceTypeId> {
4240        self.instances.get(idx as usize).copied().ok_or_else(|| {
4241            format_err!(
4242                offset,
4243                "unknown instance {idx}: instance index out of bounds"
4244            )
4245        })
4246    }
4247
4248    fn value_at(&mut self, idx: u32, offset: usize) -> Result<&ComponentValType> {
4249        match self.values.get_mut(idx as usize) {
4250            Some((ty, used)) if !*used => {
4251                *used = true;
4252                Ok(ty)
4253            }
4254            Some(_) => bail!(offset, "value {idx} cannot be used more than once"),
4255            None => bail!(offset, "unknown value {idx}: value index out of bounds"),
4256        }
4257    }
4258
4259    fn defined_type_at(&self, idx: u32, offset: usize) -> Result<ComponentDefinedTypeId> {
4260        match self.component_type_at(idx, offset)? {
4261            ComponentAnyTypeId::Defined(id) => Ok(id),
4262            _ => bail!(offset, "type index {idx} is not a defined type"),
4263        }
4264    }
4265
4266    fn core_function_at(&self, idx: u32, offset: usize) -> Result<CoreTypeId> {
4267        match self.core_funcs.get(idx as usize) {
4268            Some(id) => Ok(*id),
4269            None => bail!(
4270                offset,
4271                "unknown core function {idx}: function index out of bounds"
4272            ),
4273        }
4274    }
4275
4276    fn module_at(&self, idx: u32, offset: usize) -> Result<ComponentCoreModuleTypeId> {
4277        match self.core_modules.get(idx as usize) {
4278            Some(id) => Ok(*id),
4279            None => bail!(offset, "unknown module {idx}: module index out of bounds"),
4280        }
4281    }
4282
4283    fn core_instance_at(&self, idx: u32, offset: usize) -> Result<ComponentCoreInstanceTypeId> {
4284        match self.core_instances.get(idx as usize) {
4285            Some(id) => Ok(*id),
4286            None => bail!(
4287                offset,
4288                "unknown core instance {idx}: instance index out of bounds"
4289            ),
4290        }
4291    }
4292
4293    fn core_instance_export<'a>(
4294        &self,
4295        instance_index: u32,
4296        name: &str,
4297        types: &'a TypeList,
4298        offset: usize,
4299    ) -> Result<&'a EntityType> {
4300        match types[self.core_instance_at(instance_index, offset)?]
4301            .internal_exports(types)
4302            .get(name)
4303        {
4304            Some(export) => Ok(export),
4305            None => bail!(
4306                offset,
4307                "core instance {instance_index} has no export named `{name}`"
4308            ),
4309        }
4310    }
4311
4312    fn global_at(&self, idx: u32, offset: usize) -> Result<&GlobalType> {
4313        match self.core_globals.get(idx as usize) {
4314            Some(t) => Ok(t),
4315            None => bail!(offset, "unknown global {idx}: global index out of bounds"),
4316        }
4317    }
4318
4319    fn table_at(&self, idx: u32, offset: usize) -> Result<&TableType> {
4320        match self.core_tables.get(idx as usize) {
4321            Some(t) => Ok(t),
4322            None => bail!(offset, "unknown table {idx}: table index out of bounds"),
4323        }
4324    }
4325
4326    fn memory_at(&self, idx: u32, offset: usize) -> Result<&MemoryType> {
4327        match self.core_memories.get(idx as usize) {
4328            Some(t) => Ok(t),
4329            None => bail!(offset, "unknown memory {idx}: memory index out of bounds"),
4330        }
4331    }
4332
4333    fn tag_at(&self, idx: u32, offset: usize) -> Result<CoreTypeId> {
4334        match self.core_tags.get(idx as usize) {
4335            Some(t) => Ok(*t),
4336            None => bail!(offset, "unknown tag {idx}: tag index out of bounds"),
4337        }
4338    }
4339
4340    /// Validates that the linear memory at `idx` is valid to use as a canonical
4341    /// ABI memory.
4342    ///
4343    /// At this time this requires that the memory is a plain 32-bit linear
4344    /// memory. Notably this disallows shared memory and 64-bit linear memories.
4345    fn cabi_memory_at(&self, idx: u32, offset: usize) -> Result<()> {
4346        let ty = self.memory_at(idx, offset)?;
4347        SubtypeCx::memory_type(
4348            ty,
4349            &MemoryType {
4350                initial: 0,
4351                maximum: None,
4352                memory64: false,
4353                shared: false,
4354                page_size_log2: None,
4355            },
4356            offset,
4357        )
4358        .map_err(|mut e| {
4359            e.add_context("canonical ABI memory is not a 32-bit linear memory".into());
4360            e
4361        })
4362    }
4363
4364    /// Completes the translation of this component, performing final
4365    /// validation of its structure.
4366    ///
4367    /// This method is required to be called for translating all components.
4368    /// Internally this will convert local data structures into a
4369    /// `ComponentType` which is suitable to use to describe the type of this
4370    /// component.
4371    pub fn finish(&mut self, types: &TypeAlloc, offset: usize) -> Result<ComponentType> {
4372        let mut ty = ComponentType {
4373            // Inherit some fields based on translation of the component.
4374            info: self.type_info,
4375            imports: self.imports.clone(),
4376            exports: self.exports.clone(),
4377
4378            // This is filled in as a subset of `self.defined_resources`
4379            // depending on what's actually used by the exports. See the
4380            // bottom of this function.
4381            defined_resources: Default::default(),
4382
4383            // These are inherited directly from what was calculated for this
4384            // component.
4385            imported_resources: mem::take(&mut self.imported_resources)
4386                .into_iter()
4387                .collect(),
4388            explicit_resources: mem::take(&mut self.explicit_resources),
4389        };
4390
4391        // Collect all "free variables", or resources, from the imports of this
4392        // component. None of the resources defined within this component can
4393        // be used as part of the exports. This set is then used to reject any
4394        // of `self.defined_resources` which show up.
4395        let mut free = IndexSet::default();
4396        for ty in ty.imports.values() {
4397            types.free_variables_component_entity(ty, &mut free);
4398        }
4399        for (resource, _path) in self.defined_resources.iter() {
4400            // FIXME: this error message is quite opaque and doesn't indicate
4401            // more contextual information such as:
4402            //
4403            // * what was the exported resource found in the imports
4404            // * which import was the resource found within
4405            //
4406            // These are possible to calculate here if necessary, however.
4407            if free.contains(resource) {
4408                bail!(offset, "local resource type found in imports");
4409            }
4410        }
4411
4412        // The next step in validation a component, with respect to resources,
4413        // is to minimize the set of defined resources to only those that
4414        // are actually used by the exports. This weeds out resources that are
4415        // defined, used within a component, and never exported, for example.
4416        //
4417        // The free variables of all exports are inserted into the `free` set
4418        // (which is reused from the imports after clearing it). The defined
4419        // resources calculated for this component are then inserted into this
4420        // type's list of defined resources if it's contained somewhere in
4421        // the free variables.
4422        //
4423        // Note that at the same time all defined resources must be exported,
4424        // somehow, transitively from this component. The `explicit_resources`
4425        // map is consulted for this purpose which lists all explicitly
4426        // exported resources in the component, regardless from whence they
4427        // came. If not present in this map then it's not exported and an error
4428        // is returned.
4429        //
4430        // NB: the "types are exported" check is probably sufficient nowadays
4431        // that the check of the `explicit_resources` map is probably not
4432        // necessary, but it's left here for completeness and out of an
4433        // abundance of caution.
4434        free.clear();
4435        for ty in ty.exports.values() {
4436            types.free_variables_component_entity(ty, &mut free);
4437        }
4438        for (id, _rep) in mem::take(&mut self.defined_resources) {
4439            if !free.contains(&id) {
4440                continue;
4441            }
4442
4443            let path = match ty.explicit_resources.get(&id).cloned() {
4444                Some(path) => path,
4445                // FIXME: this error message is quite opaque and doesn't
4446                // indicate more contextual information such as:
4447                //
4448                // * which resource wasn't found in an export
4449                // * which export has a reference to the resource
4450                //
4451                // These are possible to calculate here if necessary, however.
4452                None => bail!(
4453                    offset,
4454                    "local resource type found in export but not exported itself"
4455                ),
4456            };
4457
4458            ty.defined_resources.push((id, path));
4459        }
4460
4461        Ok(ty)
4462    }
4463
4464    fn check_value_support(&self, offset: usize) -> Result<()> {
4465        if !self.features.cm_values() {
4466            bail!(
4467                offset,
4468                "support for component model `value`s is not enabled"
4469            );
4470        }
4471        Ok(())
4472    }
4473}
4474
4475impl InternRecGroup for ComponentState {
4476    fn features(&self) -> &WasmFeatures {
4477        &self.features
4478    }
4479
4480    fn add_type_id(&mut self, id: CoreTypeId) {
4481        self.core_types.push(ComponentCoreTypeId::Sub(id));
4482    }
4483
4484    fn type_id_at(&self, idx: u32, offset: usize) -> Result<CoreTypeId> {
4485        match self.core_type_at(idx, offset)? {
4486            ComponentCoreTypeId::Sub(id) => Ok(id),
4487            ComponentCoreTypeId::Module(_) => {
4488                bail!(offset, "type index {idx} is a module type, not a sub type");
4489            }
4490        }
4491    }
4492
4493    fn types_len(&self) -> u32 {
4494        u32::try_from(self.core_types.len()).unwrap()
4495    }
4496}
4497
4498impl ComponentNameContext {
4499    /// Registers that the resource `id` is named `name` within this context.
4500    fn register(&mut self, name: &str, id: AliasableResourceId) {
4501        let idx = self.all_resource_names.len();
4502        let prev = self.resource_name_map.insert(id, idx);
4503        assert!(
4504            prev.is_none(),
4505            "for {id:?}, inserted {idx:?} but already had {prev:?}"
4506        );
4507        self.all_resource_names.insert(name.to_string());
4508    }
4509
4510    fn validate_extern(
4511        &self,
4512        name: &str,
4513        kind: ExternKind,
4514        ty: &ComponentEntityType,
4515        types: &TypeAlloc,
4516        offset: usize,
4517        kind_names: &mut IndexSet<ComponentName>,
4518        items: &mut IndexMap<String, ComponentEntityType>,
4519        info: &mut TypeInfo,
4520        features: &WasmFeatures,
4521    ) -> Result<()> {
4522        // First validate that `name` is even a valid kebab name, meaning it's
4523        // in kebab-case, is an ID, etc.
4524        let kebab = ComponentName::new_with_features(name, offset, *features)
4525            .with_context(|| format!("{} name `{name}` is not a valid extern name", kind.desc()))?;
4526
4527        if let ExternKind::Export = kind {
4528            match kebab.kind() {
4529                ComponentNameKind::Label(_)
4530                | ComponentNameKind::AsyncLabel(_)
4531                | ComponentNameKind::Method(_)
4532                | ComponentNameKind::AsyncMethod(_)
4533                | ComponentNameKind::Static(_)
4534                | ComponentNameKind::AsyncStatic(_)
4535                | ComponentNameKind::Constructor(_)
4536                | ComponentNameKind::Interface(_) => {}
4537
4538                ComponentNameKind::Hash(_)
4539                | ComponentNameKind::Url(_)
4540                | ComponentNameKind::Dependency(_) => {
4541                    bail!(offset, "name `{name}` is not a valid export name")
4542                }
4543            }
4544        }
4545
4546        // Validate that the kebab name, if it has structure such as
4547        // `[method]a.b`, is indeed valid with respect to known resources.
4548        self.validate(&kebab, ty, types, offset, features)
4549            .with_context(|| format!("{} name `{kebab}` is not valid", kind.desc()))?;
4550
4551        // Top-level kebab-names must all be unique, even between both imports
4552        // and exports ot a component. For those names consult the `kebab_names`
4553        // set.
4554        if let Some(prev) = kind_names.replace(kebab.clone()) {
4555            bail!(
4556                offset,
4557                "{} name `{kebab}` conflicts with previous name `{prev}`",
4558                kind.desc()
4559            );
4560        }
4561
4562        // Otherwise all strings must be unique, regardless of their name, so
4563        // consult the `items` set to ensure that we're not for example
4564        // importing the same interface ID twice.
4565        match items.entry(name.to_string()) {
4566            Entry::Occupied(e) => {
4567                bail!(
4568                    offset,
4569                    "{kind} name `{name}` conflicts with previous name `{prev}`",
4570                    kind = kind.desc(),
4571                    prev = e.key(),
4572                );
4573            }
4574            Entry::Vacant(e) => {
4575                e.insert(*ty);
4576                info.combine(ty.info(types), offset)?;
4577            }
4578        }
4579        Ok(())
4580    }
4581
4582    /// Validates that the `name` provided is allowed to have the type `ty`.
4583    fn validate(
4584        &self,
4585        name: &ComponentName,
4586        ty: &ComponentEntityType,
4587        types: &TypeAlloc,
4588        offset: usize,
4589        features: &WasmFeatures,
4590    ) -> Result<()> {
4591        let func = || {
4592            let id = match ty {
4593                ComponentEntityType::Func(id) => *id,
4594                _ => bail!(offset, "item is not a func"),
4595            };
4596            Ok(&types[id])
4597        };
4598        match name.kind() {
4599            ComponentNameKind::AsyncLabel(_)
4600            | ComponentNameKind::AsyncMethod(_)
4601            | ComponentNameKind::AsyncStatic(_) => {
4602                if !features.cm_async() {
4603                    bail!(
4604                        offset,
4605                        "async kebab-names require the component model async feature"
4606                    );
4607                }
4608            }
4609            _ => {}
4610        }
4611
4612        match name.kind() {
4613            // No validation necessary for these styles of names
4614            ComponentNameKind::Label(_)
4615            | ComponentNameKind::AsyncLabel(_)
4616            | ComponentNameKind::Interface(_)
4617            | ComponentNameKind::Url(_)
4618            | ComponentNameKind::Dependency(_)
4619            | ComponentNameKind::Hash(_) => {}
4620
4621            // Constructors must return `(own $resource)` or
4622            // `(result (own $Tresource))` and the `$resource` must be named
4623            // within this context to match `rname`.
4624            ComponentNameKind::Constructor(rname) => {
4625                let ty = func()?;
4626                let ty = match ty.result {
4627                    Some(result) => result,
4628                    None => bail!(offset, "function should return one value"),
4629                };
4630                let resource = match ty {
4631                    ComponentValType::Primitive(_) => None,
4632                    ComponentValType::Type(ty) => match &types[ty] {
4633                        ComponentDefinedType::Own(id) => Some(id),
4634                        ComponentDefinedType::Result {
4635                            ok: Some(ComponentValType::Type(ok)),
4636                            ..
4637                        } => match &types[*ok] {
4638                            ComponentDefinedType::Own(id) => Some(id),
4639                            _ => None,
4640                        },
4641                        _ => None,
4642                    },
4643                };
4644                let resource = match resource {
4645                    Some(id) => id,
4646                    None => bail!(
4647                        offset,
4648                        "function should return `(own $T)` or `(result (own $T))`"
4649                    ),
4650                };
4651                self.validate_resource_name(*resource, rname, offset)?;
4652            }
4653
4654            // Methods must take `(param "self" (borrow $resource))` as the
4655            // first argument where `$resources` matches the name `resource` as
4656            // named in this context.
4657            ComponentNameKind::Method(name) | ComponentNameKind::AsyncMethod(name) => {
4658                let ty = func()?;
4659                if ty.params.len() == 0 {
4660                    bail!(offset, "function should have at least one argument");
4661                }
4662                let (pname, pty) = &ty.params[0];
4663                if pname.as_str() != "self" {
4664                    bail!(
4665                        offset,
4666                        "function should have a first argument called `self`",
4667                    );
4668                }
4669                let id = match pty {
4670                    ComponentValType::Primitive(_) => None,
4671                    ComponentValType::Type(ty) => match &types[*ty] {
4672                        ComponentDefinedType::Borrow(id) => Some(id),
4673                        _ => None,
4674                    },
4675                };
4676                let id = match id {
4677                    Some(id) => id,
4678                    None => bail!(
4679                        offset,
4680                        "function should take a first argument of `(borrow $T)`"
4681                    ),
4682                };
4683                self.validate_resource_name(*id, name.resource(), offset)?;
4684            }
4685
4686            // Static methods don't have much validation beyond that they must
4687            // be a function and the resource name referred to must already be
4688            // in this context.
4689            ComponentNameKind::Static(name) | ComponentNameKind::AsyncStatic(name) => {
4690                func()?;
4691                if !self.all_resource_names.contains(name.resource().as_str()) {
4692                    bail!(offset, "static resource name is not known in this context");
4693                }
4694            }
4695        }
4696
4697        Ok(())
4698    }
4699
4700    fn validate_resource_name(
4701        &self,
4702        id: AliasableResourceId,
4703        name: &KebabStr,
4704        offset: usize,
4705    ) -> Result<()> {
4706        let expected_name_idx = match self.resource_name_map.get(&id) {
4707            Some(idx) => *idx,
4708            None => {
4709                bail!(
4710                    offset,
4711                    "resource used in function does not have a name in this context"
4712                )
4713            }
4714        };
4715        let expected_name = &self.all_resource_names[expected_name_idx];
4716        if name.as_str() != expected_name {
4717            bail!(
4718                offset,
4719                "function does not match expected \
4720                         resource name `{expected_name}`"
4721            );
4722        }
4723        Ok(())
4724    }
4725}
4726
4727use self::append_only::*;
4728
4729mod append_only {
4730    use crate::prelude::IndexMap;
4731    use core::hash::Hash;
4732    use core::ops::Deref;
4733
4734    pub struct IndexMapAppendOnly<K, V>(IndexMap<K, V>);
4735
4736    impl<K, V> IndexMapAppendOnly<K, V>
4737    where
4738        K: Hash + Eq + Ord + PartialEq + Clone,
4739    {
4740        pub fn insert(&mut self, key: K, value: V) {
4741            let prev = self.0.insert(key, value);
4742            assert!(prev.is_none());
4743        }
4744    }
4745
4746    impl<K, V> Deref for IndexMapAppendOnly<K, V> {
4747        type Target = IndexMap<K, V>;
4748        fn deref(&self) -> &IndexMap<K, V> {
4749            &self.0
4750        }
4751    }
4752
4753    impl<K, V> Default for IndexMapAppendOnly<K, V> {
4754        fn default() -> Self {
4755            Self(Default::default())
4756        }
4757    }
4758
4759    impl<K, V> IntoIterator for IndexMapAppendOnly<K, V> {
4760        type IntoIter = <IndexMap<K, V> as IntoIterator>::IntoIter;
4761        type Item = <IndexMap<K, V> as IntoIterator>::Item;
4762        fn into_iter(self) -> Self::IntoIter {
4763            self.0.into_iter()
4764        }
4765    }
4766}