wirm 3.0.0

A lightweight WebAssembly Transformation Library for the Component Model
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
use crate::ir::component::idx_spaces::Space;
use crate::ir::component::refs::{IndexedRef, RefKind};
use crate::ir::component::visitor::driver::{drive_event, VisitEvent};
use crate::ir::component::visitor::events_structural::get_structural_events;
use crate::ir::component::visitor::events_topological::get_topological_events;
use crate::ir::component::visitor::utils::VisitCtxInner;
use crate::ir::types::CustomSection;
use crate::{Component, Module};
use wasmparser::{
    CanonicalFunction, ComponentAlias, ComponentExport, ComponentImport, ComponentInstance,
    ComponentStartFunction, ComponentType, ComponentTypeDeclaration, CoreType, Instance,
    InstanceTypeDeclaration, ModuleTypeDeclaration, SubType,
};

pub(crate) mod driver;
mod events_structural;
pub(crate) mod events_topological;
#[cfg(test)]
mod tests;
pub(crate) mod utils;

/// Walk a [`Component`] using its *structural* (in-file) order.
///
/// This traversal visits items in the same order they appear in the
/// component’s section layout. Nested components are entered and exited
/// according to their lexical structure, and all visitor callbacks are
/// invoked in a manner consistent with the original encoding order.
///
/// # Semantics
///
/// - Preserves section order exactly as defined in the component.
/// - Nested components are visited depth-first.
/// - Scope management and ID resolution are handled internally.
/// - No reordering is performed to satisfy reference dependencies.
///
/// This is the most appropriate traversal for:
///
/// - Analysis passes
/// - Pretty-printing
/// - Validation-like inspections
/// - Any logic that expects lexical ordering
///
/// # Guarantees
///
/// - No forward-reference elimination is attempted.
/// - The visitor observes the same structural hierarchy as encoded.
/// - `enter_component` / `exit_component` callbacks are properly paired.
///
/// See also [`walk_topological`] for a dependency-ordered traversal.
pub fn walk_structural<'ir, V: ComponentVisitor<'ir>>(root: &'ir Component<'ir>, visitor: &mut V) {
    walk(get_structural_events, root, visitor);
}

/// Walk a [`Component`] in *topological* (dependency) order.
///
/// This traversal reorders items such that definitions are visited
/// before any items that reference them. The resulting visitation
/// order contains no forward references, making it suitable for
/// encoding or transforming components that require dependency-safe
/// emission.
///
/// # Semantics
///
/// - Items are visited in a dependency-respecting order.
/// - Nested components are still entered/exited with correct scope
///   management.
/// - All visitor callbacks observe valid, already-declared references.
/// - Structural layout order is **not** preserved.
///
/// # When to Use
///
/// This traversal is intended for:
///
/// - Component encoding
/// - Instrumentation passes
/// - Lowering or rewriting IR where forward references are illegal
/// - Any pass that requires reference-safe emission order
///
/// # Guarantees
///
/// - No visitor callback observes an unresolved forward reference.
/// - Scope handling and ID resolution remain logically consistent.
/// - `enter_component` / `exit_component` callbacks are properly paired.
///
/// See also [`walk_structural`] for lexical-order traversal.
pub fn walk_topological<'ir, V: ComponentVisitor<'ir>>(root: &'ir Component<'ir>, visitor: &mut V) {
    walk(get_topological_events, root, visitor);
}

fn walk<'ir, V: ComponentVisitor<'ir>>(
    get_evts: fn(&'ir Component<'ir>, &mut VisitCtx<'ir>, &mut Vec<VisitEvent<'ir>>),
    root: &'ir Component<'ir>,
    visitor: &mut V,
) {
    let mut ctx = VisitCtx::new(root);
    let mut events = Vec::new();
    get_evts(root, &mut ctx, &mut events);

    for event in events.iter() {
        drive_event(event, visitor, &mut ctx);
    }
}

/// A structured, read-only visitor over a [`Component`] tree.
///
/// All methods have default no-op implementations. Override only the
/// callbacks relevant to your use case.
///
/// # Guarantees
///
/// - `enter_component` and `exit_component` are always properly paired.
/// - Nested components are visited in a well-structured manner.
/// - IDs are resolved and stable within a single traversal.
///
/// # ID Semantics
///
/// - `id: None` is used only for the root component.
/// - All other items receive a resolved `u32` ID corresponding to their
///   index within the appropriate namespace at that depth.
/// - For items that may belong to multiple namespaces (e.g. imports,
///   exports, aliases, canonical functions), the `ItemKind` parameter
///   indicates the resolved kind of the item.
///
/// # Mutation
///
/// This visitor is strictly read-only. Implementations must not mutate
/// the underlying component structure.
pub trait ComponentVisitor<'a> {
    /// Invoked when entering the outermost, root component to enable special handling.
    ///
    /// This is the earliest hook available for a component.
    fn enter_root_component(&mut self, _cx: &VisitCtx<'a>, _component: &Component<'a>) {}
    /// Invoked after all items within the root component have been visited.
    ///
    /// Always paired with a prior `enter_root_component` call.
    fn exit_root_component(&mut self, _cx: &VisitCtx<'a>, _component: &Component<'a>) {}
    /// Invoked when entering a subcomponent within the root.
    ///
    /// The `id` corresponds to the resolved component index within the
    /// current namespace. This callback is paired with `exit_component`
    /// once traversal of the component’s body has completed.
    fn enter_component(&mut self, _cx: &VisitCtx<'a>, _id: u32, _component: &Component<'a>) {}
    /// Invoked after all items within a subcomponent have been visited.
    ///
    /// Always paired with a prior `enter_component` call.
    fn exit_component(&mut self, _cx: &VisitCtx<'a>, _id: u32, _component: &Component<'a>) {}
    /// Invoked for each core WebAssembly module defined in the component.
    ///
    /// The `id` corresponds to the module’s resolved index within the
    /// current core module namespace.
    fn visit_module(&mut self, _cx: &VisitCtx<'a>, _id: u32, _module: &Module<'a>) {}

    // ------------------------
    // Component-level items
    // ------------------------

    /// Invoked when entering a component-level type definition.
    ///
    /// This includes all variants of `ComponentType`, such as defined,
    /// function, component, instance, and resource types.
    ///
    /// The `id` corresponds to the resolved type index within the
    /// component type namespace.
    ///
    /// This callback is paired with `exit_comp_type`, and any nested
    /// declarations (e.g. `ComponentTypeDeclaration` or
    /// `InstanceTypeDeclaration`) will be reported between the enter/exit
    /// calls.
    fn enter_comp_type(&mut self, _cx: &VisitCtx<'a>, _id: u32, _comp_type: &ComponentType<'a>) {}

    /// Invoked for each declaration within a `ComponentType::Component`.
    ///
    /// The `decl_idx` is the index of this declaration within the parent
    /// component type’s declaration list. The `parent` is the enclosing
    /// `ComponentType`, and `decl` is the specific declaration.
    ///
    /// These callbacks are emitted between `enter_comp_type` and
    /// `exit_comp_type` for the enclosing type.
    fn visit_comp_type_decl(
        &mut self,
        _cx: &VisitCtx<'a>,
        _decl_idx: usize,
        _id: u32,
        _parent: &ComponentType<'a>,
        _decl: &ComponentTypeDeclaration<'a>,
    ) {
    }

    /// Invoked for each declaration within a `ComponentType::Instance`.
    ///
    /// The `decl_idx` is the index of this declaration within the parent
    /// instance type’s declaration list. The `parent` is the enclosing
    /// `ComponentType`, and `decl` is the specific instance type
    /// declaration.
    ///
    /// These callbacks are emitted between `enter_comp_type` and
    /// `exit_comp_type` for the enclosing type.
    fn visit_inst_type_decl(
        &mut self,
        _cx: &VisitCtx<'a>,
        _decl_idx: usize,
        _id: u32,
        _parent: &ComponentType<'a>,
        _decl: &InstanceTypeDeclaration<'a>,
    ) {
    }

    /// Invoked after all nested declarations within a component-level
    /// type have been visited.
    ///
    /// Always paired with a prior `enter_comp_type` call for the same `id`.
    fn exit_comp_type(&mut self, _cx: &VisitCtx<'a>, _id: u32, _comp_type: &ComponentType<'a>) {}

    /// Invoked for each component instance.
    ///
    /// The `id` corresponds to the resolved instance index within the
    /// component instance namespace.
    fn visit_comp_instance(
        &mut self,
        _cx: &VisitCtx<'a>,
        _id: u32,
        _instance: &ComponentInstance<'a>,
    ) {
    }

    // ------------------------------------------------
    // Items with multiple possible resolved namespaces
    // ------------------------------------------------

    /// Invoked for canonical functions.
    ///
    /// The `kind` parameter indicates the resolved namespace of this item
    /// (e.g. component function vs. core function).
    ///
    /// The `id` is the resolved index within the namespace identified
    /// by `kind`.
    fn visit_canon(
        &mut self,
        _cx: &VisitCtx<'a>,
        _kind: ItemKind,
        _id: u32,
        _canon: &CanonicalFunction,
    ) {
    }

    /// Invoked for component aliases.
    ///
    /// The `kind` parameter indicates the resolved target namespace
    /// referenced by the alias.
    ///
    /// The `id` is the resolved index of the alias within its namespace.
    fn visit_alias(
        &mut self,
        _cx: &VisitCtx<'a>,
        _kind: ItemKind,
        _id: u32,
        _alias: &ComponentAlias<'a>,
    ) {
    }

    /// Invoked for component imports.
    ///
    /// The `kind` parameter identifies the imported item category
    /// (e.g. type, function, instance).
    ///
    /// The `id` is the resolved index assigned to the imported item
    /// within the corresponding namespace.
    fn visit_comp_import(
        &mut self,
        _cx: &VisitCtx<'a>,
        _kind: ItemKind,
        _id: u32,
        _import: &ComponentImport<'a>,
    ) {
    }

    /// Invoked for component exports.
    ///
    /// The `kind` parameter identifies the exported item category.
    ///
    /// The `id` is the resolved index of the exported item within the
    /// corresponding namespace.
    fn visit_comp_export(
        &mut self,
        _cx: &VisitCtx<'a>,
        _kind: ItemKind,
        _id: u32,
        _export: &ComponentExport<'a>,
    ) {
    }

    // ============================================================
    // Core Recursion Groups (`core rec`)
    // ============================================================

    /// Called when entering a core recursion group (`core rec`).
    ///
    /// A recursion group defines one or more mutually recursive core
    /// subtypes that are allocated as a unit in the core type index
    /// space. All subtypes belonging to this group will be reported
    /// via subsequent `visit_core_subtype` calls, followed by a single
    /// `exit_core_rec_group`.
    ///
    /// Parameters:
    /// - `count`: The total number of subtypes in this recursion group.
    /// - `core_type`: The enclosing `CoreType` that owns this group.
    ///
    /// Ordering guarantees:
    /// - Exactly `count` calls to `visit_core_subtype` will occur
    ///   before `exit_core_rec_group` is invoked.
    /// - No other recursion group callbacks will be interleaved.
    ///
    /// Indexing semantics:
    /// - Each subtype reported within this group corresponds to a
    ///   consecutive allocation in the core type index space.
    fn enter_core_rec_group(
        &mut self,
        _cx: &VisitCtx<'a>,
        _count: usize,
        _core_type: &CoreType<'a>,
    ) {
    }

    /// Called for each subtype within the current recursion group.
    ///
    /// This callback is emitted between `enter_core_rec_group` and
    /// `exit_core_rec_group`.
    ///
    /// Parameters:
    /// - `id`: The resolved core type index assigned to this subtype.
    ///   These indices are contiguous within the enclosing recursion group.
    /// - `subtype`: The subtype definition, including finality,
    ///   supertype information, and its composite type.
    ///
    /// Invariants:
    /// - This is only invoked while a recursion group is active.
    /// - The `id` is stable and corresponds to the canonical core
    ///   type namespace for the enclosing module.
    fn visit_core_subtype(&mut self, _cx: &VisitCtx<'a>, _id: u32, _subtype: &SubType) {}

    /// Called after all subtypes in the current recursion group
    /// have been reported.
    ///
    /// Always paired with a prior `enter_core_rec_group`. No additional
    /// `visit_core_subtype` calls will occur after this callback.
    ///
    /// At this point, the full set of types in the group is known and
    /// may be finalized or encoded as a unit.
    fn exit_core_rec_group(&mut self, _cx: &VisitCtx<'a>) {}

    // ============================================================
    // Core Type Definitions
    // ============================================================

    /// Called when entering a core type definition.
    ///
    /// This corresponds to a type allocated in the core type namespace
    /// (e.g., a module type). The `id` is the resolved index within that
    /// namespace.
    ///
    /// This callback forms a structured pair with `exit_core_type`.
    /// Any nested structure associated with this type (such as module
    /// type declarations) will be reported between these two calls.
    ///
    /// Ordering guarantees:
    /// `enter_core_type(id, ...)`
    ///   → zero or more `visit_module_type_decl(...)`
    ///   → `exit_core_type(id, ...)`
    ///
    /// The same `id` is passed to both enter and exit.
    fn enter_core_type(&mut self, _cx: &VisitCtx<'a>, _id: u32, _core_type: &CoreType<'a>) {}

    /// Called for each declaration inside a core module type.
    ///
    /// Emitted only while visiting a core type whose underlying
    /// definition is a module type.
    ///
    /// Parameters:
    /// - `decl_idx`: The declaration’s ordinal position within the
    ///   parent module type.
    /// - `id`: The resolved core type index of the enclosing type.
    /// - `parent`: The enclosing `CoreType`.
    /// - `decl`: The specific module type declaration.
    ///
    /// Ordering guarantees:
    /// - These callbacks occur strictly between `enter_core_type`
    ///   and `exit_core_type` for the same `id`.
    /// - Declarations are visited in source order.
    ///
    /// Indexing semantics:
    /// - `decl_idx` is local to the parent type and does not refer
    ///   to a global index space.
    fn visit_module_type_decl(
        &mut self,
        _cx: &VisitCtx<'a>,
        _decl_idx: usize,
        _id: u32,
        _parent: &CoreType<'a>,
        _decl: &ModuleTypeDeclaration<'a>,
    ) {
    }

    /// Called after all nested declarations for a core type
    /// have been visited.
    ///
    /// Always paired with a prior `enter_core_type` for the same `id`.
    /// No additional callbacks related to this type will occur after
    /// this point.
    ///
    /// Implementations may use this as a finalization hook once the
    /// full structural contents of the type are known.
    fn exit_core_type(&mut self, _cx: &VisitCtx<'a>, _id: u32, _core_type: &CoreType<'a>) {}

    /// Invoked for each core WebAssembly instance.
    ///
    /// The `id` corresponds to the resolved instance index within the
    /// core instance namespace.
    fn visit_core_instance(&mut self, _cx: &VisitCtx<'a>, _id: u32, _inst: &Instance<'a>) {}

    // ------------------------
    // Sections
    // ------------------------

    /// Invoked for each custom section encountered during traversal.
    ///
    /// Custom sections are visited in traversal order and are not
    /// associated with structured enter/exit pairing.
    fn visit_custom_section(&mut self, _cx: &VisitCtx<'a>, _sect: &CustomSection<'a>) {}

    /// Invoked if the component defines a start function.
    ///
    /// This callback is emitted at the point in traversal where the
    /// start section appears.
    fn visit_start_section(&mut self, _cx: &VisitCtx<'a>, _start: &ComponentStartFunction) {}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ItemKind {
    Comp,
    CompFunc,
    CompVal,
    CompType,
    CompInst,
    CoreInst,
    CoreModule,
    CoreType,
    CoreFunc,
    CoreMemory,
    CoreTable,
    CoreGlobal,
    CoreTag,
    NA,
}
impl From<Space> for ItemKind {
    fn from(space: Space) -> Self {
        match space {
            Space::Comp => Self::Comp,
            Space::CompFunc => Self::CompFunc,
            Space::CompVal => Self::CompVal,
            Space::CompType => Self::CompType,
            Space::CompInst => Self::CompInst,
            Space::CoreInst => Self::CoreInst,
            Space::CoreModule => Self::CoreModule,
            Space::CoreType => Self::CoreType,
            Space::CoreFunc => Self::CoreFunc,
            Space::CoreMemory => Self::CoreMemory,
            Space::CoreTable => Self::CoreTable,
            Space::CoreGlobal => Self::CoreGlobal,
            Space::CoreTag => Self::CoreTag,
            Space::NA => Self::NA,
        }
    }
}

/// Context provided during component traversal.
///
/// `VisitCtx` allows resolution of referenced indices (such as type,
/// function, instance, or module indices) relative to the current
/// traversal position.
///
/// The context:
///
/// - Tracks nested component boundaries
/// - Tracks nested index scopes
/// - Correctly resolves `(outer ...)` references
/// - Resolves references across component and core index spaces
///
/// This type is opaque and cannot be constructed by users. It is only
/// available during traversal via [`walk_topological`] or [`walk_structural`].
///
/// All resolution operations are read-only and reflect the *semantic*
/// structure of the component, not its internal storage layout.
pub struct VisitCtx<'a> {
    pub(crate) inner: VisitCtxInner<'a>,
}
impl<'a> VisitCtx<'a> {
    pub(crate) fn new(component: &'a Component<'a>) -> Self {
        Self {
            inner: VisitCtxInner::new(component),
        }
    }
    /// Resolves a single [`IndexedRef`] into a fully resolved semantic item.
    ///
    /// This applies:
    ///
    /// - Depth resolution (`outer` / nested scopes)
    /// - Index space resolution
    /// - Component vs core namespace resolution
    ///
    /// The returned [`ResolvedItem`] represents the semantic target
    /// referenced by the index.
    ///
    /// To pull such references from an IR node, use one of the following traits
    /// (only the applicable traits have been defined per node):
    /// - [`crate::ir::component::refs::ReferencedIndices`]: to pull ALL refs
    /// - [`crate::ir::component::refs::GetCompRefs`]: to pull component refs
    /// - [`crate::ir::component::refs::GetModuleRefs`]: to pull module refs
    /// - [`crate::ir::component::refs::GetTypeRefs`]: to pull type refs
    /// - [`crate::ir::component::refs::GetFuncRefs`]: to pull func refs
    /// - [`crate::ir::component::refs::GetFuncRef`]: if a node only has a single func ref
    /// - [`crate::ir::component::refs::GetMemRefs`]: to pull memory refs
    /// - [`crate::ir::component::refs::GetTableRefs`]: to pull table refs
    /// - [`crate::ir::component::refs::GetItemRefs`]: to pull refs to items
    /// - [`crate::ir::component::refs::GetItemRef`]: if a node only has a single item ref
    /// - [`crate::ir::component::refs::GetParamRefs`]: to pull refs of parameters
    /// - [`crate::ir::component::refs::GetResultRefs`]: to pull refs of results
    /// - [`crate::ir::component::refs::GetArgRefs`]: to pull refs of args
    /// - [`crate::ir::component::refs::GetDescriptorRefs`]: to pull refs of descriptors
    /// - [`crate::ir::component::refs::GetDescribesRefs`]: to pull refs of describes
    pub fn resolve(&self, ref_: &IndexedRef) -> ResolvedItem<'_, '_> {
        self.inner.resolve(ref_)
    }
    /// Resolves a collection of [`RefKind`] values into their semantic targets.
    ///
    /// This is a convenience helper for bulk resolution when a node exposes
    /// multiple referenced indices.
    ///
    /// Read through [`VisitCtx::resolve`] for how to pull such references from IR nodes.
    pub fn resolve_all(&self, refs: &[RefKind]) -> Vec<ResolvedItem<'_, '_>> {
        self.inner.resolve_all(refs)
    }
    /// Looks up the name (if any) of the root component.
    ///
    /// Returns `None` if the component has no name.
    pub fn lookup_root_comp_name(&self) -> Option<&str> {
        self.inner.lookup_root_comp_name()
    }
    /// Looks up the name (if any) of a component by its ID.
    ///
    /// Returns `None` if:
    /// - The component has no name
    /// - The ID is not valid in the current context
    pub fn lookup_comp_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_comp_name(id)
    }
    /// Looks up the name (if any) of a component instance by its ID.
    ///
    /// Returns `None` if:
    /// - The instance has no name
    /// - The ID is not valid in the current context
    pub fn lookup_comp_inst_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_comp_inst_name(id)
    }
    /// Looks up the name (if any) of a component type by its ID.
    ///
    /// Returns `None` if:
    /// - The type has no name
    /// - The ID is not valid in the current context
    pub fn lookup_comp_type_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_comp_type_name(id)
    }
    /// Looks up the name (if any) of a component func by its ID.
    ///
    /// Returns `None` if:
    /// - The func has no name
    /// - The ID is not valid in the current context
    pub fn lookup_comp_func_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_comp_func_name(id)
    }
    /// Looks up the name (if any) of a module by its ID.
    ///
    /// Returns `None` if:
    /// - The module has no name
    /// - The ID is not valid in the current context
    pub fn lookup_module_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_module_name(id)
    }
    /// Looks up the name (if any) of a core instance by its ID.
    ///
    /// Returns `None` if:
    /// - The instance has no name
    /// - The ID is not valid in the current context
    pub fn lookup_core_inst_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_core_inst_name(id)
    }
    /// Looks up the name (if any) of a core type by its ID.
    ///
    /// Returns `None` if:
    /// - The type has no name
    /// - The ID is not valid in the current context
    pub fn lookup_core_type_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_core_type_name(id)
    }
    /// Looks up the name (if any) of a core function by its ID.
    ///
    /// Returns `None` if:
    /// - The function has no name
    /// - The ID is not valid in the current context
    pub fn lookup_core_func_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_core_func_name(id)
    }
    /// Looks up the name (if any) of a global by its ID.
    ///
    /// Returns `None` if:
    /// - The global has no name
    /// - The ID is not valid in the current context
    pub fn lookup_global_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_global_name(id)
    }
    /// Looks up the name (if any) of a memory by its ID.
    ///
    /// Returns `None` if:
    /// - The memory has no name
    /// - The ID is not valid in the current context
    pub fn lookup_memory_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_memory_name(id)
    }
    /// Looks up the name (if any) of a tag by its ID.
    ///
    /// Returns `None` if:
    /// - The tag has no name
    /// - The ID is not valid in the current context
    pub fn lookup_tag_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_tag_name(id)
    }
    /// Looks up the name (if any) of a table by its ID.
    ///
    /// Returns `None` if:
    /// - The table has no name
    /// - The ID is not valid in the current context
    pub fn lookup_table_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_table_name(id)
    }
    /// Looks up the name (if any) of a value by its ID.
    ///
    /// Returns `None` if:
    /// - The value has no name
    /// - The ID is not valid in the current context
    pub fn lookup_value_name(&self, id: u32) -> Option<&str> {
        self.inner.lookup_value_name(id)
    }
}

/// A resolved component item.
///
/// This represents the semantic target of a reference after index
/// resolution has been performed.
///
/// Each variant contains:
///
/// - A `u32` representing the **resolved index of the item within its
///   corresponding namespace**, and
/// - A reference to the underlying IR node.
///
/// The `u32` is *not* a syntactic index from the binary. Instead, it is
/// the canonical, namespace-specific ID assigned during resolution. For
/// example, a component type's `u32` is its resolved index in the
/// component type namespace, and a core instance's `u32` is its resolved
/// index in the core instance namespace.
///
/// This enum allows callers to uniformly handle any reference target
/// without needing to separately track both namespace and ID.
///
/// # Invariant
///
/// The `u32` stored in each variant **must** correspond to the namespace
/// implied by the variant and must match the ID used during visitor
/// traversal. For example, `ResolvedItem::CompType(idx, _)` must always
/// have `idx` equal to the resolved index of that component type in the
/// component type namespace.
pub enum ResolvedItem<'a, 'b> {
    /// A resolved subcomponent.
    Component(u32, &'a Component<'b>),

    /// A resolved core WebAssembly module.
    Module(u32, &'a Module<'b>),

    /// A resolved canonical function.
    Func(u32, &'a CanonicalFunction),

    /// A resolved component-level type.
    CompType(u32, &'a ComponentType<'b>),

    /// A resolved component instance.
    CompInst(u32, &'a ComponentInstance<'b>),

    /// A resolved core WebAssembly instance.
    CoreInst(u32, &'a Instance<'b>),

    /// A resolved core WebAssembly type.
    CoreType(u32, &'a CoreType<'b>),

    /// A resolved component alias.
    Alias(u32, &'a ComponentAlias<'b>),

    /// A resolved component import.
    Import(u32, &'a ComponentImport<'b>),

    /// A resolved component export.
    Export(u32, &'a ComponentExport<'b>),
}