Coverage Report

Created: 2025-01-09 07:53

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