Skip to main content

wasmtime_environ/component/translate/
inline.rs

1//! Implementation of "inlining" a component into a flat list of initializers.
2//!
3//! After the first phase of compiling a component we're left with a single
4//! root `Translation` for the original component along with a "static" list of
5//! child components. Each `Translation` has a list of `LocalInitializer` items
6//! inside of it which is a primitive representation of how the component
7//! should be constructed with effectively one initializer per item in the
8//! index space of a component. This "local initializer" list would be
9//! relatively inefficient to process at runtime and more importantly doesn't
10//! convey enough information to understand what trampolines need to be
11//! compiled or what fused adapters need to be generated. This consequently is
12//! the motivation for this file.
13//!
14//! The second phase of compilation, inlining here, will in a sense interpret
15//! the initializers, at compile time, into a new list of `GlobalInitializer` entries
16//! which are a sort of "global initializer". The generated `GlobalInitializer` is
17//! much more specific than the `LocalInitializer` and additionally far fewer
18//! `GlobalInitializer` structures are generated (in theory) than there are local
19//! initializers.
20//!
21//! The "inlining" portion of the name of this module indicates how the
22//! instantiation of a component is interpreted as calling a function. The
23//! function's arguments are the imports provided to the instantiation of a
24//! component, and further nested function calls happen on a stack when a
25//! nested component is instantiated. The inlining then refers to how this
26//! stack of instantiations is flattened to one list of `GlobalInitializer`
27//! entries to represent the process of instantiating a component graph,
28//! similar to how function inlining removes call instructions and creates one
29//! giant function for a call graph. Here there are no inlining heuristics or
30//! anything like that, we simply inline everything into the root component's
31//! list of initializers.
32//!
33//! Another primary task this module performs is a form of dataflow analysis
34//! to represent items in each index space with their definition rather than
35//! references of relative indices. These definitions (all the `*Def` types in
36//! this module) are not local to any one nested component and instead
37//! represent state available at runtime tracked in the final `Component`
38//! produced.
39//!
40//! With all this pieced together the general idea is relatively
41//! straightforward. All of a component's initializers are processed in sequence
42//! where instantiating a nested component pushes a "frame" onto a stack to
43//! start executing and we resume at the old one when we're done. Items are
44//! tracked where they come from and at the end after processing only the
45//! side-effectful initializers are emitted to the `GlobalInitializer` list in the
46//! final `Component`.
47
48use crate::component::translate::*;
49use crate::{EntityType, Memory};
50use core::str::FromStr;
51use std::borrow::Cow;
52use wasmparser::component_types::{ComponentAnyTypeId, ComponentCoreModuleTypeId};
53
54pub(super) fn run(
55    types: &mut ComponentTypesBuilder,
56    result: &Translation<'_>,
57    nested_modules: &PrimaryMap<StaticModuleIndex, ModuleTranslation<'_>>,
58    nested_components: &PrimaryMap<StaticComponentIndex, Translation<'_>>,
59) -> Result<dfg::ComponentDfg> {
60    let mut inliner = Inliner {
61        nested_modules,
62        nested_components,
63        result: Default::default(),
64        import_path_interner: Default::default(),
65        runtime_instances: PrimaryMap::default(),
66    };
67
68    let index = RuntimeComponentInstanceIndex::from_u32(0);
69
70    // The initial arguments to the root component are all host imports. This
71    // means that they're all using the `ComponentItemDef::Host` variant. Here
72    // an `ImportIndex` is allocated for each item and then the argument is
73    // recorded.
74    //
75    // Note that this is represents the abstract state of a host import of an
76    // item since we don't know the precise structure of the host import.
77    let mut args = HashMap::with_capacity(result.exports.len());
78    let mut path = Vec::new();
79    types.resources_mut().set_current_instance(index);
80    let types_ref = result.types_ref();
81    for init in result.initializers.iter() {
82        let (name, ty) = match *init {
83            LocalInitializer::Import(name, ty) => (name, ty),
84            _ => continue,
85        };
86
87        // Before `convert_component_entity_type` below all resource types
88        // introduced by this import need to be registered and have indexes
89        // assigned to them. Any fresh new resource type referred to by imports
90        // is a brand new introduction of a resource which needs to have a type
91        // allocated to it, so new runtime imports are injected for each
92        // resource along with updating the `imported_resources` map.
93        let index = inliner.result.import_types.next_key();
94        types.resources_mut().register_component_entity_type(
95            &types_ref,
96            ty,
97            &mut path,
98            &mut |path| {
99                let index = inliner.runtime_import(&ImportPath {
100                    index,
101                    path: path.iter().copied().map(Into::into).collect(),
102                });
103                inliner.result.imported_resources.push(index)
104            },
105        );
106
107        // With resources all taken care of it's now possible to convert this
108        // into Wasmtime's type system.
109        let ty = types.convert_component_entity_type(types_ref, ty)?;
110
111        // Imports of types that aren't resources are not required to be
112        // specified by the host since it's just for type information within
113        // the component.
114        if let TypeDef::Interface(_) = ty {
115            continue;
116        }
117        let index = inliner.result.import_types.push((
118            name.name.to_string(),
119            ComponentExtern {
120                ty,
121                data: ComponentExternData::new(name),
122            },
123        ));
124        let path = ImportPath::root(index);
125        args.insert(name.name, ComponentItemDef::from_import(path, ty)?);
126    }
127
128    // This will run the inliner to completion after being seeded with the
129    // initial frame. When the inliner finishes it will return the exports of
130    // the root frame which are then used for recording the exports of the
131    // component.
132    inliner.result.num_runtime_component_instances += 1;
133    let frame = InlinerFrame::new(index, result, ComponentClosure::default(), args, None);
134    let resources_snapshot = types.resources_mut().clone();
135    let mut frames = vec![(frame, resources_snapshot)];
136    let exports = inliner.run(types, &mut frames)?;
137    assert!(frames.is_empty());
138
139    let mut export_map = Default::default();
140    for (name, (def, data)) in exports {
141        let data = ComponentExternData::new(data);
142        inliner.record_export(name, def, data, types, &mut export_map)?;
143    }
144    inliner.result.exports = export_map;
145    inliner.result.num_future_tables = types.num_future_tables();
146    inliner.result.num_stream_tables = types.num_stream_tables();
147    inliner.result.num_error_context_tables = types.num_error_context_tables();
148
149    Ok(inliner.result)
150}
151
152struct Inliner<'a> {
153    /// The list of static modules that were found during initial translation of
154    /// the component.
155    ///
156    /// This is used during the instantiation of these modules to ahead-of-time
157    /// order the arguments precisely according to what the module is defined as
158    /// needing which avoids the need to do string lookups or permute arguments
159    /// at runtime.
160    nested_modules: &'a PrimaryMap<StaticModuleIndex, ModuleTranslation<'a>>,
161
162    /// The list of static components that were found during initial translation of
163    /// the component.
164    ///
165    /// This is used when instantiating nested components to push a new
166    /// `InlinerFrame` with the `Translation`s here.
167    nested_components: &'a PrimaryMap<StaticComponentIndex, Translation<'a>>,
168
169    /// The final `Component` that is being constructed and returned from this
170    /// inliner.
171    result: dfg::ComponentDfg,
172
173    // Maps used to "intern" various runtime items to only save them once at
174    // runtime instead of multiple times.
175    import_path_interner: HashMap<ImportPath<'a>, RuntimeImportIndex>,
176
177    /// Origin information about where each runtime instance came from
178    runtime_instances: PrimaryMap<dfg::InstanceId, InstanceModule>,
179}
180
181/// A "stack frame" as part of the inlining process, or the progress through
182/// instantiating a component.
183///
184/// All instantiations of a component will create an `InlinerFrame` and are
185/// incrementally processed via the `initializers` list here. Note that the
186/// inliner frames are stored on the heap to avoid recursion based on user
187/// input.
188struct InlinerFrame<'a> {
189    instance: RuntimeComponentInstanceIndex,
190
191    /// The remaining initializers to process when instantiating this component.
192    initializers: std::slice::Iter<'a, LocalInitializer<'a>>,
193
194    /// The component being instantiated.
195    translation: &'a Translation<'a>,
196
197    /// The "closure arguments" to this component, or otherwise the maps indexed
198    /// by `ModuleUpvarIndex` and `ComponentUpvarIndex`. This is created when
199    /// a component is created and stored as part of a component's state during
200    /// inlining.
201    closure: ComponentClosure<'a>,
202
203    /// The arguments to the creation of this component.
204    ///
205    /// At the root level these are all imports from the host and between
206    /// components this otherwise tracks how all the arguments are defined.
207    args: HashMap<&'a str, ComponentItemDef<'a>>,
208
209    // core wasm index spaces
210    funcs: PrimaryMap<FuncIndex, (ModuleInternedTypeIndex, dfg::CoreDef)>,
211    memories: PrimaryMap<MemoryIndex, dfg::CoreExport<EntityIndex>>,
212    tables: PrimaryMap<TableIndex, dfg::CoreExport<EntityIndex>>,
213    globals: PrimaryMap<GlobalIndex, dfg::CoreExport<EntityIndex>>,
214    tags: PrimaryMap<TagIndex, dfg::CoreExport<EntityIndex>>,
215    modules: PrimaryMap<ModuleIndex, ModuleDef<'a>>,
216
217    // component model index spaces
218    component_funcs: PrimaryMap<ComponentFuncIndex, ComponentFuncDef<'a>>,
219    module_instances: PrimaryMap<ModuleInstanceIndex, ModuleInstanceDef<'a>>,
220    component_instances: PrimaryMap<ComponentInstanceIndex, ComponentInstanceDef<'a>>,
221    components: PrimaryMap<ComponentIndex, ComponentDef<'a>>,
222
223    /// The type of instance produced by completing the instantiation of this
224    /// frame.
225    ///
226    /// This is a wasmparser-relative piece of type information which is used to
227    /// register resource types after instantiation has completed.
228    ///
229    /// This is `Some` for all subcomponents and `None` for the root component.
230    instance_ty: Option<ComponentInstanceTypeId>,
231}
232
233/// "Closure state" for a component which is resolved from the `ClosedOverVars`
234/// state that was calculated during translation.
235//
236// FIXME: this is cloned quite a lot and given the internal maps if this is a
237// perf issue we may want to `Rc` these fields. Note that this is only a perf
238// hit at compile-time though which we in general don't pay too much
239// attention to.
240#[derive(Default, Clone)]
241struct ComponentClosure<'a> {
242    modules: PrimaryMap<ModuleUpvarIndex, ModuleDef<'a>>,
243    components: PrimaryMap<ComponentUpvarIndex, ComponentDef<'a>>,
244}
245
246/// Representation of a "path" into an import.
247///
248/// Imports from the host at this time are one of three things:
249///
250/// * Functions
251/// * Core wasm modules
252/// * "Instances" of these three items
253///
254/// The "base" values are functions and core wasm modules, but the abstraction
255/// of an instance allows embedding functions/modules deeply within other
256/// instances. This "path" represents optionally walking through a host instance
257/// to get to the final desired item. At runtime instances are just maps of
258/// values and so this is used to ensure that we primarily only deal with
259/// individual functions and modules instead of synthetic instances.
260#[derive(Clone, PartialEq, Hash, Eq)]
261struct ImportPath<'a> {
262    index: ImportIndex,
263    path: Vec<Cow<'a, str>>,
264}
265
266/// Representation of all items which can be defined within a component.
267///
268/// This is the "value" of an item defined within a component and is used to
269/// represent both imports and exports.
270#[derive(Clone)]
271enum ComponentItemDef<'a> {
272    Component(ComponentDef<'a>),
273    Instance(ComponentInstanceDef<'a>),
274    Func(ComponentFuncDef<'a>),
275    Module(ModuleDef<'a>),
276    Type(TypeDef),
277}
278
279#[derive(Clone)]
280enum ModuleDef<'a> {
281    /// A core wasm module statically defined within the original component.
282    ///
283    /// The `StaticModuleIndex` indexes into the `static_modules` map in the
284    /// `Inliner`.
285    Static(StaticModuleIndex, ComponentCoreModuleTypeId),
286
287    /// A core wasm module that was imported from the host.
288    Import(ImportPath<'a>, TypeModuleIndex),
289}
290
291// Note that unlike all other `*Def` types which are not allowed to have local
292// indices this type does indeed have local indices. That is represented with
293// the lack of a `Clone` here where once this is created it's never moved across
294// components because module instances always stick within one component.
295enum ModuleInstanceDef<'a> {
296    /// A core wasm module instance was created through the instantiation of a
297    /// module.
298    ///
299    /// The `RuntimeInstanceIndex` was the index allocated as this was the
300    /// `n`th instantiation and the `ModuleIndex` points into an
301    /// `InlinerFrame`'s local index space.
302    Instantiated(dfg::InstanceId, ModuleIndex),
303
304    /// A "synthetic" core wasm module which is just a bag of named indices.
305    ///
306    /// Note that this can really only be used for passing as an argument to
307    /// another module's instantiation and is used to rename arguments locally.
308    Synthetic(&'a HashMap<&'a str, EntityIndex>),
309}
310
311#[derive(Clone)]
312enum ComponentFuncDef<'a> {
313    /// A compile-time builtin intrinsic.
314    UnsafeIntrinsic(UnsafeIntrinsic),
315
316    /// A host-imported component function.
317    Import(ImportPath<'a>),
318
319    /// A core wasm function was lifted into a component function.
320    Lifted {
321        /// The component function type.
322        ty: TypeFuncIndex,
323        /// The core Wasm function.
324        func: dfg::CoreDef,
325        /// Canonical options.
326        options: AdapterOptions,
327    },
328}
329
330#[derive(Clone)]
331enum ComponentInstanceDef<'a> {
332    /// The `__wasmtime_intrinsics` instance that exports all of our
333    /// compile-time builtin intrinsics.
334    Intrinsics,
335
336    /// A host-imported instance.
337    ///
338    /// This typically means that it's "just" a map of named values. It's not
339    /// actually supported to take a `wasmtime::component::Instance` and pass it
340    /// to another instance at this time.
341    Import(ImportPath<'a>, TypeComponentInstanceIndex),
342
343    /// A concrete map of values.
344    ///
345    /// This is used for both instantiated components as well as "synthetic"
346    /// components. This variant can be used for both because both are
347    /// represented by simply a bag of items within the entire component
348    /// instantiation process.
349    //
350    // FIXME: same as the issue on `ComponentClosure` where this is cloned a lot
351    // and may need `Rc`.
352    Items(
353        IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>,
354        TypeComponentInstanceIndex,
355    ),
356}
357
358#[derive(Clone)]
359struct ComponentDef<'a> {
360    index: StaticComponentIndex,
361    closure: ComponentClosure<'a>,
362}
363
364impl<'a> Inliner<'a> {
365    /// Symbolically instantiates a component using the type information and
366    /// `frames` provided.
367    ///
368    /// The `types` provided is the type information for the entire component
369    /// translation process. This is a distinct output artifact separate from
370    /// the component metadata.
371    ///
372    /// The `frames` argument is storage to handle a "call stack" of components
373    /// instantiating one another. The youngest frame (last element) of the
374    /// frames list is a component that's currently having its initializers
375    /// processed. The second element of each frame is a snapshot of the
376    /// resource-related information just before the frame was translated. For
377    /// more information on this snapshotting see the documentation on
378    /// `ResourcesBuilder`.
379    fn run(
380        &mut self,
381        types: &mut ComponentTypesBuilder,
382        frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>,
383    ) -> Result<IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>>
384    {
385        // This loop represents the execution of the instantiation of a
386        // component. This is an iterative process which is finished once all
387        // initializers are processed. Currently this is modeled as an infinite
388        // loop which drives the top-most iterator of the `frames` stack
389        // provided as an argument to this function.
390        loop {
391            let (frame, _) = frames.last_mut().unwrap();
392            types.resources_mut().set_current_instance(frame.instance);
393            match frame.initializers.next() {
394                // Process the initializer and if it started the instantiation
395                // of another component then we push that frame on the stack to
396                // continue onwards.
397                Some(init) => match self.initializer(frames, types, init)? {
398                    Some(new_frame) => {
399                        frames.push((new_frame, types.resources_mut().clone()));
400                    }
401                    None => {}
402                },
403
404                // If there are no more initializers for this frame then the
405                // component it represents has finished instantiation. The
406                // exports of the component are collected and then the entire
407                // frame is discarded. The exports are then either pushed in the
408                // parent frame, if any, as a new component instance or they're
409                // returned from this function for the root set of exports.
410                None => {
411                    let exports = frame
412                        .translation
413                        .exports
414                        .iter()
415                        .map(|(name, (item, data))| Ok((*name, (frame.item(*item, types)?, *data))))
416                        .collect::<Result<_>>()?;
417                    let instance_ty = frame.instance_ty;
418                    let (_, snapshot) = frames.pop().unwrap();
419                    *types.resources_mut() = snapshot;
420                    match frames.last_mut() {
421                        Some((parent, _)) => {
422                            parent.finish_instantiate(exports, instance_ty.unwrap(), types)?;
423                        }
424                        None => break Ok(exports),
425                    }
426                }
427            }
428        }
429    }
430
431    fn initializer(
432        &mut self,
433        frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>,
434        types: &mut ComponentTypesBuilder,
435        initializer: &'a LocalInitializer,
436    ) -> Result<Option<InlinerFrame<'a>>> {
437        use LocalInitializer::*;
438
439        let (frame, _) = frames.last_mut().unwrap();
440        match initializer {
441            // When a component imports an item the actual definition of the
442            // item is looked up here (not at runtime) via its name. The
443            // arguments provided in our `InlinerFrame` describe how each
444            // argument was defined, so we simply move it from there into the
445            // correct index space.
446            //
447            // Note that for the root component this will add `*::Import` items
448            // but for sub-components this will do resolution to connect what
449            // was provided as an import at the instantiation-site to what was
450            // needed during the component's instantiation.
451            Import(name, ty) => {
452                let arg = match frame.args.get(name.name) {
453                    Some(arg) => arg,
454
455                    // Not all arguments need to be provided for instantiation,
456                    // namely the root component in Wasmtime doesn't require
457                    // structural type imports to be satisfied. These type
458                    // imports are relevant for bindings generators and such but
459                    // as a runtime there's not really a definition to fit in.
460                    //
461                    // If no argument was provided for `name` then it's asserted
462                    // that this is a type import and additionally it's not a
463                    // resource type import (which indeed must be provided). If
464                    // all that passes then this initializer is effectively
465                    // skipped.
466                    None => {
467                        match ty {
468                            ComponentEntityType::Type {
469                                created: ComponentAnyTypeId::Resource(_),
470                                ..
471                            } => unreachable!(),
472                            ComponentEntityType::Type { .. } => {}
473                            _ => unreachable!(),
474                        }
475                        return Ok(None);
476                    }
477                };
478
479                // Next resource types need to be handled. For example if a
480                // resource is imported into this component then it needs to be
481                // assigned a unique table to provide the isolation guarantees
482                // of resources (this component's table is shared with no
483                // others). Here `register_component_entity_type` will find
484                // imported resources and then `lookup_resource` will find the
485                // resource within `arg` as necessary to lookup the original
486                // true definition of this resource.
487                //
488                // This is what enables tracking true resource origins
489                // throughout component translation while simultaneously also
490                // tracking unique tables for each resource in each component.
491                let mut path = Vec::new();
492                let (resources, types) = types.resources_mut_and_types();
493                resources.register_component_entity_type(
494                    &frame.translation.types_ref(),
495                    *ty,
496                    &mut path,
497                    &mut |path| arg.lookup_resource(path, types),
498                );
499
500                // And now with all the type information out of the way the
501                // `arg` definition is moved into its corresponding index space.
502                frame.push_item(arg.clone());
503            }
504
505            IntrinsicsImport => {
506                frame
507                    .component_instances
508                    .push(ComponentInstanceDef::Intrinsics);
509            }
510
511            // Lowering a component function to a core wasm function is
512            // generally what "triggers compilation". Here various metadata is
513            // recorded and then the final component gets an initializer
514            // recording the lowering.
515            //
516            // NB: at this time only lowered imported functions are supported.
517            Lower {
518                func,
519                options,
520                lower_ty,
521            } => {
522                let lower_ty =
523                    types.convert_component_func_type(frame.translation.types_ref(), *lower_ty)?;
524                let options_lower = self.adapter_options(frames, types, options);
525                let (frame, _) = frames.last_mut().unwrap();
526                let lower_core_type = options_lower.core_type;
527                let func = match &frame.component_funcs[*func] {
528                    // If this component function was originally a host import
529                    // then this is a lowered host function which needs a
530                    // trampoline to enter WebAssembly. That's recorded here
531                    // with all relevant information.
532                    ComponentFuncDef::Import(path) => {
533                        let import = self.runtime_import(path);
534                        let options = self.canonical_options(options_lower);
535                        let index = self.result.trampolines.push((
536                            lower_core_type,
537                            dfg::Trampoline::LowerImport {
538                                import,
539                                options,
540                                lower_ty,
541                            },
542                        ));
543                        dfg::CoreDef::Trampoline(index)
544                    }
545
546                    // Lowering a lifted function means that a "fused adapter"
547                    // was just identified.
548                    //
549                    // Metadata about this fused adapter is recorded in the
550                    // `Adapters` output of this compilation pass. Currently the
551                    // implementation of fused adapters is to generate a core
552                    // wasm module which is instantiated with relevant imports
553                    // and the exports are used as the fused adapters. At this
554                    // time we don't know when precisely the instance will be
555                    // created but we do know that the result of this will be an
556                    // export from a previously-created instance.
557                    //
558                    // To model this the result of this arm is a
559                    // `CoreDef::Export`. The actual indices listed within the
560                    // export are "fake indices" in the sense of they're not
561                    // resolved yet. This resolution will happen at a later
562                    // compilation phase. Any usages of the `CoreDef::Export`
563                    // here will be detected and rewritten to an actual runtime
564                    // instance created.
565                    //
566                    // The `instance` field of the `CoreExport` has a marker
567                    // which indicates that it's a fused adapter. The `item` is
568                    // a function where the function index corresponds to the
569                    // `adapter_idx` which contains the metadata about this
570                    // adapter being created. The metadata is used to learn
571                    // about the dependencies and when the adapter module can
572                    // be instantiated.
573                    ComponentFuncDef::Lifted {
574                        ty: lift_ty,
575                        func,
576                        options: options_lift,
577                    } => {
578                        let adapter_idx = self.result.adapters.push(Adapter {
579                            lift_ty: *lift_ty,
580                            lift_options: options_lift.clone(),
581                            lower_ty,
582                            lower_options: options_lower,
583                            func: func.clone(),
584                        });
585                        dfg::CoreDef::Adapter(adapter_idx)
586                    }
587
588                    ComponentFuncDef::UnsafeIntrinsic(intrinsic) => {
589                        dfg::CoreDef::UnsafeIntrinsic(options.core_type, *intrinsic)
590                    }
591                };
592                frame.funcs.push((lower_core_type, func));
593            }
594
595            // Lifting a core wasm function is relatively easy for now in that
596            // some metadata about the lifting is simply recorded. This'll get
597            // plumbed through to exports or a fused adapter later on.
598            Lift(ty, func, options) => {
599                let ty = types.convert_component_func_type(frame.translation.types_ref(), *ty)?;
600                let options = self.adapter_options(frames, types, options);
601                let (frame, _) = frames.last_mut().unwrap();
602                let func = frame.funcs[*func].1.clone();
603                frame
604                    .component_funcs
605                    .push(ComponentFuncDef::Lifted { ty, func, options });
606            }
607
608            // A new resource type is being introduced, so it's recorded as a
609            // brand new resource in the final `resources` array. Additionally
610            // for now resource introductions are considered side effects to
611            // know when to register their destructors so that's recorded as
612            // well.
613            //
614            // Note that this has the effect of when a component is instantiated
615            // twice it will produce unique types for the resources from each
616            // instantiation. That's the intended runtime semantics and
617            // implementation here, however.
618            Resource(ty, rep, dtor) => {
619                let idx = self.result.resources.push(dfg::Resource {
620                    rep: *rep,
621                    dtor: dtor.map(|i| frame.funcs[i].1.clone()),
622                    instance: frame.instance,
623                });
624                self.result
625                    .side_effects
626                    .push(dfg::SideEffect::Resource(idx));
627
628                // Register with type translation that all future references to
629                // `ty` will refer to `idx`.
630                //
631                // Note that this registration information is lost when this
632                // component finishes instantiation due to the snapshotting
633                // behavior in the frame processing loop above. This is also
634                // intended, though, since `ty` can't be referred to outside of
635                // this component.
636                let idx = self.result.resource_index(idx);
637                types.resources_mut().register_resource(ty.resource(), idx);
638            }
639
640            // Resource-related intrinsics are generally all the same.
641            // Wasmparser type information is converted to wasmtime type
642            // information and then new entries for each intrinsic are recorded.
643            ResourceNew(id, ty) => {
644                let id = types.resource_id(id.resource());
645                let index = self.result.trampolines.push((
646                    *ty,
647                    dfg::Trampoline::ResourceNew {
648                        instance: frame.instance,
649                        ty: id,
650                    },
651                ));
652                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
653            }
654            ResourceRep(id, ty) => {
655                let id = types.resource_id(id.resource());
656                let index = self.result.trampolines.push((
657                    *ty,
658                    dfg::Trampoline::ResourceRep {
659                        instance: frame.instance,
660                        ty: id,
661                    },
662                ));
663                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
664            }
665            ResourceDrop(id, ty) => {
666                let id = types.resource_id(id.resource());
667                let index = self.result.trampolines.push((
668                    *ty,
669                    dfg::Trampoline::ResourceDrop {
670                        instance: frame.instance,
671                        ty: id,
672                    },
673                ));
674                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
675            }
676            BackpressureInc { func } => {
677                let index = self.result.trampolines.push((
678                    *func,
679                    dfg::Trampoline::BackpressureInc {
680                        instance: frame.instance,
681                    },
682                ));
683                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
684            }
685            BackpressureDec { func } => {
686                let index = self.result.trampolines.push((
687                    *func,
688                    dfg::Trampoline::BackpressureDec {
689                        instance: frame.instance,
690                    },
691                ));
692                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
693            }
694            TaskReturn { result, options } => {
695                let results = result
696                    .iter()
697                    .map(|ty| types.valtype(frame.translation.types_ref(), ty))
698                    .collect::<Result<_>>()?;
699                let results = types.new_tuple_type(results);
700                let func = options.core_type;
701                let options = self.adapter_options(frames, types, options);
702                let (frame, _) = frames.last_mut().unwrap();
703                let options = self.canonical_options(options);
704                let index = self.result.trampolines.push((
705                    func,
706                    dfg::Trampoline::TaskReturn {
707                        instance: frame.instance,
708                        results,
709                        options,
710                    },
711                ));
712                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
713            }
714            TaskCancel { func } => {
715                let index = self.result.trampolines.push((
716                    *func,
717                    dfg::Trampoline::TaskCancel {
718                        instance: frame.instance,
719                    },
720                ));
721                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
722            }
723            WaitableSetNew { func } => {
724                let index = self.result.trampolines.push((
725                    *func,
726                    dfg::Trampoline::WaitableSetNew {
727                        instance: frame.instance,
728                    },
729                ));
730                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
731            }
732            WaitableSetWait { options } => {
733                let func = options.core_type;
734                let options = self.adapter_options(frames, types, options);
735                let (frame, _) = frames.last_mut().unwrap();
736                let options = self.canonical_options(options);
737                let index = self.result.trampolines.push((
738                    func,
739                    dfg::Trampoline::WaitableSetWait {
740                        instance: frame.instance,
741                        options,
742                    },
743                ));
744                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
745            }
746            WaitableSetPoll { options } => {
747                let func = options.core_type;
748                let options = self.adapter_options(frames, types, options);
749                let (frame, _) = frames.last_mut().unwrap();
750                let options = self.canonical_options(options);
751                let index = self.result.trampolines.push((
752                    func,
753                    dfg::Trampoline::WaitableSetPoll {
754                        instance: frame.instance,
755                        options,
756                    },
757                ));
758                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
759            }
760            WaitableSetDrop { func } => {
761                let index = self.result.trampolines.push((
762                    *func,
763                    dfg::Trampoline::WaitableSetDrop {
764                        instance: frame.instance,
765                    },
766                ));
767                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
768            }
769            WaitableJoin { func } => {
770                let index = self.result.trampolines.push((
771                    *func,
772                    dfg::Trampoline::WaitableJoin {
773                        instance: frame.instance,
774                    },
775                ));
776                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
777            }
778            SubtaskDrop { func } => {
779                let index = self.result.trampolines.push((
780                    *func,
781                    dfg::Trampoline::SubtaskDrop {
782                        instance: frame.instance,
783                    },
784                ));
785                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
786            }
787            SubtaskCancel { func, async_ } => {
788                let index = self.result.trampolines.push((
789                    *func,
790                    dfg::Trampoline::SubtaskCancel {
791                        instance: frame.instance,
792                        async_: *async_,
793                    },
794                ));
795                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
796            }
797            StreamNew { ty, func } => {
798                let InterfaceType::Stream(ty) =
799                    types.defined_type(frame.translation.types_ref(), *ty)?
800                else {
801                    unreachable!()
802                };
803                let index = self.result.trampolines.push((
804                    *func,
805                    dfg::Trampoline::StreamNew {
806                        instance: frame.instance,
807                        ty,
808                    },
809                ));
810                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
811            }
812            StreamRead { ty, options } => {
813                let InterfaceType::Stream(ty) =
814                    types.defined_type(frame.translation.types_ref(), *ty)?
815                else {
816                    unreachable!()
817                };
818                let func = options.core_type;
819                let options = self.adapter_options(frames, types, options);
820                let (frame, _) = frames.last_mut().unwrap();
821                let options = self.canonical_options(options);
822                let index = self.result.trampolines.push((
823                    func,
824                    dfg::Trampoline::StreamRead {
825                        instance: frame.instance,
826                        ty,
827                        options,
828                    },
829                ));
830                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
831            }
832            StreamWrite { ty, options } => {
833                let InterfaceType::Stream(ty) =
834                    types.defined_type(frame.translation.types_ref(), *ty)?
835                else {
836                    unreachable!()
837                };
838                let func = options.core_type;
839                let options = self.adapter_options(frames, types, options);
840                let (frame, _) = frames.last_mut().unwrap();
841                let options = self.canonical_options(options);
842                let index = self.result.trampolines.push((
843                    func,
844                    dfg::Trampoline::StreamWrite {
845                        instance: frame.instance,
846                        ty,
847                        options,
848                    },
849                ));
850                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
851            }
852            StreamCancelRead { ty, func, async_ } => {
853                let InterfaceType::Stream(ty) =
854                    types.defined_type(frame.translation.types_ref(), *ty)?
855                else {
856                    unreachable!()
857                };
858                let index = self.result.trampolines.push((
859                    *func,
860                    dfg::Trampoline::StreamCancelRead {
861                        instance: frame.instance,
862                        ty,
863                        async_: *async_,
864                    },
865                ));
866                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
867            }
868            StreamCancelWrite { ty, func, async_ } => {
869                let InterfaceType::Stream(ty) =
870                    types.defined_type(frame.translation.types_ref(), *ty)?
871                else {
872                    unreachable!()
873                };
874                let index = self.result.trampolines.push((
875                    *func,
876                    dfg::Trampoline::StreamCancelWrite {
877                        instance: frame.instance,
878                        ty,
879                        async_: *async_,
880                    },
881                ));
882                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
883            }
884            StreamDropReadable { ty, func } => {
885                let InterfaceType::Stream(ty) =
886                    types.defined_type(frame.translation.types_ref(), *ty)?
887                else {
888                    unreachable!()
889                };
890                let index = self.result.trampolines.push((
891                    *func,
892                    dfg::Trampoline::StreamDropReadable {
893                        instance: frame.instance,
894                        ty,
895                    },
896                ));
897                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
898            }
899            StreamDropWritable { ty, func } => {
900                let InterfaceType::Stream(ty) =
901                    types.defined_type(frame.translation.types_ref(), *ty)?
902                else {
903                    unreachable!()
904                };
905                let index = self.result.trampolines.push((
906                    *func,
907                    dfg::Trampoline::StreamDropWritable {
908                        instance: frame.instance,
909                        ty,
910                    },
911                ));
912                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
913            }
914            FutureNew { ty, func } => {
915                let InterfaceType::Future(ty) =
916                    types.defined_type(frame.translation.types_ref(), *ty)?
917                else {
918                    unreachable!()
919                };
920                let index = self.result.trampolines.push((
921                    *func,
922                    dfg::Trampoline::FutureNew {
923                        instance: frame.instance,
924                        ty,
925                    },
926                ));
927                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
928            }
929            FutureRead { ty, options } => {
930                let InterfaceType::Future(ty) =
931                    types.defined_type(frame.translation.types_ref(), *ty)?
932                else {
933                    unreachable!()
934                };
935                let func = options.core_type;
936                let options = self.adapter_options(frames, types, options);
937                let (frame, _) = frames.last_mut().unwrap();
938                let options = self.canonical_options(options);
939                let index = self.result.trampolines.push((
940                    func,
941                    dfg::Trampoline::FutureRead {
942                        instance: frame.instance,
943                        ty,
944                        options,
945                    },
946                ));
947                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
948            }
949            FutureWrite { ty, options } => {
950                let InterfaceType::Future(ty) =
951                    types.defined_type(frame.translation.types_ref(), *ty)?
952                else {
953                    unreachable!()
954                };
955                let func = options.core_type;
956                let options = self.adapter_options(frames, types, options);
957                let (frame, _) = frames.last_mut().unwrap();
958                let options = self.canonical_options(options);
959                let index = self.result.trampolines.push((
960                    func,
961                    dfg::Trampoline::FutureWrite {
962                        instance: frame.instance,
963                        ty,
964                        options,
965                    },
966                ));
967                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
968            }
969            FutureCancelRead { ty, func, async_ } => {
970                let InterfaceType::Future(ty) =
971                    types.defined_type(frame.translation.types_ref(), *ty)?
972                else {
973                    unreachable!()
974                };
975                let index = self.result.trampolines.push((
976                    *func,
977                    dfg::Trampoline::FutureCancelRead {
978                        instance: frame.instance,
979                        ty,
980                        async_: *async_,
981                    },
982                ));
983                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
984            }
985            FutureCancelWrite { ty, func, async_ } => {
986                let InterfaceType::Future(ty) =
987                    types.defined_type(frame.translation.types_ref(), *ty)?
988                else {
989                    unreachable!()
990                };
991                let index = self.result.trampolines.push((
992                    *func,
993                    dfg::Trampoline::FutureCancelWrite {
994                        instance: frame.instance,
995                        ty,
996                        async_: *async_,
997                    },
998                ));
999                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1000            }
1001            FutureDropReadable { ty, func } => {
1002                let InterfaceType::Future(ty) =
1003                    types.defined_type(frame.translation.types_ref(), *ty)?
1004                else {
1005                    unreachable!()
1006                };
1007                let index = self.result.trampolines.push((
1008                    *func,
1009                    dfg::Trampoline::FutureDropReadable {
1010                        instance: frame.instance,
1011                        ty,
1012                    },
1013                ));
1014                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1015            }
1016            FutureDropWritable { ty, func } => {
1017                let InterfaceType::Future(ty) =
1018                    types.defined_type(frame.translation.types_ref(), *ty)?
1019                else {
1020                    unreachable!()
1021                };
1022                let index = self.result.trampolines.push((
1023                    *func,
1024                    dfg::Trampoline::FutureDropWritable {
1025                        instance: frame.instance,
1026                        ty,
1027                    },
1028                ));
1029                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1030            }
1031            ErrorContextNew { options } => {
1032                let ty = types.error_context_table_type()?;
1033                let func = options.core_type;
1034                let options = self.adapter_options(frames, types, options);
1035                let (frame, _) = frames.last_mut().unwrap();
1036                let options = self.canonical_options(options);
1037                let index = self.result.trampolines.push((
1038                    func,
1039                    dfg::Trampoline::ErrorContextNew {
1040                        instance: frame.instance,
1041                        ty,
1042                        options,
1043                    },
1044                ));
1045                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
1046            }
1047            ErrorContextDebugMessage { options } => {
1048                let ty = types.error_context_table_type()?;
1049                let func = options.core_type;
1050                let options = self.adapter_options(frames, types, options);
1051                let (frame, _) = frames.last_mut().unwrap();
1052                let options = self.canonical_options(options);
1053                let index = self.result.trampolines.push((
1054                    func,
1055                    dfg::Trampoline::ErrorContextDebugMessage {
1056                        instance: frame.instance,
1057                        ty,
1058                        options,
1059                    },
1060                ));
1061                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
1062            }
1063            ErrorContextDrop { func } => {
1064                let ty = types.error_context_table_type()?;
1065                let index = self.result.trampolines.push((
1066                    *func,
1067                    dfg::Trampoline::ErrorContextDrop {
1068                        instance: frame.instance,
1069                        ty,
1070                    },
1071                ));
1072                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1073            }
1074            ContextGet { func, i } => {
1075                let intrinsic = match i {
1076                    0 => UnsafeIntrinsic::ContextGetI32_0,
1077                    1 => UnsafeIntrinsic::ContextGetI32_1,
1078                    _ => unreachable!(),
1079                };
1080                frame
1081                    .funcs
1082                    .push((*func, dfg::CoreDef::UnsafeIntrinsic(*func, intrinsic)));
1083            }
1084            ContextSet { func, i } => {
1085                let intrinsic = match i {
1086                    0 => UnsafeIntrinsic::ContextSetI32_0,
1087                    1 => UnsafeIntrinsic::ContextSetI32_1,
1088                    _ => unreachable!(),
1089                };
1090                frame
1091                    .funcs
1092                    .push((*func, dfg::CoreDef::UnsafeIntrinsic(*func, intrinsic)));
1093            }
1094            ThreadIndex { func } => {
1095                let index = self.result.trampolines.push((
1096                    *func,
1097                    dfg::Trampoline::ThreadIndex {
1098                        instance: frame.instance,
1099                    },
1100                ));
1101                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1102            }
1103            ThreadNewIndirect {
1104                func,
1105                start_func_table_index,
1106                start_func_ty,
1107            } => {
1108                let table_export = frame.tables[*start_func_table_index]
1109                    .clone()
1110                    .map_index(|i| match i {
1111                        EntityIndex::Table(i) => i,
1112                        _ => unreachable!(),
1113                    });
1114
1115                let table_id = self.result.tables.push(table_export);
1116                let index = self.result.trampolines.push((
1117                    *func,
1118                    dfg::Trampoline::ThreadNewIndirect {
1119                        instance: frame.instance,
1120                        start_func_ty_idx: *start_func_ty,
1121                        start_func_table_id: table_id,
1122                    },
1123                ));
1124                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1125            }
1126            ThreadResumeLater { func } => {
1127                let index = self.result.trampolines.push((
1128                    *func,
1129                    dfg::Trampoline::ThreadResumeLater {
1130                        instance: frame.instance,
1131                    },
1132                ));
1133                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1134            }
1135            ThreadSuspend { func, cancellable } => {
1136                let index = self.result.trampolines.push((
1137                    *func,
1138                    dfg::Trampoline::ThreadSuspend {
1139                        instance: frame.instance,
1140                        cancellable: *cancellable,
1141                    },
1142                ));
1143                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1144            }
1145            ThreadYield { func, cancellable } => {
1146                let index = self.result.trampolines.push((
1147                    *func,
1148                    dfg::Trampoline::ThreadYield {
1149                        instance: frame.instance,
1150                        cancellable: *cancellable,
1151                    },
1152                ));
1153                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1154            }
1155            ThreadSuspendThenResume { func, cancellable } => {
1156                let index = self.result.trampolines.push((
1157                    *func,
1158                    dfg::Trampoline::ThreadSuspendThenResume {
1159                        instance: frame.instance,
1160                        cancellable: *cancellable,
1161                    },
1162                ));
1163                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1164            }
1165            ThreadYieldThenResume { func, cancellable } => {
1166                let index = self.result.trampolines.push((
1167                    *func,
1168                    dfg::Trampoline::ThreadYieldThenResume {
1169                        instance: frame.instance,
1170                        cancellable: *cancellable,
1171                    },
1172                ));
1173                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1174            }
1175            ThreadSuspendThenPromote { func, cancellable } => {
1176                let index = self.result.trampolines.push((
1177                    *func,
1178                    dfg::Trampoline::ThreadSuspendThenPromote {
1179                        instance: frame.instance,
1180                        cancellable: *cancellable,
1181                    },
1182                ));
1183                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1184            }
1185            ThreadYieldThenPromote { func, cancellable } => {
1186                let index = self.result.trampolines.push((
1187                    *func,
1188                    dfg::Trampoline::ThreadYieldThenPromote {
1189                        instance: frame.instance,
1190                        cancellable: *cancellable,
1191                    },
1192                ));
1193                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1194            }
1195            ModuleStatic(idx, ty) => {
1196                frame.modules.push(ModuleDef::Static(*idx, *ty));
1197            }
1198
1199            // Instantiation of a module is one of the meatier initializers that
1200            // we'll generate. The main magic here is that for a statically
1201            // known module we can order the imports as a list to exactly what
1202            // the static module needs to be instantiated. For imported modules,
1203            // however, the runtime string resolution must happen at runtime so
1204            // that is deferred here by organizing the arguments as a two-layer
1205            // `IndexMap` of what we're providing.
1206            //
1207            // In both cases though a new `RuntimeInstanceIndex` is allocated
1208            // and an initializer is recorded to indicate that it's being
1209            // instantiated.
1210            ModuleInstantiate(module, args) => {
1211                let (instance_module, init) = match &frame.modules[*module] {
1212                    ModuleDef::Static(idx, _ty) => {
1213                        let mut defs = Vec::new();
1214                        for (module, name, _ty) in self.nested_modules[*idx].module.imports() {
1215                            let instance = args[module];
1216                            defs.push(
1217                                self.core_def_of_module_instance_export(frame, instance, name),
1218                            );
1219                        }
1220                        (
1221                            InstanceModule::Static(*idx),
1222                            dfg::Instance::Static(*idx, defs.into()),
1223                        )
1224                    }
1225                    ModuleDef::Import(path, ty) => {
1226                        let mut defs = IndexMap::new();
1227                        for ((module, name), _) in types[*ty].imports.iter() {
1228                            let instance = args[module.as_str()];
1229                            let def =
1230                                self.core_def_of_module_instance_export(frame, instance, name);
1231                            defs.entry(module.to_string())
1232                                .or_insert(IndexMap::new())
1233                                .insert(name.to_string(), def);
1234                        }
1235                        let index = self.runtime_import(path);
1236                        (
1237                            InstanceModule::Import(*ty),
1238                            dfg::Instance::Import(index, defs),
1239                        )
1240                    }
1241                };
1242
1243                let instance = self.result.instances.push(init);
1244                let instance2 = self.runtime_instances.push(instance_module);
1245                assert_eq!(instance, instance2);
1246
1247                self.result
1248                    .side_effects
1249                    .push(dfg::SideEffect::Instance(instance, frame.instance));
1250
1251                frame
1252                    .module_instances
1253                    .push(ModuleInstanceDef::Instantiated(instance, *module));
1254            }
1255
1256            ModuleSynthetic(map) => {
1257                frame
1258                    .module_instances
1259                    .push(ModuleInstanceDef::Synthetic(map));
1260            }
1261
1262            // This is one of the stages of the "magic" of implementing outer
1263            // aliases to components and modules. For more information on this
1264            // see the documentation on `LexicalScope`. This stage of the
1265            // implementation of outer aliases is where the `ClosedOverVars` is
1266            // transformed into a `ComponentClosure` state using the current
1267            // `InlinerFrame`'s state. This will capture the "runtime" state of
1268            // outer components and upvars and such naturally as part of the
1269            // inlining process.
1270            ComponentStatic(index, vars) => {
1271                frame.components.push(ComponentDef {
1272                    index: *index,
1273                    closure: ComponentClosure {
1274                        modules: vars
1275                            .modules
1276                            .iter()
1277                            .map(|(_, m)| frame.closed_over_module(m))
1278                            .collect(),
1279                        components: vars
1280                            .components
1281                            .iter()
1282                            .map(|(_, m)| frame.closed_over_component(m))
1283                            .collect(),
1284                    },
1285                });
1286            }
1287
1288            // Like module instantiation is this is a "meaty" part, and don't be
1289            // fooled by the relative simplicity of this case. This is
1290            // implemented primarily by the `Inliner` structure and the design
1291            // of this entire module, so the "easy" step here is to simply
1292            // create a new inliner frame and return it to get pushed onto the
1293            // stack.
1294            ComponentInstantiate(component, args, ty) => {
1295                let component: &ComponentDef<'a> = &frame.components[*component];
1296                let index = RuntimeComponentInstanceIndex::from_u32(
1297                    self.result.num_runtime_component_instances,
1298                );
1299                self.result.num_runtime_component_instances += 1;
1300                let frame = InlinerFrame::new(
1301                    index,
1302                    &self.nested_components[component.index],
1303                    component.closure.clone(),
1304                    args.iter()
1305                        .map(|(name, item)| Ok((*name, frame.item(*item, types)?)))
1306                        .collect::<Result<_>>()?,
1307                    Some(*ty),
1308                );
1309                return Ok(Some(frame));
1310            }
1311
1312            ComponentSynthetic(map, ty) => {
1313                let items = map
1314                    .iter()
1315                    .map(|(name, (index, data))| Ok((*name, (frame.item(*index, types)?, *data))))
1316                    .collect::<Result<_>>()?;
1317                let types_ref = frame.translation.types_ref();
1318                let ty = types.convert_instance(types_ref, *ty)?;
1319                frame
1320                    .component_instances
1321                    .push(ComponentInstanceDef::Items(items, ty));
1322            }
1323
1324            // Core wasm aliases, this and the cases below, are creating
1325            // `CoreExport` items primarily to insert into the index space so we
1326            // can create a unique identifier pointing to each core wasm export
1327            // with the instance and relevant index/name as necessary.
1328            AliasExportFunc(instance, name) => {
1329                let (ty, def) = match &frame.module_instances[*instance] {
1330                    ModuleInstanceDef::Instantiated(instance, module) => {
1331                        let (ty, item) = match &frame.modules[*module] {
1332                            ModuleDef::Static(idx, _ty) => {
1333                                let name = self.nested_modules[*idx]
1334                                    .module
1335                                    .strings
1336                                    .get_atom(name)
1337                                    .unwrap();
1338                                let entity = self.nested_modules[*idx].module.exports[&name];
1339                                let ty = match entity {
1340                                    EntityIndex::Function(f) => {
1341                                        self.nested_modules[*idx].module.functions[f]
1342                                            .signature
1343                                            .unwrap_module_type_index()
1344                                    }
1345                                    _ => unreachable!(),
1346                                };
1347                                (ty, ExportItem::Index(entity))
1348                            }
1349                            ModuleDef::Import(_path, module_ty) => {
1350                                let module_ty = &types.component_types()[*module_ty];
1351                                let entity_ty = &module_ty.exports[&**name];
1352                                let ty = entity_ty.unwrap_func().unwrap_module_type_index();
1353                                (ty, ExportItem::Name((*name).to_string()))
1354                            }
1355                        };
1356                        let def = dfg::CoreExport {
1357                            instance: *instance,
1358                            item,
1359                        }
1360                        .into();
1361                        (ty, def)
1362                    }
1363                    ModuleInstanceDef::Synthetic(instance) => match instance[*name] {
1364                        EntityIndex::Function(i) => frame.funcs[i].clone(),
1365                        _ => unreachable!(),
1366                    },
1367                };
1368                frame.funcs.push((ty, def));
1369            }
1370
1371            AliasExportTable(instance, name) => {
1372                frame.tables.push(
1373                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1374                        dfg::CoreDef::Export(e) => e,
1375                        _ => unreachable!(),
1376                    },
1377                );
1378            }
1379
1380            AliasExportGlobal(instance, name) => {
1381                frame.globals.push(
1382                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1383                        dfg::CoreDef::Export(e) => e,
1384                        _ => unreachable!(),
1385                    },
1386                );
1387            }
1388
1389            AliasExportMemory(instance, name) => {
1390                frame.memories.push(
1391                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1392                        dfg::CoreDef::Export(e) => e,
1393                        _ => unreachable!(),
1394                    },
1395                );
1396            }
1397
1398            AliasExportTag(instance, name) => {
1399                frame.tags.push(
1400                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1401                        dfg::CoreDef::Export(e) => e,
1402                        _ => unreachable!(),
1403                    },
1404                );
1405            }
1406
1407            AliasComponentExport(instance, name) => {
1408                match &frame.component_instances[*instance] {
1409                    ComponentInstanceDef::Intrinsics => {
1410                        frame.push_item(ComponentItemDef::Func(ComponentFuncDef::UnsafeIntrinsic(
1411                            UnsafeIntrinsic::from_str(name)?,
1412                        )));
1413                    }
1414
1415                    // Aliasing an export from an imported instance means that
1416                    // we're extending the `ImportPath` by one name, represented
1417                    // with the clone + push here. Afterwards an appropriate
1418                    // item is then pushed in the relevant index space.
1419                    ComponentInstanceDef::Import(path, ty) => {
1420                        let path = path.push(*name);
1421                        let def =
1422                            ComponentItemDef::from_import(path, types[*ty].exports[*name].ty)?;
1423                        frame.push_item(def);
1424                    }
1425
1426                    // Given a component instance which was either created
1427                    // through instantiation of a component or through a
1428                    // synthetic renaming of items we just schlep around the
1429                    // definitions of various items here.
1430                    ComponentInstanceDef::Items(map, _) => frame.push_item(map[*name].0.clone()),
1431                }
1432            }
1433
1434            // For more information on these see `LexicalScope` but otherwise
1435            // this is just taking a closed over variable and inserting the
1436            // actual definition into the local index space since this
1437            // represents an outer alias to a module/component
1438            AliasModule(idx) => {
1439                frame.modules.push(frame.closed_over_module(idx));
1440            }
1441            AliasComponent(idx) => {
1442                frame.components.push(frame.closed_over_component(idx));
1443            }
1444
1445            Export(item) => match item {
1446                ComponentItem::Func(i) => {
1447                    frame
1448                        .component_funcs
1449                        .push(frame.component_funcs[*i].clone());
1450                }
1451                ComponentItem::Module(i) => {
1452                    frame.modules.push(frame.modules[*i].clone());
1453                }
1454                ComponentItem::Component(i) => {
1455                    frame.components.push(frame.components[*i].clone());
1456                }
1457                ComponentItem::ComponentInstance(i) => {
1458                    frame
1459                        .component_instances
1460                        .push(frame.component_instances[*i].clone());
1461                }
1462
1463                // Type index spaces aren't maintained during this inlining pass
1464                // so ignore this.
1465                ComponentItem::Type(_) => {}
1466            },
1467        }
1468
1469        Ok(None)
1470    }
1471
1472    /// "Commits" a path of an import to an actual index which is something that
1473    /// will be calculated at runtime.
1474    ///
1475    /// Note that the cost of calculating an item for a `RuntimeImportIndex` at
1476    /// runtime is amortized with an `InstancePre` which represents "all the
1477    /// runtime imports are lined up" and after that no more name resolution is
1478    /// necessary.
1479    fn runtime_import(&mut self, path: &ImportPath<'a>) -> RuntimeImportIndex {
1480        *self
1481            .import_path_interner
1482            .entry(path.clone())
1483            .or_insert_with(|| {
1484                self.result.imports.push((
1485                    path.index,
1486                    path.path.iter().map(|s| s.to_string()).collect(),
1487                ))
1488            })
1489    }
1490
1491    /// Returns the `CoreDef`, the canonical definition for a core wasm item,
1492    /// for the export `name` of `instance` within `frame`.
1493    fn core_def_of_module_instance_export(
1494        &self,
1495        frame: &InlinerFrame<'a>,
1496        instance: ModuleInstanceIndex,
1497        name: &'a str,
1498    ) -> dfg::CoreDef {
1499        match &frame.module_instances[instance] {
1500            // Instantiations of a statically known module means that we can
1501            // refer to the exported item by a precise index, skipping name
1502            // lookups at runtime.
1503            //
1504            // Instantiations of an imported module, however, must do name
1505            // lookups at runtime since we don't know the structure ahead of
1506            // time here.
1507            ModuleInstanceDef::Instantiated(instance, module) => {
1508                let item = match frame.modules[*module] {
1509                    ModuleDef::Static(idx, _ty) => {
1510                        let name = self.nested_modules[idx]
1511                            .module
1512                            .strings
1513                            .get_atom(name)
1514                            .unwrap();
1515                        let entity = self.nested_modules[idx].module.exports[&name];
1516                        ExportItem::Index(entity)
1517                    }
1518                    ModuleDef::Import(..) => ExportItem::Name(name.to_string()),
1519                };
1520                dfg::CoreExport {
1521                    instance: *instance,
1522                    item,
1523                }
1524                .into()
1525            }
1526
1527            // This is a synthetic instance so the canonical definition of the
1528            // original item is returned.
1529            ModuleInstanceDef::Synthetic(instance) => match instance[name] {
1530                EntityIndex::Function(i) => frame.funcs[i].1.clone(),
1531                EntityIndex::Table(i) => frame.tables[i].clone().into(),
1532                EntityIndex::Global(i) => frame.globals[i].clone().into(),
1533                EntityIndex::Memory(i) => frame.memories[i].clone().into(),
1534                EntityIndex::Tag(i) => frame.tags[i].clone().into(),
1535            },
1536        }
1537    }
1538
1539    fn memory(
1540        &mut self,
1541        frame: &InlinerFrame<'a>,
1542        types: &ComponentTypesBuilder,
1543        memory: MemoryIndex,
1544    ) -> (dfg::CoreExport<MemoryIndex>, Memory) {
1545        let memory = frame.memories[memory].clone().map_index(|i| match i {
1546            EntityIndex::Memory(i) => i,
1547            _ => unreachable!(),
1548        });
1549        let ty = match &self.runtime_instances[memory.instance] {
1550            InstanceModule::Static(idx) => match &memory.item {
1551                ExportItem::Index(i) => self.nested_modules[*idx].module.memories[*i],
1552                ExportItem::Name(_) => unreachable!(),
1553            },
1554            InstanceModule::Import(ty) => match &memory.item {
1555                ExportItem::Name(name) => match types[*ty].exports[name] {
1556                    EntityType::Memory(m) => m,
1557                    _ => unreachable!(),
1558                },
1559                ExportItem::Index(_) => unreachable!(),
1560            },
1561        };
1562        (memory, ty)
1563    }
1564
1565    /// Translates a `LocalCanonicalOptions` which indexes into the `frame`
1566    /// specified into a runtime representation.
1567    fn adapter_options(
1568        &mut self,
1569        frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>,
1570        types: &ComponentTypesBuilder,
1571        options: &LocalCanonicalOptions,
1572    ) -> AdapterOptions {
1573        let (frame, _) = frames.last_mut().unwrap();
1574        let data_model = match options.data_model {
1575            LocalDataModel::Gc {} => DataModel::Gc {},
1576            LocalDataModel::LinearMemory { memory, realloc } => {
1577                let memory = memory.map(|i| self.memory(frame, types, i));
1578                let realloc = realloc.map(|i| frame.funcs[i].1.clone());
1579                DataModel::LinearMemory { memory, realloc }
1580            }
1581        };
1582        let callback = options.callback.map(|i| frame.funcs[i].1.clone());
1583        let post_return = options.post_return.map(|i| frame.funcs[i].1.clone());
1584        AdapterOptions {
1585            instance: frame.instance,
1586            string_encoding: options.string_encoding,
1587            callback,
1588            post_return,
1589            async_: options.async_,
1590            cancellable: options.cancellable,
1591            core_type: options.core_type,
1592            data_model,
1593        }
1594    }
1595
1596    /// Translates an `AdapterOptions` into a `CanonicalOptions` where
1597    /// memories/functions are inserted into the global initializer list for
1598    /// use at runtime. This is only used for lowered host functions and lifted
1599    /// functions exported to the host.
1600    fn canonical_options(&mut self, options: AdapterOptions) -> dfg::OptionsId {
1601        let data_model = match options.data_model {
1602            DataModel::Gc {} => dfg::CanonicalOptionsDataModel::Gc {},
1603            DataModel::LinearMemory { memory, realloc } => {
1604                dfg::CanonicalOptionsDataModel::LinearMemory {
1605                    memory: memory.map(|(export, _)| self.result.memories.push(export)),
1606                    realloc: realloc.map(|def| self.result.reallocs.push(def)),
1607                }
1608            }
1609        };
1610        let callback = options.callback.map(|def| self.result.callbacks.push(def));
1611        let post_return = options
1612            .post_return
1613            .map(|def| self.result.post_returns.push(def));
1614        self.result.options.push(dfg::CanonicalOptions {
1615            instance: options.instance,
1616            string_encoding: options.string_encoding,
1617            callback,
1618            post_return,
1619            async_: options.async_,
1620            cancellable: options.cancellable,
1621            core_type: options.core_type,
1622            data_model,
1623        })
1624    }
1625
1626    fn record_export(
1627        &mut self,
1628        name: &str,
1629        def: ComponentItemDef<'a>,
1630        data: ComponentExternData,
1631        types: &'a ComponentTypesBuilder,
1632        map: &mut IndexMap<String, (dfg::Export, ComponentExternData)>,
1633    ) -> Result<()> {
1634        let export = match def {
1635            // Exported modules are currently saved in a `PrimaryMap`, at
1636            // runtime, so an index (`RuntimeModuleIndex`) is assigned here and
1637            // then an initializer is recorded about where the module comes
1638            // from.
1639            ComponentItemDef::Module(module) => match module {
1640                ModuleDef::Static(index, ty) => dfg::Export::ModuleStatic { ty, index },
1641                ModuleDef::Import(path, ty) => dfg::Export::ModuleImport {
1642                    ty,
1643                    import: self.runtime_import(&path),
1644                },
1645            },
1646
1647            ComponentItemDef::Func(func) => match func {
1648                // If this is a lifted function from something lowered in this
1649                // component then the configured options are plumbed through
1650                // here.
1651                ComponentFuncDef::Lifted { ty, func, options } => {
1652                    let options = self.canonical_options(options);
1653                    dfg::Export::LiftedFunction { ty, func, options }
1654                }
1655
1656                // Currently reexported functions from an import are not
1657                // supported. Being able to actually call these functions is
1658                // somewhat tricky and needs something like temporary scratch
1659                // space that isn't implemented.
1660                ComponentFuncDef::Import(_) => {
1661                    bail!(
1662                        "component export `{name}` is a reexport of an imported function which is not implemented"
1663                    )
1664                }
1665
1666                ComponentFuncDef::UnsafeIntrinsic(_) => {
1667                    bail!(
1668                        "component export `{name}` is a reexport of an intrinsic function which is not supported"
1669                    )
1670                }
1671            },
1672
1673            ComponentItemDef::Instance(instance) => {
1674                let mut exports = IndexMap::new();
1675                match instance {
1676                    ComponentInstanceDef::Intrinsics => {
1677                        bail!(
1678                            "component export `{name}` is a reexport of the intrinsics instance which is not supported"
1679                        )
1680                    }
1681
1682                    // If this instance is one that was originally imported by
1683                    // the component itself then the imports are translated here
1684                    // by converting to a `ComponentItemDef` and then
1685                    // recursively recording the export as a reexport.
1686                    //
1687                    // Note that for now this would only work with
1688                    // module-exporting instances.
1689                    ComponentInstanceDef::Import(path, ty) => {
1690                        for (name, ty) in types[ty].exports.iter() {
1691                            let path = path.push(name);
1692                            let def = ComponentItemDef::from_import(path, ty.ty)?;
1693                            self.record_export(name, def, ty.data.clone(), types, &mut exports)?;
1694                        }
1695                        dfg::Export::Instance { ty, exports }
1696                    }
1697
1698                    // An exported instance which is itself a bag of items is
1699                    // translated recursively here to our `exports` map which is
1700                    // the bag of items we're exporting.
1701                    ComponentInstanceDef::Items(map, ty) => {
1702                        for (name, (def, data)) in map {
1703                            let data = ComponentExternData::new(data);
1704                            self.record_export(name, def, data.clone(), types, &mut exports)?;
1705                        }
1706                        dfg::Export::Instance { ty, exports }
1707                    }
1708                }
1709            }
1710
1711            // FIXME(#4283) should make an official decision on whether this is
1712            // the final treatment of this or not.
1713            ComponentItemDef::Component(_) => {
1714                bail!("exporting a component from the root component is not supported")
1715            }
1716
1717            ComponentItemDef::Type(def) => dfg::Export::Type(def),
1718        };
1719
1720        map.insert(name.to_string(), (export, data));
1721        Ok(())
1722    }
1723}
1724
1725impl<'a> InlinerFrame<'a> {
1726    fn new(
1727        instance: RuntimeComponentInstanceIndex,
1728        translation: &'a Translation<'a>,
1729        closure: ComponentClosure<'a>,
1730        args: HashMap<&'a str, ComponentItemDef<'a>>,
1731        instance_ty: Option<ComponentInstanceTypeId>,
1732    ) -> Self {
1733        // FIXME: should iterate over the initializers of `translation` and
1734        // calculate the size of each index space to use `with_capacity` for
1735        // all the maps below. Given that doing such would be wordy and compile
1736        // time is otherwise not super crucial it's not done at this time.
1737        InlinerFrame {
1738            instance,
1739            translation,
1740            closure,
1741            args,
1742            instance_ty,
1743            initializers: translation.initializers.iter(),
1744
1745            funcs: Default::default(),
1746            memories: Default::default(),
1747            tables: Default::default(),
1748            globals: Default::default(),
1749            tags: Default::default(),
1750
1751            component_instances: Default::default(),
1752            component_funcs: Default::default(),
1753            module_instances: Default::default(),
1754            components: Default::default(),
1755            modules: Default::default(),
1756        }
1757    }
1758
1759    fn item(
1760        &self,
1761        index: ComponentItem,
1762        types: &mut ComponentTypesBuilder,
1763    ) -> Result<ComponentItemDef<'a>> {
1764        Ok(match index {
1765            ComponentItem::Func(i) => ComponentItemDef::Func(self.component_funcs[i].clone()),
1766            ComponentItem::Component(i) => ComponentItemDef::Component(self.components[i].clone()),
1767            ComponentItem::ComponentInstance(i) => {
1768                ComponentItemDef::Instance(self.component_instances[i].clone())
1769            }
1770            ComponentItem::Module(i) => ComponentItemDef::Module(self.modules[i].clone()),
1771            ComponentItem::Type(t) => {
1772                let types_ref = self.translation.types_ref();
1773                ComponentItemDef::Type(types.convert_type(types_ref, t)?)
1774            }
1775        })
1776    }
1777
1778    /// Pushes the component `item` definition provided into the appropriate
1779    /// index space within this component.
1780    fn push_item(&mut self, item: ComponentItemDef<'a>) {
1781        match item {
1782            ComponentItemDef::Func(i) => {
1783                self.component_funcs.push(i);
1784            }
1785            ComponentItemDef::Module(i) => {
1786                self.modules.push(i);
1787            }
1788            ComponentItemDef::Component(i) => {
1789                self.components.push(i);
1790            }
1791            ComponentItemDef::Instance(i) => {
1792                self.component_instances.push(i);
1793            }
1794
1795            // In short, type definitions aren't tracked here.
1796            //
1797            // The longer form explanation for this is that structural types
1798            // like lists and records don't need to be tracked at all and the
1799            // only significant type which needs tracking is resource types
1800            // themselves. Resource types, however, are tracked within the
1801            // `ResourcesBuilder` state rather than an `InlinerFrame` so they're
1802            // ignored here as well. The general reason for that is that type
1803            // information is everywhere and this `InlinerFrame` is not
1804            // everywhere so it seemed like it would make sense to split the
1805            // two.
1806            //
1807            // Note though that this case is actually frequently hit, so it
1808            // can't be `unreachable!()`. Instead callers are responsible for
1809            // handling this appropriately with respect to resources.
1810            ComponentItemDef::Type(_ty) => {}
1811        }
1812    }
1813
1814    fn closed_over_module(&self, index: &ClosedOverModule) -> ModuleDef<'a> {
1815        match *index {
1816            ClosedOverModule::Local(i) => self.modules[i].clone(),
1817            ClosedOverModule::Upvar(i) => self.closure.modules[i].clone(),
1818        }
1819    }
1820
1821    fn closed_over_component(&self, index: &ClosedOverComponent) -> ComponentDef<'a> {
1822        match *index {
1823            ClosedOverComponent::Local(i) => self.components[i].clone(),
1824            ClosedOverComponent::Upvar(i) => self.closure.components[i].clone(),
1825        }
1826    }
1827
1828    /// Completes the instantiation of a subcomponent and records type
1829    /// information for the instance that was produced.
1830    ///
1831    /// This method is invoked when an `InlinerFrame` finishes for a
1832    /// subcomponent. The `def` provided represents the instance that was
1833    /// produced from instantiation, and `ty` is the wasmparser-defined type of
1834    /// the instance produced.
1835    ///
1836    /// The purpose of this method is to record type information about resources
1837    /// in the instance produced. In the component model all instantiations of a
1838    /// component produce fresh new types for all resources which are unequal to
1839    /// all prior resources. This means that if wasmparser's `ty` type
1840    /// information references a unique resource within `def` that has never
1841    /// been registered before then that means it's a defined resource within
1842    /// the component that was just instantiated (as opposed to an imported
1843    /// resource which was reexported).
1844    ///
1845    /// Further type translation after this instantiation can refer to these
1846    /// resource types and a mapping from those types to the wasmtime-internal
1847    /// types is required, so this method builds up those mappings.
1848    ///
1849    /// Essentially what happens here is that the `ty` type is registered and
1850    /// any new unique resources are registered so new tables can be introduced
1851    /// along with origin information about the actual underlying resource type
1852    /// and which component instantiated it.
1853    fn finish_instantiate(
1854        &mut self,
1855        exports: IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>,
1856        ty: ComponentInstanceTypeId,
1857        types: &mut ComponentTypesBuilder,
1858    ) -> Result<()> {
1859        let types_ref = self.translation.types_ref();
1860        {
1861            let (resources, types) = types.resources_mut_and_types();
1862            let mut path = Vec::new();
1863            resources.register_component_entity_type(
1864                &types_ref,
1865                ComponentEntityType::Instance(ty),
1866                &mut path,
1867                &mut |path| match path {
1868                    [] => unreachable!(),
1869                    [name, rest @ ..] => exports[name].0.lookup_resource(rest, types),
1870                },
1871            );
1872        }
1873        let ty = types.convert_instance(types_ref, ty)?;
1874        let def = ComponentInstanceDef::Items(exports, ty);
1875        let arg = ComponentItemDef::Instance(def);
1876        self.push_item(arg);
1877        Ok(())
1878    }
1879}
1880
1881impl<'a> ImportPath<'a> {
1882    fn root(index: ImportIndex) -> ImportPath<'a> {
1883        ImportPath {
1884            index,
1885            path: Vec::new(),
1886        }
1887    }
1888
1889    fn push(&self, s: impl Into<Cow<'a, str>>) -> ImportPath<'a> {
1890        let mut new = self.clone();
1891        new.path.push(s.into());
1892        new
1893    }
1894}
1895
1896impl<'a> ComponentItemDef<'a> {
1897    fn from_import(path: ImportPath<'a>, ty: TypeDef) -> Result<ComponentItemDef<'a>> {
1898        let item = match ty {
1899            TypeDef::Module(ty) => ComponentItemDef::Module(ModuleDef::Import(path, ty)),
1900            TypeDef::ComponentInstance(ty) => {
1901                ComponentItemDef::Instance(ComponentInstanceDef::Import(path, ty))
1902            }
1903            TypeDef::ComponentFunc(_ty) => ComponentItemDef::Func(ComponentFuncDef::Import(path)),
1904            // FIXME(#4283) should commit one way or another to how this
1905            // should be treated.
1906            TypeDef::Component(_ty) => bail!("root-level component imports are not supported"),
1907            TypeDef::Interface(_) | TypeDef::Resource(_) => ComponentItemDef::Type(ty),
1908            TypeDef::CoreFunc(_) => unreachable!(),
1909        };
1910        Ok(item)
1911    }
1912
1913    /// Walks the `path` within `self` to find a resource at that path.
1914    ///
1915    /// This method is used when resources are found within wasmparser's type
1916    /// information and they need to be correlated with actual concrete
1917    /// definitions from this inlining pass. The `path` here is a list of
1918    /// instance export names (or empty) to walk to reach down into the final
1919    /// definition which should refer to a resource itself.
1920    fn lookup_resource(&self, path: &[&str], types: &ComponentTypes) -> ResourceIndex {
1921        let mut cur = self.clone();
1922
1923        // Each element of `path` represents unwrapping a layer of an instance
1924        // type, so handle those here by updating `cur` iteratively.
1925        for element in path.iter().copied() {
1926            let instance = match cur {
1927                ComponentItemDef::Instance(def) => def,
1928                _ => unreachable!(),
1929            };
1930            cur = match instance {
1931                // If this instance is a "bag of things" then this is as easy as
1932                // looking up the name in the bag of names.
1933                ComponentInstanceDef::Items(names, _) => names[element].0.clone(),
1934
1935                // If, however, this instance is an imported instance then this
1936                // is a further projection within the import with one more path
1937                // element. The `types` type information is used to lookup the
1938                // type of `element` within the instance type, and that's used
1939                // in conjunction with a one-longer `path` to produce a new item
1940                // definition.
1941                ComponentInstanceDef::Import(path, ty) => {
1942                    ComponentItemDef::from_import(path.push(element), types[ty].exports[element].ty)
1943                        .unwrap()
1944                }
1945                ComponentInstanceDef::Intrinsics => {
1946                    unreachable!("intrinsics do not define resources")
1947                }
1948            };
1949        }
1950
1951        // Once `path` has been iterated over it must be the case that the final
1952        // item is a resource type, in which case a lookup can be performed.
1953        match cur {
1954            ComponentItemDef::Type(TypeDef::Resource(idx)) => types[idx].unwrap_concrete_ty(),
1955            _ => unreachable!(),
1956        }
1957    }
1958}
1959
1960#[derive(Clone, Copy)]
1961enum InstanceModule {
1962    Static(StaticModuleIndex),
1963    Import(TypeModuleIndex),
1964}
1965
1966impl ComponentExternData {
1967    fn new(data: wasmparser::ComponentExternName<'_>) -> Self {
1968        ComponentExternData {
1969            implements: data.implements.map(|s| s.to_string()),
1970            external_id: data.external_id.map(|s| s.to_string()),
1971        }
1972    }
1973}