wasmtime_wit_bindgen/
lib.rs

1use crate::rust::{RustGenerator, TypeMode, to_rust_ident, to_rust_upper_camel_case};
2use crate::types::{TypeInfo, Types};
3use anyhow::bail;
4use heck::*;
5use indexmap::{IndexMap, IndexSet};
6use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
7use std::fmt::Write as _;
8use std::io::{Read, Write};
9use std::mem;
10use std::process::{Command, Stdio};
11use wit_parser::*;
12
13macro_rules! uwrite {
14    ($dst:expr, $($arg:tt)*) => {
15        write!($dst, $($arg)*).unwrap()
16    };
17}
18
19macro_rules! uwriteln {
20    ($dst:expr, $($arg:tt)*) => {
21        writeln!($dst, $($arg)*).unwrap()
22    };
23}
24
25mod rust;
26mod source;
27mod types;
28use source::Source;
29
30#[derive(Clone)]
31enum InterfaceName {
32    /// This interface was remapped using `with` to some other Rust code.
33    Remapped {
34        /// This is the `::`-separated string which is the path to the mapped
35        /// item relative to the root of the `bindgen!` macro invocation.
36        ///
37        /// This path currently starts with `__with_name$N` and will then
38        /// optionally have `::` projections through to the actual item
39        /// depending on how `with` was configured.
40        name_at_root: String,
41
42        /// This is currently only used for exports and is the relative path to
43        /// where this mapped name would be located if `with` were not
44        /// specified. Basically it's the same as the `Path` variant of this
45        /// enum if the mapping weren't present.
46        local_path: Vec<String>,
47    },
48
49    /// This interface is generated in the module hierarchy specified.
50    ///
51    /// The path listed here is the path, from the root of the `bindgen!` macro,
52    /// to where this interface is generated.
53    Path(Vec<String>),
54}
55
56#[derive(Default)]
57struct Wasmtime {
58    src: Source,
59    opts: Opts,
60    /// A list of all interfaces which were imported by this world.
61    ///
62    /// The first two values identify the interface; the third is the contents of the
63    /// module that this interface generated. The fourth value is the name of the
64    /// interface as also present in `self.interface_names`.
65    import_interfaces: Vec<(WorldKey, InterfaceId, String, InterfaceName)>,
66    import_functions: Vec<Function>,
67    exports: Exports,
68    types: Types,
69    sizes: SizeAlign,
70    interface_names: HashMap<InterfaceId, InterfaceName>,
71    interface_last_seen_as_import: HashMap<InterfaceId, bool>,
72    trappable_errors: IndexMap<TypeId, String>,
73    // Track the with options that were used. Remapped interfaces provided via `with`
74    // are required to be used.
75    used_with_opts: HashSet<String>,
76    // Track the imports that matched the `trappable_imports` spec.
77    used_trappable_imports_opts: HashSet<String>,
78    world_link_options: LinkOptionsBuilder,
79    interface_link_options: HashMap<InterfaceId, LinkOptionsBuilder>,
80}
81
82#[derive(Default)]
83struct Exports {
84    fields: BTreeMap<String, ExportField>,
85    modules: Vec<(InterfaceId, String, InterfaceName)>,
86    funcs: Vec<String>,
87}
88
89struct ExportField {
90    ty: String,
91    ty_index: String,
92    load: String,
93    get_index: String,
94}
95
96#[derive(Default, Debug, Clone, Copy)]
97pub enum Ownership {
98    /// Generated types will be composed entirely of owning fields, regardless
99    /// of whether they are used as parameters to guest exports or not.
100    #[default]
101    Owning,
102
103    /// Generated types used as parameters to guest exports will be "deeply
104    /// borrowing", i.e. contain references rather than owned values when
105    /// applicable.
106    Borrowing {
107        /// Whether or not to generate "duplicate" type definitions for a single
108        /// WIT type if necessary, for example if it's used as both an import
109        /// and an export, or if it's used both as a parameter to an export and
110        /// a return value from an export.
111        duplicate_if_necessary: bool,
112    },
113}
114
115#[derive(Default, Debug, Clone)]
116pub struct Opts {
117    /// Whether or not `rustfmt` is executed to format generated code.
118    pub rustfmt: bool,
119
120    /// Whether or not to emit `tracing` macro calls on function entry/exit.
121    pub tracing: bool,
122
123    /// Whether or not `tracing` macro calls should included argument and
124    /// return values which contain dynamically-sized `list` values.
125    pub verbose_tracing: bool,
126
127    /// Whether or not to use async rust functions and traits.
128    pub async_: AsyncConfig,
129
130    /// Whether or not to use `func_wrap_concurrent` when generating code for
131    /// async imports.
132    ///
133    /// Unlike `func_wrap_async`, `func_wrap_concurrent` allows host functions
134    /// to suspend without monopolizing the `Store`, meaning other guest tasks
135    /// can make progress concurrently.
136    pub concurrent_imports: bool,
137
138    /// Whether or not to use `call_concurrent` when generating code for
139    /// async exports.
140    ///
141    /// Unlike `call_async`, `call_concurrent` allows the caller to make
142    /// multiple concurrent calls on the same component instance.
143    pub concurrent_exports: bool,
144
145    /// A list of "trappable errors" which are used to replace the `E` in
146    /// `result<T, E>` found in WIT.
147    pub trappable_error_type: Vec<TrappableError>,
148
149    /// Whether to generate owning or borrowing type definitions.
150    pub ownership: Ownership,
151
152    /// Whether or not to generate code for only the interfaces of this wit file or not.
153    pub only_interfaces: bool,
154
155    /// Configuration of which imports are allowed to generate a trap.
156    pub trappable_imports: TrappableImports,
157
158    /// Remapping of interface names to rust module names.
159    /// TODO: is there a better type to use for the value of this map?
160    pub with: HashMap<String, String>,
161
162    /// Additional derive attributes to add to generated types. If using in a CLI, this flag can be
163    /// specified multiple times to add multiple attributes.
164    ///
165    /// These derive attributes will be added to any generated structs or enums
166    pub additional_derive_attributes: Vec<String>,
167
168    /// Evaluate to a string literal containing the generated code rather than the generated tokens
169    /// themselves. Mostly useful for Wasmtime internal debugging and development.
170    pub stringify: bool,
171
172    /// Temporary option to skip `impl<T: Trait> Trait for &mut T` for the
173    /// `wasmtime-wasi` crate while that's given a chance to update its b
174    /// indings.
175    pub skip_mut_forwarding_impls: bool,
176
177    /// Indicates that the `T` in `Store<T>` should be send even if async is not
178    /// enabled.
179    ///
180    /// This is helpful when sync bindings depend on generated functions from
181    /// async bindings as is the case with WASI in-tree.
182    pub require_store_data_send: bool,
183
184    /// Path to the `wasmtime` crate if it's not the default path.
185    pub wasmtime_crate: Option<String>,
186
187    /// If true, write the generated bindings to a file for better error
188    /// messages from `rustc`.
189    ///
190    /// This can also be toggled via the `WASMTIME_DEBUG_BINDGEN` environment
191    /// variable, but that will affect _all_ `bindgen!` macro invocations (and
192    /// can sometimes lead to one invocation ovewriting another in unpredictable
193    /// ways), whereas this option lets you specify it on a case-by-case basis.
194    pub debug: bool,
195}
196
197#[derive(Debug, Clone)]
198pub struct TrappableError {
199    /// Full path to the error, such as `wasi:io/streams/error`.
200    pub wit_path: String,
201
202    /// The name, in Rust, of the error type to generate.
203    pub rust_type_name: String,
204}
205
206/// Which imports should be generated as async functions.
207///
208/// The imports should be declared in the following format:
209/// - Regular functions: `"{function-name}"`
210/// - Resource methods: `"[method]{resource-name}.{method-name}"`
211/// - Resource destructors: `"[drop]{resource-name}"`
212///
213/// Examples:
214/// - Regular function: `"get-environment"`
215/// - Resource method: `"[method]input-stream.read"`
216/// - Resource destructor: `"[drop]input-stream"`
217#[derive(Default, Debug, Clone)]
218pub enum AsyncConfig {
219    /// No functions are `async`.
220    #[default]
221    None,
222    /// All generated functions should be `async`.
223    All,
224    /// These imported functions should not be async, but everything else is.
225    AllExceptImports(HashSet<String>),
226    /// These functions are the only imports that are async, all other imports
227    /// are sync.
228    ///
229    /// Note that all exports are still async in this situation.
230    OnlyImports(HashSet<String>),
231}
232
233#[derive(PartialEq, Debug, Copy, Clone)]
234pub enum CallStyle {
235    Sync,
236    Async,
237    Concurrent,
238}
239
240#[derive(Default, Debug, Clone)]
241pub enum TrappableImports {
242    /// No imports are allowed to trap.
243    #[default]
244    None,
245    /// All imports may trap.
246    All,
247    /// Only the specified set of functions may trap.
248    Only(HashSet<String>),
249}
250
251impl TrappableImports {
252    fn can_trap(&self, f: &Function) -> bool {
253        match self {
254            TrappableImports::None => false,
255            TrappableImports::All => true,
256            TrappableImports::Only(set) => set.contains(&f.name),
257        }
258    }
259}
260
261impl Opts {
262    pub fn generate(&self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> {
263        // TODO: Should we refine this test to inspect only types reachable from
264        // the specified world?
265        if !cfg!(feature = "component-model-async")
266            && resolve
267                .types
268                .iter()
269                .any(|(_, ty)| matches!(ty.kind, TypeDefKind::Future(_) | TypeDefKind::Stream(_)))
270        {
271            anyhow::bail!(
272                "must enable `component-model-async` feature when using WIT files \
273                 containing future, stream, or error-context types"
274            );
275        }
276
277        let mut r = Wasmtime::default();
278        r.sizes.fill(resolve);
279        r.opts = self.clone();
280        r.populate_world_and_interface_options(resolve, world);
281        r.generate(resolve, world)
282    }
283
284    fn is_store_data_send(&self) -> bool {
285        matches!(self.call_style(), CallStyle::Async | CallStyle::Concurrent)
286            || self.require_store_data_send
287    }
288
289    pub fn import_call_style(&self, qualifier: Option<&str>, f: &str) -> CallStyle {
290        let matched = |names: &HashSet<String>| {
291            names.contains(f)
292                || qualifier
293                    .map(|v| names.contains(&format!("{v}#{f}")))
294                    .unwrap_or(false)
295        };
296
297        match &self.async_ {
298            AsyncConfig::AllExceptImports(names) if matched(names) => CallStyle::Sync,
299            AsyncConfig::OnlyImports(names) if !matched(names) => CallStyle::Sync,
300            _ => self.call_style(),
301        }
302    }
303
304    pub fn drop_call_style(&self, qualifier: Option<&str>, r: &str) -> CallStyle {
305        self.import_call_style(qualifier, &format!("[drop]{r}"))
306    }
307
308    pub fn call_style(&self) -> CallStyle {
309        match &self.async_ {
310            AsyncConfig::None => CallStyle::Sync,
311
312            AsyncConfig::All | AsyncConfig::AllExceptImports(_) | AsyncConfig::OnlyImports(_) => {
313                if self.concurrent_imports {
314                    CallStyle::Concurrent
315                } else {
316                    CallStyle::Async
317                }
318            }
319        }
320    }
321}
322
323impl Wasmtime {
324    fn populate_world_and_interface_options(&mut self, resolve: &Resolve, world: WorldId) {
325        self.world_link_options.add_world(resolve, &world);
326
327        for (_, import) in resolve.worlds[world].imports.iter() {
328            match import {
329                WorldItem::Interface { id, .. } => {
330                    let mut o = LinkOptionsBuilder::default();
331                    o.add_interface(resolve, id);
332                    self.interface_link_options.insert(*id, o);
333                }
334                WorldItem::Function(_) | WorldItem::Type(_) => {}
335            }
336        }
337    }
338    fn name_interface(
339        &mut self,
340        resolve: &Resolve,
341        id: InterfaceId,
342        name: &WorldKey,
343        is_export: bool,
344    ) -> bool {
345        let mut path = Vec::new();
346        if is_export {
347            path.push("exports".to_string());
348        }
349        match name {
350            WorldKey::Name(name) => {
351                path.push(name.to_snake_case());
352            }
353            WorldKey::Interface(_) => {
354                let iface = &resolve.interfaces[id];
355                let pkgname = &resolve.packages[iface.package.unwrap()].name;
356                path.push(pkgname.namespace.to_snake_case());
357                path.push(self.name_package_module(resolve, iface.package.unwrap()));
358                path.push(to_rust_ident(iface.name.as_ref().unwrap()));
359            }
360        }
361        let entry = if let Some(name_at_root) = self.lookup_replacement(resolve, name, None) {
362            InterfaceName::Remapped {
363                name_at_root,
364                local_path: path,
365            }
366        } else {
367            InterfaceName::Path(path)
368        };
369
370        let remapped = matches!(entry, InterfaceName::Remapped { .. });
371        self.interface_names.insert(id, entry);
372        remapped
373    }
374
375    /// If the package `id` is the only package with its namespace/name combo
376    /// then pass through the name unmodified. If, however, there are multiple
377    /// versions of this package then the package module is going to get version
378    /// information.
379    fn name_package_module(&self, resolve: &Resolve, id: PackageId) -> String {
380        let pkg = &resolve.packages[id];
381        let versions_with_same_name = resolve
382            .packages
383            .iter()
384            .filter_map(|(_, p)| {
385                if p.name.namespace == pkg.name.namespace && p.name.name == pkg.name.name {
386                    Some(&p.name.version)
387                } else {
388                    None
389                }
390            })
391            .collect::<Vec<_>>();
392        let base = pkg.name.name.to_snake_case();
393        if versions_with_same_name.len() == 1 {
394            return base;
395        }
396
397        let version = match &pkg.name.version {
398            Some(version) => version,
399            // If this package didn't have a version then don't mangle its name
400            // and other packages with the same name but with versions present
401            // will have their names mangled.
402            None => return base,
403        };
404
405        // Here there's multiple packages with the same name that differ only in
406        // version, so the version needs to be mangled into the Rust module name
407        // that we're generating. This in theory could look at all of
408        // `versions_with_same_name` and produce a minimal diff, e.g. for 0.1.0
409        // and 0.2.0 this could generate "foo1" and "foo2", but for now
410        // a simpler path is chosen to generate "foo0_1_0" and "foo0_2_0".
411        let version = version
412            .to_string()
413            .replace('.', "_")
414            .replace('-', "_")
415            .replace('+', "_")
416            .to_snake_case();
417        format!("{base}{version}")
418    }
419
420    fn generate(&mut self, resolve: &Resolve, id: WorldId) -> anyhow::Result<String> {
421        self.types.analyze(resolve, id);
422
423        self.world_link_options.write_struct(&mut self.src);
424
425        // Resolve the `trappable_error_type` configuration values to `TypeId`
426        // values. This is done by iterating over each `trappable_error_type`
427        // and then locating the interface that it corresponds to as well as the
428        // type within that interface.
429        //
430        // Note that `LookupItem::InterfaceNoPop` is used here as the full
431        // hierarchical behavior of `lookup_keys` isn't used as the interface
432        // must be named here.
433        'outer: for (i, te) in self.opts.trappable_error_type.iter().enumerate() {
434            let error_name = format!("_TrappableError{i}");
435            for (id, iface) in resolve.interfaces.iter() {
436                for (key, projection) in lookup_keys(
437                    resolve,
438                    &WorldKey::Interface(id),
439                    LookupItem::InterfaceNoPop,
440                ) {
441                    assert!(projection.is_empty());
442
443                    // If `wit_path` looks like `{key}/{type_name}` where
444                    // `type_name` is a type within `iface` then we've found a
445                    // match. Otherwise continue to the next lookup key if there
446                    // is one, and failing that continue to the next interface.
447                    let suffix = match te.wit_path.strip_prefix(&key) {
448                        Some(s) => s,
449                        None => continue,
450                    };
451                    let suffix = match suffix.strip_prefix('/') {
452                        Some(s) => s,
453                        None => continue,
454                    };
455                    if let Some(id) = iface.types.get(suffix) {
456                        uwriteln!(self.src, "type {error_name} = {};", te.rust_type_name);
457                        let prev = self.trappable_errors.insert(*id, error_name);
458                        assert!(prev.is_none());
459                        continue 'outer;
460                    }
461                }
462            }
463
464            bail!(
465                "failed to locate a WIT error type corresponding to the \
466                 `trappable_error_type` name `{}` provided",
467                te.wit_path
468            )
469        }
470
471        // Convert all entries in `with` as relative to the root of where the
472        // macro itself is invoked. This emits a `pub use` to bring the name
473        // into scope under an "anonymous name" which then replaces the `with`
474        // map entry.
475        let mut with = self.opts.with.iter_mut().collect::<Vec<_>>();
476        with.sort();
477        for (i, (_k, v)) in with.into_iter().enumerate() {
478            let name = format!("__with_name{i}");
479            uwriteln!(self.src, "#[doc(hidden)]\npub use {v} as {name};");
480            *v = name;
481        }
482
483        let world = &resolve.worlds[id];
484        for (name, import) in world.imports.iter() {
485            if !self.opts.only_interfaces || matches!(import, WorldItem::Interface { .. }) {
486                self.import(resolve, name, import);
487            }
488        }
489
490        for (name, export) in world.exports.iter() {
491            if !self.opts.only_interfaces || matches!(export, WorldItem::Interface { .. }) {
492                self.export(resolve, name, export);
493            }
494        }
495        self.finish(resolve, id)
496    }
497
498    fn import(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) {
499        let mut generator = InterfaceGenerator::new(self, resolve);
500        match item {
501            WorldItem::Function(func) => {
502                self.import_functions.push(func.clone());
503            }
504            WorldItem::Interface { id, .. } => {
505                generator
506                    .generator
507                    .interface_last_seen_as_import
508                    .insert(*id, true);
509                generator.current_interface = Some((*id, name, false));
510                let snake = to_rust_ident(&match name {
511                    WorldKey::Name(s) => s.to_snake_case(),
512                    WorldKey::Interface(id) => resolve.interfaces[*id]
513                        .name
514                        .as_ref()
515                        .unwrap()
516                        .to_snake_case(),
517                });
518                let module = if generator
519                    .generator
520                    .name_interface(resolve, *id, name, false)
521                {
522                    // If this interface is remapped then that means that it was
523                    // provided via the `with` key in the bindgen configuration.
524                    // That means that bindings generation is skipped here. To
525                    // accommodate future bindgens depending on this bindgen
526                    // though we still generate a module which reexports the
527                    // original module. This helps maintain the same output
528                    // structure regardless of whether `with` is used.
529                    let name_at_root = match &generator.generator.interface_names[id] {
530                        InterfaceName::Remapped { name_at_root, .. } => name_at_root,
531                        InterfaceName::Path(_) => unreachable!(),
532                    };
533                    let path_to_root = generator.path_to_root();
534                    format!(
535                        "
536                            pub mod {snake} {{
537                                #[allow(unused_imports)]
538                                pub use {path_to_root}{name_at_root}::*;
539                            }}
540                        "
541                    )
542                } else {
543                    // If this interface is not remapped then it's time to
544                    // actually generate bindings here.
545                    generator.generator.interface_link_options[id].write_struct(&mut generator.src);
546                    generator.types(*id);
547                    let key_name = resolve.name_world_key(name);
548                    generator.generate_add_to_linker(*id, &key_name);
549
550                    let module = &generator.src[..];
551                    let wt = generator.generator.wasmtime_path();
552
553                    format!(
554                        "
555                            #[allow(clippy::all)]
556                            pub mod {snake} {{
557                                #[allow(unused_imports)]
558                                use {wt}::component::__internal::{{anyhow, Box}};
559
560                                {module}
561                            }}
562                        "
563                    )
564                };
565                self.import_interfaces.push((
566                    name.clone(),
567                    *id,
568                    module,
569                    self.interface_names[id].clone(),
570                ));
571
572                let interface_path = self.import_interface_path(id);
573                self.interface_link_options[id]
574                    .write_impl_from_world(&mut self.src, &interface_path);
575            }
576            WorldItem::Type(ty) => {
577                let name = match name {
578                    WorldKey::Name(name) => name,
579                    WorldKey::Interface(_) => unreachable!(),
580                };
581                generator.define_type(name, *ty);
582                let body = mem::take(&mut generator.src);
583                self.src.push_str(&body);
584            }
585        };
586    }
587
588    fn export(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) {
589        let wt = self.wasmtime_path();
590        let mut generator = InterfaceGenerator::new(self, resolve);
591        let field;
592        let ty;
593        let ty_index;
594        let load;
595        let get_index;
596        match item {
597            WorldItem::Function(func) => {
598                generator.define_rust_guest_export(resolve, None, func);
599                let body = mem::take(&mut generator.src).into();
600                load = generator.extract_typed_function(func).1;
601                assert!(generator.src.is_empty());
602                generator.generator.exports.funcs.push(body);
603                ty_index = format!("{wt}::component::ComponentExportIndex");
604                field = func_field_name(resolve, func);
605                ty = format!("{wt}::component::Func");
606                let sig = generator.typedfunc_sig(func, TypeMode::AllBorrowed("'_"));
607                let typecheck = format!(
608                    "match item {{
609                            {wt}::component::types::ComponentItem::ComponentFunc(func) => {{
610                                anyhow::Context::context(
611                                    func.typecheck::<{sig}>(&_instance_type),
612                                    \"type-checking export func `{0}`\"
613                                )?;
614                                index
615                            }}
616                            _ => Err(anyhow::anyhow!(\"export `{0}` is not a function\"))?,
617                        }}",
618                    func.name
619                );
620                get_index = format!(
621                    "{{ let (item, index) = _component.get_export(None, \"{}\")
622                        .ok_or_else(|| anyhow::anyhow!(\"no export `{0}` found\"))?;
623                        {typecheck}
624                     }}",
625                    func.name
626                );
627            }
628            WorldItem::Type(_) => unreachable!(),
629            WorldItem::Interface { id, .. } => {
630                generator
631                    .generator
632                    .interface_last_seen_as_import
633                    .insert(*id, false);
634                generator.generator.name_interface(resolve, *id, name, true);
635                generator.current_interface = Some((*id, name, true));
636                generator.types(*id);
637                let struct_name = "Guest";
638                let iface = &resolve.interfaces[*id];
639                let iface_name = match name {
640                    WorldKey::Name(name) => name,
641                    WorldKey::Interface(_) => iface.name.as_ref().unwrap(),
642                };
643                uwriteln!(generator.src, "pub struct {struct_name} {{");
644                for (_, func) in iface.functions.iter() {
645                    uwriteln!(
646                        generator.src,
647                        "{}: {wt}::component::Func,",
648                        func_field_name(resolve, func)
649                    );
650                }
651                uwriteln!(generator.src, "}}");
652
653                uwriteln!(generator.src, "#[derive(Clone)]");
654                uwriteln!(generator.src, "pub struct {struct_name}Indices {{");
655                for (_, func) in iface.functions.iter() {
656                    uwriteln!(
657                        generator.src,
658                        "{}: {wt}::component::ComponentExportIndex,",
659                        func_field_name(resolve, func)
660                    );
661                }
662                uwriteln!(generator.src, "}}");
663
664                uwriteln!(generator.src, "impl {struct_name}Indices {{");
665                let instance_name = resolve.name_world_key(name);
666                uwrite!(
667                    generator.src,
668                    "
669/// Constructor for [`{struct_name}Indices`] which takes a
670/// [`Component`]({wt}::component::Component) as input and can be executed
671/// before instantiation.
672///
673/// This constructor can be used to front-load string lookups to find exports
674/// within a component.
675pub fn new<_T>(
676    _instance_pre: &{wt}::component::InstancePre<_T>,
677) -> {wt}::Result<{struct_name}Indices> {{
678    let instance = _instance_pre.component().get_export_index(None, \"{instance_name}\")
679        .ok_or_else(|| anyhow::anyhow!(\"no exported instance named `{instance_name}`\"))?;
680    let mut lookup = move |name| {{
681        _instance_pre.component().get_export_index(Some(&instance), name).ok_or_else(|| {{
682            anyhow::anyhow!(
683                \"instance export `{instance_name}` does \\
684                  not have export `{{name}}`\"
685            )
686        }})
687    }};
688    let _ = &mut lookup;
689                    "
690                );
691                let mut fields = Vec::new();
692                for (_, func) in iface.functions.iter() {
693                    let name = func_field_name(resolve, func);
694                    uwriteln!(generator.src, "let {name} = lookup(\"{}\")?;", func.name);
695                    fields.push(name);
696                }
697                uwriteln!(generator.src, "Ok({struct_name}Indices {{");
698                for name in fields {
699                    uwriteln!(generator.src, "{name},");
700                }
701                uwriteln!(generator.src, "}})");
702                uwriteln!(generator.src, "}}"); // end `fn _new`
703
704                uwrite!(
705                    generator.src,
706                    "
707                        pub fn load(
708                            &self,
709                            mut store: impl {wt}::AsContextMut,
710                            instance: &{wt}::component::Instance,
711                        ) -> {wt}::Result<{struct_name}> {{
712                            let _instance = instance;
713                            let _instance_pre = _instance.instance_pre(&store);
714                            let _instance_type = _instance_pre.instance_type();
715                            let mut store = store.as_context_mut();
716                            let _ = &mut store;
717                    "
718                );
719                let mut fields = Vec::new();
720                for (_, func) in iface.functions.iter() {
721                    let (name, getter) = generator.extract_typed_function(func);
722                    uwriteln!(generator.src, "let {name} = {getter};");
723                    fields.push(name);
724                }
725                uwriteln!(generator.src, "Ok({struct_name} {{");
726                for name in fields {
727                    uwriteln!(generator.src, "{name},");
728                }
729                uwriteln!(generator.src, "}})");
730                uwriteln!(generator.src, "}}"); // end `fn new`
731                uwriteln!(generator.src, "}}"); // end `impl {struct_name}Indices`
732
733                uwriteln!(generator.src, "impl {struct_name} {{");
734                let mut resource_methods = IndexMap::new();
735
736                for (_, func) in iface.functions.iter() {
737                    match func.kind.resource() {
738                        None => {
739                            generator.define_rust_guest_export(resolve, Some(name), func);
740                        }
741                        Some(id) => {
742                            resource_methods.entry(id).or_insert(Vec::new()).push(func);
743                        }
744                    }
745                }
746
747                for (id, _) in resource_methods.iter() {
748                    let name = resolve.types[*id].name.as_ref().unwrap();
749                    let snake = name.to_snake_case();
750                    let camel = name.to_upper_camel_case();
751                    uwriteln!(
752                        generator.src,
753                        "pub fn {snake}(&self) -> Guest{camel}<'_> {{
754                            Guest{camel} {{ funcs: self }}
755                        }}"
756                    );
757                }
758
759                uwriteln!(generator.src, "}}");
760
761                for (id, methods) in resource_methods {
762                    let resource_name = resolve.types[id].name.as_ref().unwrap();
763                    let camel = resource_name.to_upper_camel_case();
764                    uwriteln!(generator.src, "impl Guest{camel}<'_> {{");
765                    for method in methods {
766                        generator.define_rust_guest_export(resolve, Some(name), method);
767                    }
768                    uwriteln!(generator.src, "}}");
769                }
770
771                let module = &generator.src[..];
772                let snake = to_rust_ident(iface_name);
773
774                let module = format!(
775                    "
776                        #[allow(clippy::all)]
777                        pub mod {snake} {{
778                            #[allow(unused_imports)]
779                            use {wt}::component::__internal::{{anyhow, Box}};
780
781                            {module}
782                        }}
783                    "
784                );
785                let pkgname = match name {
786                    WorldKey::Name(_) => None,
787                    WorldKey::Interface(_) => {
788                        Some(resolve.packages[iface.package.unwrap()].name.clone())
789                    }
790                };
791                self.exports
792                    .modules
793                    .push((*id, module, self.interface_names[id].clone()));
794
795                let (path, method_name) = match pkgname {
796                    Some(pkgname) => (
797                        format!(
798                            "exports::{}::{}::{snake}::{struct_name}",
799                            pkgname.namespace.to_snake_case(),
800                            self.name_package_module(resolve, iface.package.unwrap()),
801                        ),
802                        format!(
803                            "{}_{}_{snake}",
804                            pkgname.namespace.to_snake_case(),
805                            self.name_package_module(resolve, iface.package.unwrap())
806                        ),
807                    ),
808                    None => (format!("exports::{snake}::{struct_name}"), snake.clone()),
809                };
810                field = format!("interface{}", self.exports.fields.len());
811                load = format!("self.{field}.load(&mut store, &_instance)?");
812                self.exports.funcs.push(format!(
813                    "
814                        pub fn {method_name}(&self) -> &{path} {{
815                            &self.{field}
816                        }}
817                    ",
818                ));
819                ty_index = format!("{path}Indices");
820                ty = path;
821                get_index = format!("{ty_index}::new(_instance_pre)?");
822            }
823        }
824        let prev = self.exports.fields.insert(
825            field,
826            ExportField {
827                ty,
828                ty_index,
829                load,
830                get_index,
831            },
832        );
833        assert!(prev.is_none());
834    }
835
836    fn build_world_struct(&mut self, resolve: &Resolve, world: WorldId) {
837        let wt = self.wasmtime_path();
838        let world_name = &resolve.worlds[world].name;
839        let camel = to_rust_upper_camel_case(&world_name);
840        let (async_, async__, where_clause, await_) = match self.opts.call_style() {
841            CallStyle::Async | CallStyle::Concurrent => {
842                ("async", "_async", "where _T: Send", ".await")
843            }
844            CallStyle::Sync => ("", "", "", ""),
845        };
846        uwriteln!(
847            self.src,
848            "
849/// Auto-generated bindings for a pre-instantiated version of a
850/// component which implements the world `{world_name}`.
851///
852/// This structure is created through [`{camel}Pre::new`] which
853/// takes a [`InstancePre`]({wt}::component::InstancePre) that
854/// has been created through a [`Linker`]({wt}::component::Linker).
855///
856/// For more information see [`{camel}`] as well.
857pub struct {camel}Pre<T: 'static> {{
858    instance_pre: {wt}::component::InstancePre<T>,
859    indices: {camel}Indices,
860}}
861
862impl<T: 'static> Clone for {camel}Pre<T> {{
863    fn clone(&self) -> Self {{
864        Self {{
865            instance_pre: self.instance_pre.clone(),
866            indices: self.indices.clone(),
867        }}
868    }}
869}}
870
871impl<_T: 'static> {camel}Pre<_T> {{
872    /// Creates a new copy of `{camel}Pre` bindings which can then
873    /// be used to instantiate into a particular store.
874    ///
875    /// This method may fail if the component behind `instance_pre`
876    /// does not have the required exports.
877    pub fn new(instance_pre: {wt}::component::InstancePre<_T>) -> {wt}::Result<Self> {{
878        let indices = {camel}Indices::new(&instance_pre)?;
879        Ok(Self {{ instance_pre, indices }})
880    }}
881
882    pub fn engine(&self) -> &{wt}::Engine {{
883        self.instance_pre.engine()
884    }}
885
886    pub fn instance_pre(&self) -> &{wt}::component::InstancePre<_T> {{
887        &self.instance_pre
888    }}
889
890    /// Instantiates a new instance of [`{camel}`] within the
891    /// `store` provided.
892    ///
893    /// This function will use `self` as the pre-instantiated
894    /// instance to perform instantiation. Afterwards the preloaded
895    /// indices in `self` are used to lookup all exports on the
896    /// resulting instance.
897    pub {async_} fn instantiate{async__}(
898        &self,
899        mut store: impl {wt}::AsContextMut<Data = _T>,
900    ) -> {wt}::Result<{camel}>
901        {where_clause}
902    {{
903        let mut store = store.as_context_mut();
904        let instance = self.instance_pre.instantiate{async__}(&mut store){await_}?;
905        self.indices.load(&mut store, &instance)
906    }}
907}}
908"
909        );
910
911        uwriteln!(
912            self.src,
913            "
914            /// Auto-generated bindings for index of the exports of
915            /// `{world_name}`.
916            ///
917            /// This is an implementation detail of [`{camel}Pre`] and can
918            /// be constructed if needed as well.
919            ///
920            /// For more information see [`{camel}`] as well.
921            #[derive(Clone)]
922            pub struct {camel}Indices {{"
923        );
924        for (name, field) in self.exports.fields.iter() {
925            uwriteln!(self.src, "{name}: {},", field.ty_index);
926        }
927        self.src.push_str("}\n");
928
929        uwriteln!(
930            self.src,
931            "
932                /// Auto-generated bindings for an instance a component which
933                /// implements the world `{world_name}`.
934                ///
935                /// This structure can be created through a number of means
936                /// depending on your requirements and what you have on hand:
937                ///
938                /// * The most convenient way is to use
939                ///   [`{camel}::instantiate{async__}`] which only needs a
940                ///   [`Store`], [`Component`], and [`Linker`].
941                ///
942                /// * Alternatively you can create a [`{camel}Pre`] ahead of
943                ///   time with a [`Component`] to front-load string lookups
944                ///   of exports once instead of per-instantiation. This
945                ///   method then uses [`{camel}Pre::instantiate{async__}`] to
946                ///   create a [`{camel}`].
947                ///
948                /// * If you've instantiated the instance yourself already
949                ///   then you can use [`{camel}::new`].
950                ///
951                /// These methods are all equivalent to one another and move
952                /// around the tradeoff of what work is performed when.
953                ///
954                /// [`Store`]: {wt}::Store
955                /// [`Component`]: {wt}::component::Component
956                /// [`Linker`]: {wt}::component::Linker
957                pub struct {camel} {{"
958        );
959        for (name, field) in self.exports.fields.iter() {
960            uwriteln!(self.src, "{name}: {},", field.ty);
961        }
962        self.src.push_str("}\n");
963
964        let world_trait = self.world_imports_trait(resolve, world);
965
966        uwriteln!(self.src, "const _: () = {{");
967        uwriteln!(
968            self.src,
969            "
970                #[allow(unused_imports)]
971                use {wt}::component::__internal::anyhow;
972            "
973        );
974
975        uwriteln!(
976            self.src,
977            "impl {camel}Indices {{
978                /// Creates a new copy of `{camel}Indices` bindings which can then
979                /// be used to instantiate into a particular store.
980                ///
981                /// This method may fail if the component does not have the
982                /// required exports.
983                pub fn new<_T>(_instance_pre: &{wt}::component::InstancePre<_T>) -> {wt}::Result<Self> {{
984                    let _component = _instance_pre.component();
985                    let _instance_type = _instance_pre.instance_type();
986            ",
987        );
988        for (name, field) in self.exports.fields.iter() {
989            uwriteln!(self.src, "let {name} = {};", field.get_index);
990        }
991        uwriteln!(self.src, "Ok({camel}Indices {{");
992        for (name, _) in self.exports.fields.iter() {
993            uwriteln!(self.src, "{name},");
994        }
995        uwriteln!(self.src, "}})");
996        uwriteln!(self.src, "}}"); // close `fn new`
997
998        uwriteln!(
999            self.src,
1000            "
1001                /// Uses the indices stored in `self` to load an instance
1002                /// of [`{camel}`] from the instance provided.
1003                ///
1004                /// Note that at this time this method will additionally
1005                /// perform type-checks of all exports.
1006                pub fn load(
1007                    &self,
1008                    mut store: impl {wt}::AsContextMut,
1009                    instance: &{wt}::component::Instance,
1010                ) -> {wt}::Result<{camel}> {{
1011                    let _ = &mut store;
1012                    let _instance = instance;
1013            ",
1014        );
1015        for (name, field) in self.exports.fields.iter() {
1016            uwriteln!(self.src, "let {name} = {};", field.load);
1017        }
1018        uwriteln!(self.src, "Ok({camel} {{");
1019        for (name, _) in self.exports.fields.iter() {
1020            uwriteln!(self.src, "{name},");
1021        }
1022        uwriteln!(self.src, "}})");
1023        uwriteln!(self.src, "}}"); // close `fn load`
1024        uwriteln!(self.src, "}}"); // close `impl {camel}Indices`
1025
1026        uwriteln!(
1027            self.src,
1028            "impl {camel} {{
1029                /// Convenience wrapper around [`{camel}Pre::new`] and
1030                /// [`{camel}Pre::instantiate{async__}`].
1031                pub {async_} fn instantiate{async__}<_T>(
1032                    store: impl {wt}::AsContextMut<Data = _T>,
1033                    component: &{wt}::component::Component,
1034                    linker: &{wt}::component::Linker<_T>,
1035                ) -> {wt}::Result<{camel}>
1036                    {where_clause}
1037                {{
1038                    let pre = linker.instantiate_pre(component)?;
1039                    {camel}Pre::new(pre)?.instantiate{async__}(store){await_}
1040                }}
1041
1042                /// Convenience wrapper around [`{camel}Indices::new`] and
1043                /// [`{camel}Indices::load`].
1044                pub fn new(
1045                    mut store: impl {wt}::AsContextMut,
1046                    instance: &{wt}::component::Instance,
1047                ) -> {wt}::Result<{camel}> {{
1048                    let indices = {camel}Indices::new(&instance.instance_pre(&store))?;
1049                    indices.load(&mut store, instance)
1050                }}
1051            ",
1052        );
1053        self.world_add_to_linker(resolve, world, world_trait.as_ref());
1054
1055        for func in self.exports.funcs.iter() {
1056            self.src.push_str(func);
1057        }
1058
1059        uwriteln!(self.src, "}}"); // close `impl {camel}`
1060
1061        uwriteln!(self.src, "}};"); // close `const _: () = ...
1062    }
1063
1064    fn finish(&mut self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> {
1065        let remapping_keys = self.opts.with.keys().cloned().collect::<HashSet<String>>();
1066
1067        let mut unused_keys = remapping_keys
1068            .difference(&self.used_with_opts)
1069            .map(|s| s.as_str())
1070            .collect::<Vec<&str>>();
1071
1072        unused_keys.sort();
1073
1074        if !unused_keys.is_empty() {
1075            anyhow::bail!(
1076                "interfaces were specified in the `with` config option but are not referenced in the target world: {unused_keys:?}"
1077            );
1078        }
1079
1080        if !self.opts.only_interfaces {
1081            self.build_world_struct(resolve, world)
1082        }
1083
1084        if let TrappableImports::Only(only) = &self.opts.trappable_imports {
1085            let mut unused_imports = Vec::from_iter(
1086                only.difference(&self.used_trappable_imports_opts)
1087                    .map(|s| s.as_str()),
1088            );
1089
1090            if !unused_imports.is_empty() {
1091                unused_imports.sort();
1092                anyhow::bail!(
1093                    "names specified in the `trappable_imports` config option but are not referenced in the target world: {unused_imports:?}"
1094                );
1095            }
1096        }
1097
1098        let imports = mem::take(&mut self.import_interfaces);
1099        self.emit_modules(
1100            imports
1101                .into_iter()
1102                .map(|(_, id, module, path)| (id, module, path))
1103                .collect(),
1104        );
1105
1106        let exports = mem::take(&mut self.exports.modules);
1107        self.emit_modules(exports);
1108
1109        let mut src = mem::take(&mut self.src);
1110        if self.opts.rustfmt {
1111            let mut child = Command::new("rustfmt")
1112                .arg("--edition=2018")
1113                .stdin(Stdio::piped())
1114                .stdout(Stdio::piped())
1115                .spawn()
1116                .expect("failed to spawn `rustfmt`");
1117            child
1118                .stdin
1119                .take()
1120                .unwrap()
1121                .write_all(src.as_bytes())
1122                .unwrap();
1123            src.as_mut_string().truncate(0);
1124            child
1125                .stdout
1126                .take()
1127                .unwrap()
1128                .read_to_string(src.as_mut_string())
1129                .unwrap();
1130            let status = child.wait().unwrap();
1131            assert!(status.success());
1132        }
1133
1134        Ok(src.into())
1135    }
1136
1137    fn emit_modules(&mut self, modules: Vec<(InterfaceId, String, InterfaceName)>) {
1138        #[derive(Default)]
1139        struct Module {
1140            submodules: BTreeMap<String, Module>,
1141            contents: Vec<String>,
1142        }
1143        let mut map = Module::default();
1144        for (_, module, name) in modules {
1145            let path = match name {
1146                InterfaceName::Remapped { local_path, .. } => local_path,
1147                InterfaceName::Path(path) => path,
1148            };
1149            let mut cur = &mut map;
1150            for name in path[..path.len() - 1].iter() {
1151                cur = cur
1152                    .submodules
1153                    .entry(name.clone())
1154                    .or_insert(Module::default());
1155            }
1156            cur.contents.push(module);
1157        }
1158
1159        emit(&mut self.src, map);
1160
1161        fn emit(me: &mut Source, module: Module) {
1162            for (name, submodule) in module.submodules {
1163                uwriteln!(me, "pub mod {name} {{");
1164                emit(me, submodule);
1165                uwriteln!(me, "}}");
1166            }
1167            for submodule in module.contents {
1168                uwriteln!(me, "{submodule}");
1169            }
1170        }
1171    }
1172
1173    /// Attempts to find the `key`, possibly with the resource projection
1174    /// `item`, within the `with` map provided to bindings configuration.
1175    fn lookup_replacement(
1176        &mut self,
1177        resolve: &Resolve,
1178        key: &WorldKey,
1179        item: Option<&str>,
1180    ) -> Option<String> {
1181        let item = match item {
1182            Some(item) => LookupItem::Name(item),
1183            None => LookupItem::None,
1184        };
1185
1186        for (lookup, mut projection) in lookup_keys(resolve, key, item) {
1187            if let Some(renamed) = self.opts.with.get(&lookup) {
1188                projection.push(renamed.clone());
1189                projection.reverse();
1190                self.used_with_opts.insert(lookup);
1191                return Some(projection.join("::"));
1192            }
1193        }
1194
1195        None
1196    }
1197
1198    fn wasmtime_path(&self) -> String {
1199        self.opts
1200            .wasmtime_crate
1201            .clone()
1202            .unwrap_or("wasmtime".to_string())
1203    }
1204}
1205
1206enum LookupItem<'a> {
1207    None,
1208    Name(&'a str),
1209    InterfaceNoPop,
1210}
1211
1212fn lookup_keys(
1213    resolve: &Resolve,
1214    key: &WorldKey,
1215    item: LookupItem<'_>,
1216) -> Vec<(String, Vec<String>)> {
1217    struct Name<'a> {
1218        prefix: Prefix,
1219        item: Option<&'a str>,
1220    }
1221
1222    #[derive(Copy, Clone)]
1223    enum Prefix {
1224        Namespace(PackageId),
1225        UnversionedPackage(PackageId),
1226        VersionedPackage(PackageId),
1227        UnversionedInterface(InterfaceId),
1228        VersionedInterface(InterfaceId),
1229    }
1230
1231    let prefix = match key {
1232        WorldKey::Interface(id) => Prefix::VersionedInterface(*id),
1233
1234        // Non-interface-keyed names don't get the lookup logic below,
1235        // they're relatively uncommon so only lookup the precise key here.
1236        WorldKey::Name(key) => {
1237            let to_lookup = match item {
1238                LookupItem::Name(item) => format!("{key}/{item}"),
1239                LookupItem::None | LookupItem::InterfaceNoPop => key.to_string(),
1240            };
1241            return vec![(to_lookup, Vec::new())];
1242        }
1243    };
1244
1245    // Here names are iteratively attempted as `key` + `item` is "walked to
1246    // its root" and each attempt is consulted in `self.opts.with`. This
1247    // loop will start at the leaf, the most specific path, and then walk to
1248    // the root, popping items, trying to find a result.
1249    //
1250    // Each time a name is "popped" the projection from the next path is
1251    // pushed onto `projection`. This means that if we actually find a match
1252    // then `projection` is a collection of namespaces that results in the
1253    // final replacement name.
1254    let (interface_required, item) = match item {
1255        LookupItem::None => (false, None),
1256        LookupItem::Name(s) => (false, Some(s)),
1257        LookupItem::InterfaceNoPop => (true, None),
1258    };
1259    let mut name = Name { prefix, item };
1260    let mut projection = Vec::new();
1261    let mut ret = Vec::new();
1262    loop {
1263        let lookup = name.lookup_key(resolve);
1264        ret.push((lookup, projection.clone()));
1265        if !name.pop(resolve, &mut projection) {
1266            break;
1267        }
1268        if interface_required {
1269            match name.prefix {
1270                Prefix::VersionedInterface(_) | Prefix::UnversionedInterface(_) => {}
1271                _ => break,
1272            }
1273        }
1274    }
1275
1276    return ret;
1277
1278    impl<'a> Name<'a> {
1279        fn lookup_key(&self, resolve: &Resolve) -> String {
1280            let mut s = self.prefix.lookup_key(resolve);
1281            if let Some(item) = self.item {
1282                s.push_str("/");
1283                s.push_str(item);
1284            }
1285            s
1286        }
1287
1288        fn pop(&mut self, resolve: &'a Resolve, projection: &mut Vec<String>) -> bool {
1289            match (self.item, self.prefix) {
1290                // If this is a versioned resource name, try the unversioned
1291                // resource name next.
1292                (Some(_), Prefix::VersionedInterface(id)) => {
1293                    self.prefix = Prefix::UnversionedInterface(id);
1294                    true
1295                }
1296                // If this is an unversioned resource name then time to
1297                // ignore the resource itself and move on to the next most
1298                // specific item, versioned interface names.
1299                (Some(item), Prefix::UnversionedInterface(id)) => {
1300                    self.prefix = Prefix::VersionedInterface(id);
1301                    self.item = None;
1302                    projection.push(item.to_upper_camel_case());
1303                    true
1304                }
1305                (Some(_), _) => unreachable!(),
1306                (None, _) => self.prefix.pop(resolve, projection),
1307            }
1308        }
1309    }
1310
1311    impl Prefix {
1312        fn lookup_key(&self, resolve: &Resolve) -> String {
1313            match *self {
1314                Prefix::Namespace(id) => resolve.packages[id].name.namespace.clone(),
1315                Prefix::UnversionedPackage(id) => {
1316                    let mut name = resolve.packages[id].name.clone();
1317                    name.version = None;
1318                    name.to_string()
1319                }
1320                Prefix::VersionedPackage(id) => resolve.packages[id].name.to_string(),
1321                Prefix::UnversionedInterface(id) => {
1322                    let id = resolve.id_of(id).unwrap();
1323                    match id.find('@') {
1324                        Some(i) => id[..i].to_string(),
1325                        None => id,
1326                    }
1327                }
1328                Prefix::VersionedInterface(id) => resolve.id_of(id).unwrap(),
1329            }
1330        }
1331
1332        fn pop(&mut self, resolve: &Resolve, projection: &mut Vec<String>) -> bool {
1333            *self = match *self {
1334                // try the unversioned interface next
1335                Prefix::VersionedInterface(id) => Prefix::UnversionedInterface(id),
1336                // try this interface's versioned package next
1337                Prefix::UnversionedInterface(id) => {
1338                    let iface = &resolve.interfaces[id];
1339                    let name = iface.name.as_ref().unwrap();
1340                    projection.push(to_rust_ident(name));
1341                    Prefix::VersionedPackage(iface.package.unwrap())
1342                }
1343                // try the unversioned package next
1344                Prefix::VersionedPackage(id) => Prefix::UnversionedPackage(id),
1345                // try this package's namespace next
1346                Prefix::UnversionedPackage(id) => {
1347                    let name = &resolve.packages[id].name;
1348                    projection.push(to_rust_ident(&name.name));
1349                    Prefix::Namespace(id)
1350                }
1351                // nothing left to try any more
1352                Prefix::Namespace(_) => return false,
1353            };
1354            true
1355        }
1356    }
1357}
1358
1359impl Wasmtime {
1360    fn has_world_imports_trait(&self, resolve: &Resolve, world: WorldId) -> bool {
1361        !self.import_functions.is_empty() || get_world_resources(resolve, world).count() > 0
1362    }
1363
1364    fn world_imports_trait(&mut self, resolve: &Resolve, world: WorldId) -> Option<GeneratedTrait> {
1365        if !self.has_world_imports_trait(resolve, world) {
1366            return None;
1367        }
1368
1369        let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
1370
1371        let functions = self.import_functions.clone();
1372        let mut generator = InterfaceGenerator::new(self, resolve);
1373        let generated_trait = generator.generate_trait(
1374            &format!("{world_camel}Imports"),
1375            &functions
1376                .iter()
1377                .filter(|f| f.kind.resource().is_none())
1378                .collect::<Vec<_>>(),
1379            &[],
1380            &get_world_resources(resolve, world).collect::<Vec<_>>(),
1381        );
1382        let src = String::from(mem::take(&mut generator.src));
1383        self.src.push_str(&src);
1384        Some(generated_trait)
1385    }
1386
1387    fn import_interface_paths(&self) -> Vec<(InterfaceId, String)> {
1388        self.import_interfaces
1389            .iter()
1390            .map(|(_, id, _, name)| {
1391                let path = match name {
1392                    InterfaceName::Path(path) => path.join("::"),
1393                    InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(),
1394                };
1395                (*id, path)
1396            })
1397            .collect()
1398    }
1399
1400    fn import_interface_path(&self, id: &InterfaceId) -> String {
1401        match &self.interface_names[id] {
1402            InterfaceName::Path(path) => path.join("::"),
1403            InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(),
1404        }
1405    }
1406
1407    fn import_interface_any_concurrent(&self, resolve: &Resolve, id: InterfaceId) -> bool {
1408        for (key, id2, ..) in self.import_interfaces.iter() {
1409            if id != *id2 {
1410                continue;
1411            }
1412
1413            let key = resolve.name_world_key(key);
1414            return resolve.interfaces[id].functions.iter().any(|(name, _)| {
1415                self.opts.import_call_style(Some(&key), name) == CallStyle::Concurrent
1416            });
1417        }
1418        unreachable!()
1419    }
1420
1421    fn world_host_traits(
1422        &self,
1423        resolve: &Resolve,
1424        world_trait: Option<&GeneratedTrait>,
1425    ) -> (Vec<String>, Vec<String>) {
1426        let mut sync = Vec::new();
1427        let mut concurrent = Vec::new();
1428        for (id, path) in self.import_interface_paths() {
1429            sync.push(format!("{path}::Host"));
1430            if self.import_interface_any_concurrent(resolve, id) {
1431                concurrent.push(format!("{path}::HostConcurrent"));
1432            }
1433        }
1434        if let Some(world_trait) = world_trait {
1435            sync.push(world_trait.name.clone());
1436            concurrent.extend(world_trait.concurrent_name.clone());
1437        }
1438        if let CallStyle::Async | CallStyle::Concurrent = self.opts.call_style() {
1439            sync.push("Send".to_string());
1440            if !concurrent.is_empty() {
1441                concurrent.push("Send".to_string());
1442            }
1443        }
1444        (sync, concurrent)
1445    }
1446
1447    fn world_add_to_linker(
1448        &mut self,
1449        resolve: &Resolve,
1450        world: WorldId,
1451        world_trait: Option<&GeneratedTrait>,
1452    ) {
1453        let has_world_imports_trait = self.has_world_imports_trait(resolve, world);
1454        if self.import_interfaces.is_empty() && !has_world_imports_trait {
1455            return;
1456        }
1457
1458        let (options_param, options_arg) = if self.world_link_options.has_any() {
1459            ("options: &LinkOptions,", ", options")
1460        } else {
1461            ("", "")
1462        };
1463
1464        let opt_t_send_bound = if self.opts.is_store_data_send() {
1465            "+ Send"
1466        } else {
1467            ""
1468        };
1469
1470        let wt = self.wasmtime_path();
1471        if let Some(world_trait) = world_trait {
1472            let d_bound = match &world_trait.concurrent_name {
1473                Some(name) => name.clone(),
1474                None => format!("{wt}::component::HasData"),
1475            };
1476            uwrite!(
1477                self.src,
1478                "
1479                    pub fn add_to_linker_imports<T, D>(
1480                        linker: &mut {wt}::component::Linker<T>,
1481                        {options_param}
1482                        host_getter: fn(&mut T) -> D::Data<'_>,
1483                    ) -> {wt}::Result<()>
1484                        where
1485                            D: {d_bound},
1486                            for<'a> D::Data<'a>: {name},
1487                            T: 'static {opt_t_send_bound}
1488                    {{
1489                        let mut linker = linker.root();
1490                ",
1491                name = world_trait.name,
1492            );
1493            let gate = FeatureGate::open(&mut self.src, &resolve.worlds[world].stability);
1494            for (ty, name) in get_world_resources(resolve, world) {
1495                Self::generate_add_resource_to_linker(
1496                    None,
1497                    &mut self.src,
1498                    &self.opts,
1499                    &wt,
1500                    "linker",
1501                    name,
1502                    &resolve.types[ty].stability,
1503                );
1504            }
1505            for f in self.import_functions.clone() {
1506                let mut generator = InterfaceGenerator::new(self, resolve);
1507                generator.generate_add_function_to_linker(TypeOwner::World(world), &f, "linker");
1508                let src = String::from(generator.src);
1509                self.src.push_str(&src);
1510                self.src.push_str("\n");
1511            }
1512            gate.close(&mut self.src);
1513            uwriteln!(self.src, "Ok(())\n}}");
1514        }
1515
1516        let (sync_bounds, concurrent_bounds) = self.world_host_traits(resolve, world_trait);
1517        let sync_bounds = sync_bounds.join(" + ");
1518        let concurrent_bounds = concurrent_bounds.join(" + ");
1519        let d_bounds = if !concurrent_bounds.is_empty() {
1520            concurrent_bounds
1521        } else {
1522            format!("{wt}::component::HasData")
1523        };
1524
1525        uwriteln!(
1526            self.src,
1527            "
1528                pub fn add_to_linker<T, D>(
1529                    linker: &mut {wt}::component::Linker<T>,
1530                    {options_param}
1531                    host_getter: fn(&mut T) -> D::Data<'_>,
1532                ) -> {wt}::Result<()>
1533                    where
1534                        D: {d_bounds},
1535                        for<'a> D::Data<'a>: {sync_bounds},
1536                        T: 'static {opt_t_send_bound}
1537                {{
1538            "
1539        );
1540        let gate = FeatureGate::open(&mut self.src, &resolve.worlds[world].stability);
1541        if has_world_imports_trait {
1542            uwriteln!(
1543                self.src,
1544                "Self::add_to_linker_imports::<T, D>(linker {options_arg}, host_getter)?;"
1545            );
1546        }
1547        for (interface_id, path) in self.import_interface_paths() {
1548            let options_arg = if self.interface_link_options[&interface_id].has_any() {
1549                ", &options.into()"
1550            } else {
1551                ""
1552            };
1553
1554            let import_stability = resolve.worlds[world]
1555                .imports
1556                .iter()
1557                .filter_map(|(_, i)| match i {
1558                    WorldItem::Interface { id, stability } if *id == interface_id => {
1559                        Some(stability.clone())
1560                    }
1561                    _ => None,
1562                })
1563                .next()
1564                .unwrap_or(Stability::Unknown);
1565
1566            let gate = FeatureGate::open(&mut self.src, &import_stability);
1567            uwriteln!(
1568                self.src,
1569                "{path}::add_to_linker::<T, D>(linker {options_arg}, host_getter)?;"
1570            );
1571            gate.close(&mut self.src);
1572        }
1573        gate.close(&mut self.src);
1574        uwriteln!(self.src, "Ok(())\n}}");
1575    }
1576
1577    fn generate_add_resource_to_linker(
1578        qualifier: Option<&str>,
1579        src: &mut Source,
1580        opts: &Opts,
1581        wt: &str,
1582        inst: &str,
1583        name: &str,
1584        stability: &Stability,
1585    ) {
1586        let gate = FeatureGate::open(src, stability);
1587        let camel = name.to_upper_camel_case();
1588        if let CallStyle::Async | CallStyle::Concurrent = opts.drop_call_style(qualifier, name) {
1589            uwriteln!(
1590                src,
1591                "{inst}.resource_async(
1592                    \"{name}\",
1593                    {wt}::component::ResourceType::host::<{camel}>(),
1594                    move |mut store, rep| {{
1595                        {wt}::component::__internal::Box::new(async move {{
1596                            Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep)).await
1597                        }})
1598                    }},
1599                )?;"
1600            )
1601        } else {
1602            uwriteln!(
1603                src,
1604                "{inst}.resource(
1605                    \"{name}\",
1606                    {wt}::component::ResourceType::host::<{camel}>(),
1607                    move |mut store, rep| -> {wt}::Result<()> {{
1608                        Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep))
1609                    }},
1610                )?;"
1611            )
1612        }
1613        gate.close(src);
1614    }
1615}
1616
1617struct InterfaceGenerator<'a> {
1618    src: Source,
1619    generator: &'a mut Wasmtime,
1620    resolve: &'a Resolve,
1621    current_interface: Option<(InterfaceId, &'a WorldKey, bool)>,
1622}
1623
1624impl<'a> InterfaceGenerator<'a> {
1625    fn new(generator: &'a mut Wasmtime, resolve: &'a Resolve) -> InterfaceGenerator<'a> {
1626        InterfaceGenerator {
1627            src: Source::default(),
1628            generator,
1629            resolve,
1630            current_interface: None,
1631        }
1632    }
1633
1634    fn types_imported(&self) -> bool {
1635        match self.current_interface {
1636            Some((_, _, is_export)) => !is_export,
1637            None => true,
1638        }
1639    }
1640
1641    fn types(&mut self, id: InterfaceId) {
1642        for (name, id) in self.resolve.interfaces[id].types.iter() {
1643            self.define_type(name, *id);
1644        }
1645    }
1646
1647    fn define_type(&mut self, name: &str, id: TypeId) {
1648        let ty = &self.resolve.types[id];
1649        match &ty.kind {
1650            TypeDefKind::Record(record) => self.type_record(id, name, record, &ty.docs),
1651            TypeDefKind::Flags(flags) => self.type_flags(id, name, flags, &ty.docs),
1652            TypeDefKind::Tuple(tuple) => self.type_tuple(id, name, tuple, &ty.docs),
1653            TypeDefKind::Enum(enum_) => self.type_enum(id, name, enum_, &ty.docs),
1654            TypeDefKind::Variant(variant) => self.type_variant(id, name, variant, &ty.docs),
1655            TypeDefKind::Option(t) => self.type_option(id, name, t, &ty.docs),
1656            TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs),
1657            TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs),
1658            TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs),
1659            TypeDefKind::Future(t) => self.type_future(id, name, t.as_ref(), &ty.docs),
1660            TypeDefKind::Stream(t) => self.type_stream(id, name, t.as_ref(), &ty.docs),
1661            TypeDefKind::Handle(handle) => self.type_handle(id, name, handle, &ty.docs),
1662            TypeDefKind::Resource => self.type_resource(id, name, ty, &ty.docs),
1663            TypeDefKind::Unknown => unreachable!(),
1664            TypeDefKind::FixedSizeList(..) => todo!(),
1665        }
1666    }
1667
1668    fn type_handle(&mut self, id: TypeId, name: &str, handle: &Handle, docs: &Docs) {
1669        self.rustdoc(docs);
1670        let name = name.to_upper_camel_case();
1671        uwriteln!(self.src, "pub type {name} = ");
1672        self.print_handle(handle);
1673        self.push_str(";\n");
1674        self.assert_type(id, &name);
1675    }
1676
1677    fn type_resource(&mut self, id: TypeId, name: &str, _resource: &TypeDef, docs: &Docs) {
1678        let camel = name.to_upper_camel_case();
1679        let wt = self.generator.wasmtime_path();
1680
1681        if self.types_imported() {
1682            self.rustdoc(docs);
1683
1684            let replacement = match self.current_interface {
1685                Some((_, key, _)) => {
1686                    self.generator
1687                        .lookup_replacement(self.resolve, key, Some(name))
1688                }
1689                None => {
1690                    self.generator.used_with_opts.insert(name.into());
1691                    self.generator.opts.with.get(name).cloned()
1692                }
1693            };
1694            match replacement {
1695                Some(path) => {
1696                    uwriteln!(
1697                        self.src,
1698                        "pub use {}{path} as {camel};",
1699                        self.path_to_root()
1700                    );
1701                }
1702                None => {
1703                    uwriteln!(self.src, "pub enum {camel} {{}}");
1704                }
1705            }
1706
1707            // Generate resource trait
1708
1709            let functions = get_resource_functions(self.resolve, id);
1710            self.generate_trait(
1711                &format!("Host{camel}"),
1712                &functions,
1713                &[ExtraTraitMethod::ResourceDrop { name }],
1714                &[],
1715            );
1716        } else {
1717            self.rustdoc(docs);
1718            uwriteln!(
1719                self.src,
1720                "
1721                    pub type {camel} = {wt}::component::ResourceAny;
1722
1723                    pub struct Guest{camel}<'a> {{
1724                        funcs: &'a Guest,
1725                    }}
1726                "
1727            );
1728        }
1729    }
1730
1731    fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) {
1732        let info = self.info(id);
1733        let wt = self.generator.wasmtime_path();
1734
1735        // We use a BTree set to make sure we don't have any duplicates and we have a stable order
1736        let additional_derives: BTreeSet<String> = self
1737            .generator
1738            .opts
1739            .additional_derive_attributes
1740            .iter()
1741            .cloned()
1742            .collect();
1743
1744        for (name, mode) in self.modes_of(id) {
1745            let lt = self.lifetime_for(&info, mode);
1746            self.rustdoc(docs);
1747
1748            let mut derives = additional_derives.clone();
1749
1750            uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1751            if lt.is_none() {
1752                uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1753            }
1754            uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1755            self.push_str("#[component(record)]\n");
1756            if let Some(path) = &self.generator.opts.wasmtime_crate {
1757                uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1758            }
1759
1760            if info.is_copy() {
1761                derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
1762            } else if info.is_clone() {
1763                derives.insert("Clone".to_string());
1764            }
1765
1766            if !derives.is_empty() {
1767                self.push_str("#[derive(");
1768                self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1769                self.push_str(")]\n")
1770            }
1771
1772            self.push_str(&format!("pub struct {name}"));
1773            self.print_generics(lt);
1774            self.push_str(" {\n");
1775            for field in record.fields.iter() {
1776                self.rustdoc(&field.docs);
1777                self.push_str(&format!("#[component(name = \"{}\")]\n", field.name));
1778                self.push_str("pub ");
1779                self.push_str(&to_rust_ident(&field.name));
1780                self.push_str(": ");
1781                self.print_ty(&field.ty, mode);
1782                self.push_str(",\n");
1783            }
1784            self.push_str("}\n");
1785
1786            self.push_str("impl");
1787            self.print_generics(lt);
1788            self.push_str(" core::fmt::Debug for ");
1789            self.push_str(&name);
1790            self.print_generics(lt);
1791            self.push_str(" {\n");
1792            self.push_str(
1793                "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1794            );
1795            self.push_str(&format!("f.debug_struct(\"{name}\")"));
1796            for field in record.fields.iter() {
1797                self.push_str(&format!(
1798                    ".field(\"{}\", &self.{})",
1799                    field.name,
1800                    to_rust_ident(&field.name)
1801                ));
1802            }
1803            self.push_str(".finish()\n");
1804            self.push_str("}\n");
1805            self.push_str("}\n");
1806
1807            if info.error {
1808                self.push_str("impl");
1809                self.print_generics(lt);
1810                self.push_str(" core::fmt::Display for ");
1811                self.push_str(&name);
1812                self.print_generics(lt);
1813                self.push_str(" {\n");
1814                self.push_str(
1815                    "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1816                );
1817                self.push_str("write!(f, \"{:?}\", self)\n");
1818                self.push_str("}\n");
1819                self.push_str("}\n");
1820
1821                self.push_str("impl core::error::Error for ");
1822                self.push_str(&name);
1823                self.push_str("{}\n");
1824            }
1825            self.assert_type(id, &name);
1826        }
1827    }
1828
1829    fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) {
1830        let info = self.info(id);
1831        for (name, mode) in self.modes_of(id) {
1832            let lt = self.lifetime_for(&info, mode);
1833            self.rustdoc(docs);
1834            self.push_str(&format!("pub type {name}"));
1835            self.print_generics(lt);
1836            self.push_str(" = (");
1837            for ty in tuple.types.iter() {
1838                self.print_ty(ty, mode);
1839                self.push_str(",");
1840            }
1841            self.push_str(");\n");
1842            self.assert_type(id, &name);
1843        }
1844    }
1845
1846    fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
1847        self.rustdoc(docs);
1848        let wt = self.generator.wasmtime_path();
1849        let rust_name = to_rust_upper_camel_case(name);
1850        uwriteln!(self.src, "{wt}::component::flags!(\n");
1851        self.src.push_str(&format!("{rust_name} {{\n"));
1852        for flag in flags.flags.iter() {
1853            // TODO wasmtime-component-macro doesn't support docs for flags rn
1854            uwrite!(
1855                self.src,
1856                "#[component(name=\"{}\")] const {};\n",
1857                flag.name,
1858                flag.name.to_shouty_snake_case()
1859            );
1860        }
1861        self.src.push_str("}\n");
1862        self.src.push_str(");\n\n");
1863        self.assert_type(id, &rust_name);
1864    }
1865
1866    fn type_variant(&mut self, id: TypeId, _name: &str, variant: &Variant, docs: &Docs) {
1867        self.print_rust_enum(
1868            id,
1869            variant.cases.iter().map(|c| {
1870                (
1871                    c.name.to_upper_camel_case(),
1872                    Some(c.name.clone()),
1873                    &c.docs,
1874                    c.ty.as_ref(),
1875                )
1876            }),
1877            docs,
1878            "variant",
1879        );
1880    }
1881
1882    fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) {
1883        let info = self.info(id);
1884
1885        for (name, mode) in self.modes_of(id) {
1886            self.rustdoc(docs);
1887            let lt = self.lifetime_for(&info, mode);
1888            self.push_str(&format!("pub type {name}"));
1889            self.print_generics(lt);
1890            self.push_str("= Option<");
1891            self.print_ty(payload, mode);
1892            self.push_str(">;\n");
1893            self.assert_type(id, &name);
1894        }
1895    }
1896
1897    // Emit a double-check that the wit-parser-understood size of a type agrees
1898    // with the Wasmtime-understood size of a type.
1899    fn assert_type(&mut self, id: TypeId, name: &str) {
1900        self.push_str("const _: () = {\n");
1901        let wt = self.generator.wasmtime_path();
1902        uwriteln!(
1903            self.src,
1904            "assert!({} == <{name} as {wt}::component::ComponentType>::SIZE32);",
1905            self.generator.sizes.size(&Type::Id(id)).size_wasm32(),
1906        );
1907        uwriteln!(
1908            self.src,
1909            "assert!({} == <{name} as {wt}::component::ComponentType>::ALIGN32);",
1910            self.generator.sizes.align(&Type::Id(id)).align_wasm32(),
1911        );
1912        self.push_str("};\n");
1913    }
1914
1915    fn print_rust_enum<'b>(
1916        &mut self,
1917        id: TypeId,
1918        cases: impl IntoIterator<Item = (String, Option<String>, &'b Docs, Option<&'b Type>)> + Clone,
1919        docs: &Docs,
1920        derive_component: &str,
1921    ) where
1922        Self: Sized,
1923    {
1924        let info = self.info(id);
1925        let wt = self.generator.wasmtime_path();
1926
1927        // We use a BTree set to make sure we don't have any duplicates and we have a stable order
1928        let additional_derives: BTreeSet<String> = self
1929            .generator
1930            .opts
1931            .additional_derive_attributes
1932            .iter()
1933            .cloned()
1934            .collect();
1935
1936        for (name, mode) in self.modes_of(id) {
1937            let name = to_rust_upper_camel_case(&name);
1938
1939            let mut derives = additional_derives.clone();
1940
1941            self.rustdoc(docs);
1942            let lt = self.lifetime_for(&info, mode);
1943            uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1944            if lt.is_none() {
1945                uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1946            }
1947            uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1948            self.push_str(&format!("#[component({derive_component})]\n"));
1949            if let Some(path) = &self.generator.opts.wasmtime_crate {
1950                uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1951            }
1952            if info.is_copy() {
1953                derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
1954            } else if info.is_clone() {
1955                derives.insert("Clone".to_string());
1956            }
1957
1958            if !derives.is_empty() {
1959                self.push_str("#[derive(");
1960                self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1961                self.push_str(")]\n")
1962            }
1963
1964            self.push_str(&format!("pub enum {name}"));
1965            self.print_generics(lt);
1966            self.push_str("{\n");
1967            for (case_name, component_name, docs, payload) in cases.clone() {
1968                self.rustdoc(docs);
1969                if let Some(n) = component_name {
1970                    self.push_str(&format!("#[component(name = \"{n}\")] "));
1971                }
1972                self.push_str(&case_name);
1973                if let Some(ty) = payload {
1974                    self.push_str("(");
1975                    self.print_ty(ty, mode);
1976                    self.push_str(")")
1977                }
1978                self.push_str(",\n");
1979            }
1980            self.push_str("}\n");
1981
1982            self.print_rust_enum_debug(
1983                id,
1984                mode,
1985                &name,
1986                cases
1987                    .clone()
1988                    .into_iter()
1989                    .map(|(name, _attr, _docs, ty)| (name, ty)),
1990            );
1991
1992            if info.error {
1993                self.push_str("impl");
1994                self.print_generics(lt);
1995                self.push_str(" core::fmt::Display for ");
1996                self.push_str(&name);
1997                self.print_generics(lt);
1998                self.push_str(" {\n");
1999                self.push_str(
2000                    "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
2001                );
2002                self.push_str("write!(f, \"{:?}\", self)\n");
2003                self.push_str("}\n");
2004                self.push_str("}\n");
2005
2006                self.push_str("impl");
2007                self.print_generics(lt);
2008                self.push_str(" core::error::Error for ");
2009                self.push_str(&name);
2010                self.print_generics(lt);
2011                self.push_str(" {}\n");
2012            }
2013
2014            self.assert_type(id, &name);
2015        }
2016    }
2017
2018    fn print_rust_enum_debug<'b>(
2019        &mut self,
2020        id: TypeId,
2021        mode: TypeMode,
2022        name: &str,
2023        cases: impl IntoIterator<Item = (String, Option<&'b Type>)>,
2024    ) where
2025        Self: Sized,
2026    {
2027        let info = self.info(id);
2028        let lt = self.lifetime_for(&info, mode);
2029        self.push_str("impl");
2030        self.print_generics(lt);
2031        self.push_str(" core::fmt::Debug for ");
2032        self.push_str(name);
2033        self.print_generics(lt);
2034        self.push_str(" {\n");
2035        self.push_str("fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n");
2036        self.push_str("match self {\n");
2037        for (case_name, payload) in cases {
2038            self.push_str(name);
2039            self.push_str("::");
2040            self.push_str(&case_name);
2041            if payload.is_some() {
2042                self.push_str("(e)");
2043            }
2044            self.push_str(" => {\n");
2045            self.push_str(&format!("f.debug_tuple(\"{name}::{case_name}\")"));
2046            if payload.is_some() {
2047                self.push_str(".field(e)");
2048            }
2049            self.push_str(".finish()\n");
2050            self.push_str("}\n");
2051        }
2052        self.push_str("}\n");
2053        self.push_str("}\n");
2054        self.push_str("}\n");
2055    }
2056
2057    fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) {
2058        let info = self.info(id);
2059
2060        for (name, mode) in self.modes_of(id) {
2061            self.rustdoc(docs);
2062            let lt = self.lifetime_for(&info, mode);
2063            self.push_str(&format!("pub type {name}"));
2064            self.print_generics(lt);
2065            self.push_str("= Result<");
2066            self.print_optional_ty(result.ok.as_ref(), mode);
2067            self.push_str(",");
2068            self.print_optional_ty(result.err.as_ref(), mode);
2069            self.push_str(">;\n");
2070            self.assert_type(id, &name);
2071        }
2072    }
2073
2074    fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
2075        let info = self.info(id);
2076        let wt = self.generator.wasmtime_path();
2077
2078        // We use a BTree set to make sure we don't have any duplicates and have a stable order
2079        let mut derives: BTreeSet<String> = self
2080            .generator
2081            .opts
2082            .additional_derive_attributes
2083            .iter()
2084            .cloned()
2085            .collect();
2086
2087        derives.extend(
2088            ["Clone", "Copy", "PartialEq", "Eq"]
2089                .into_iter()
2090                .map(|s| s.to_string()),
2091        );
2092
2093        let name = to_rust_upper_camel_case(name);
2094        self.rustdoc(docs);
2095        uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
2096        uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
2097        uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
2098        self.push_str("#[component(enum)]\n");
2099        if let Some(path) = &self.generator.opts.wasmtime_crate {
2100            uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
2101        }
2102
2103        self.push_str("#[derive(");
2104        self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
2105        self.push_str(")]\n");
2106
2107        let repr = match enum_.cases.len().ilog2() {
2108            0..=7 => "u8",
2109            8..=15 => "u16",
2110            _ => "u32",
2111        };
2112        uwriteln!(self.src, "#[repr({repr})]");
2113
2114        self.push_str(&format!("pub enum {name} {{\n"));
2115        for case in enum_.cases.iter() {
2116            self.rustdoc(&case.docs);
2117            self.push_str(&format!("#[component(name = \"{}\")]", case.name));
2118            self.push_str(&case.name.to_upper_camel_case());
2119            self.push_str(",\n");
2120        }
2121        self.push_str("}\n");
2122
2123        // Auto-synthesize an implementation of the standard `Error` trait for
2124        // error-looking types based on their name.
2125        if info.error {
2126            self.push_str("impl ");
2127            self.push_str(&name);
2128            self.push_str("{\n");
2129
2130            self.push_str("pub fn name(&self) -> &'static str {\n");
2131            self.push_str("match self {\n");
2132            for case in enum_.cases.iter() {
2133                self.push_str(&name);
2134                self.push_str("::");
2135                self.push_str(&case.name.to_upper_camel_case());
2136                self.push_str(" => \"");
2137                self.push_str(case.name.as_str());
2138                self.push_str("\",\n");
2139            }
2140            self.push_str("}\n");
2141            self.push_str("}\n");
2142
2143            self.push_str("pub fn message(&self) -> &'static str {\n");
2144            self.push_str("match self {\n");
2145            for case in enum_.cases.iter() {
2146                self.push_str(&name);
2147                self.push_str("::");
2148                self.push_str(&case.name.to_upper_camel_case());
2149                self.push_str(" => \"");
2150                if let Some(contents) = &case.docs.contents {
2151                    self.push_str(contents.trim());
2152                }
2153                self.push_str("\",\n");
2154            }
2155            self.push_str("}\n");
2156            self.push_str("}\n");
2157
2158            self.push_str("}\n");
2159
2160            self.push_str("impl core::fmt::Debug for ");
2161            self.push_str(&name);
2162            self.push_str(
2163                "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
2164            );
2165            self.push_str("f.debug_struct(\"");
2166            self.push_str(&name);
2167            self.push_str("\")\n");
2168            self.push_str(".field(\"code\", &(*self as i32))\n");
2169            self.push_str(".field(\"name\", &self.name())\n");
2170            self.push_str(".field(\"message\", &self.message())\n");
2171            self.push_str(".finish()\n");
2172            self.push_str("}\n");
2173            self.push_str("}\n");
2174
2175            self.push_str("impl core::fmt::Display for ");
2176            self.push_str(&name);
2177            self.push_str(
2178                "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
2179            );
2180            self.push_str("write!(f, \"{} (error {})\", self.name(), *self as i32)");
2181            self.push_str("}\n");
2182            self.push_str("}\n");
2183            self.push_str("\n");
2184            self.push_str("impl core::error::Error for ");
2185            self.push_str(&name);
2186            self.push_str("{}\n");
2187        } else {
2188            self.print_rust_enum_debug(
2189                id,
2190                TypeMode::Owned,
2191                &name,
2192                enum_
2193                    .cases
2194                    .iter()
2195                    .map(|c| (c.name.to_upper_camel_case(), None)),
2196            )
2197        }
2198        self.assert_type(id, &name);
2199    }
2200
2201    fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
2202        let info = self.info(id);
2203        for (name, mode) in self.modes_of(id) {
2204            self.rustdoc(docs);
2205            self.push_str(&format!("pub type {name}"));
2206            let lt = self.lifetime_for(&info, mode);
2207            self.print_generics(lt);
2208            self.push_str(" = ");
2209            self.print_ty(ty, mode);
2210            self.push_str(";\n");
2211            let def_id = resolve_type_definition_id(self.resolve, id);
2212            if !matches!(self.resolve().types[def_id].kind, TypeDefKind::Resource) {
2213                self.assert_type(id, &name);
2214            }
2215        }
2216    }
2217
2218    fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
2219        let info = self.info(id);
2220        for (name, mode) in self.modes_of(id) {
2221            let lt = self.lifetime_for(&info, mode);
2222            self.rustdoc(docs);
2223            self.push_str(&format!("pub type {name}"));
2224            self.print_generics(lt);
2225            self.push_str(" = ");
2226            self.print_list(ty, mode);
2227            self.push_str(";\n");
2228            self.assert_type(id, &name);
2229        }
2230    }
2231
2232    fn type_stream(&mut self, id: TypeId, name: &str, ty: Option<&Type>, docs: &Docs) {
2233        self.rustdoc(docs);
2234        self.push_str(&format!("pub type {name}"));
2235        self.print_generics(None);
2236        self.push_str(" = ");
2237        self.print_stream(ty);
2238        self.push_str(";\n");
2239        self.assert_type(id, &name);
2240    }
2241
2242    fn type_future(&mut self, id: TypeId, name: &str, ty: Option<&Type>, docs: &Docs) {
2243        self.rustdoc(docs);
2244        self.push_str(&format!("pub type {name}"));
2245        self.print_generics(None);
2246        self.push_str(" = ");
2247        self.print_future(ty);
2248        self.push_str(";\n");
2249        self.assert_type(id, &name);
2250    }
2251
2252    fn print_result_ty(&mut self, result: Option<Type>, mode: TypeMode) {
2253        match result {
2254            Some(ty) => self.print_ty(&ty, mode),
2255            None => self.push_str("()"),
2256        }
2257    }
2258
2259    fn special_case_trappable_error(
2260        &mut self,
2261        func: &Function,
2262    ) -> Option<(&'a Result_, TypeId, String)> {
2263        self.generator
2264            .used_trappable_imports_opts
2265            .insert(func.name.clone());
2266
2267        let result = func.result?;
2268
2269        // We fill in a special trappable error type in the case when a function has just one
2270        // result, which is itself a `result<a, e>`, and the `e` is *not* a primitive
2271        // (i.e. defined in std) type, and matches the typename given by the user.
2272        let id = match result {
2273            Type::Id(id) => id,
2274            _ => return None,
2275        };
2276        let result = match &self.resolve.types[id].kind {
2277            TypeDefKind::Result(r) => r,
2278            _ => return None,
2279        };
2280        let error_typeid = match result.err? {
2281            Type::Id(id) => resolve_type_definition_id(&self.resolve, id),
2282            _ => return None,
2283        };
2284
2285        let name = self.generator.trappable_errors.get(&error_typeid)?;
2286
2287        let mut path = self.path_to_root();
2288        uwrite!(path, "{name}");
2289        Some((result, error_typeid, path))
2290    }
2291
2292    fn generate_add_to_linker(&mut self, id: InterfaceId, name: &str) {
2293        let iface = &self.resolve.interfaces[id];
2294        let owner = TypeOwner::Interface(id);
2295        let wt = self.generator.wasmtime_path();
2296
2297        let mut required_conversion_traits = IndexSet::new();
2298        let extra_functions = {
2299            let mut functions = Vec::new();
2300            let mut errors_converted = IndexMap::new();
2301            let mut my_error_types = iface
2302                .types
2303                .iter()
2304                .filter(|(_, id)| self.generator.trappable_errors.contains_key(*id))
2305                .map(|(_, id)| *id)
2306                .collect::<Vec<_>>();
2307            my_error_types.extend(
2308                iface
2309                    .functions
2310                    .iter()
2311                    .filter_map(|(_, func)| self.special_case_trappable_error(func))
2312                    .map(|(_, id, _)| id),
2313            );
2314            for err_id in my_error_types {
2315                let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err_id)];
2316                let err_name = err.name.as_ref().unwrap();
2317                let owner = match err.owner {
2318                    TypeOwner::Interface(i) => i,
2319                    _ => unimplemented!(),
2320                };
2321                match self.path_to_interface(owner) {
2322                    Some(path) => {
2323                        required_conversion_traits.insert(format!("{path}::Host"));
2324                    }
2325                    None => {
2326                        if errors_converted.insert(err_name, err_id).is_none() {
2327                            functions.push(ExtraTraitMethod::ErrorConvert {
2328                                name: err_name,
2329                                id: err_id,
2330                            })
2331                        }
2332                    }
2333                }
2334            }
2335            functions
2336        };
2337
2338        // Generate the `pub trait` which represents the host functionality for
2339        // this import which additionally inherits from all resource traits
2340        // for this interface defined by `type_resource`.
2341        let generated_trait = self.generate_trait(
2342            "Host",
2343            &iface
2344                .functions
2345                .iter()
2346                .filter_map(|(_, f)| {
2347                    if f.kind.resource().is_none() {
2348                        Some(f)
2349                    } else {
2350                        None
2351                    }
2352                })
2353                .collect::<Vec<_>>(),
2354            &extra_functions,
2355            &get_resources(self.resolve, id).collect::<Vec<_>>(),
2356        );
2357
2358        let opt_t_send_bound = match self.generator.opts.call_style() {
2359            CallStyle::Async | CallStyle::Concurrent => "+ Send",
2360            CallStyle::Sync => "",
2361        };
2362
2363        let mut sync_bounds = "Host".to_string();
2364
2365        for ty in required_conversion_traits {
2366            uwrite!(sync_bounds, " + {ty}");
2367        }
2368
2369        let options_param = if self.generator.interface_link_options[&id].has_any() {
2370            "options: &LinkOptions,"
2371        } else {
2372            ""
2373        };
2374
2375        let d_bound = if generated_trait.any_concurrent {
2376            "HostConcurrent".to_string()
2377        } else {
2378            format!("{wt}::component::HasData")
2379        };
2380        uwriteln!(
2381            self.src,
2382            "
2383                pub fn add_to_linker<T, D>(
2384                    linker: &mut {wt}::component::Linker<T>,
2385                    {options_param}
2386                    host_getter: fn(&mut T) -> D::Data<'_>,
2387                ) -> {wt}::Result<()>
2388                    where
2389                        D: {d_bound},
2390                        for<'a> D::Data<'a>: {sync_bounds},
2391                        T: 'static {opt_t_send_bound},
2392                {{
2393            "
2394        );
2395
2396        let gate = FeatureGate::open(&mut self.src, &iface.stability);
2397        uwriteln!(self.src, "let mut inst = linker.instance(\"{name}\")?;");
2398
2399        for (ty, name) in get_resources(self.resolve, id) {
2400            Wasmtime::generate_add_resource_to_linker(
2401                self.qualifier().as_deref(),
2402                &mut self.src,
2403                &self.generator.opts,
2404                &wt,
2405                "inst",
2406                name,
2407                &self.resolve.types[ty].stability,
2408            );
2409        }
2410
2411        for (_, func) in iface.functions.iter() {
2412            self.generate_add_function_to_linker(owner, func, "inst");
2413        }
2414        gate.close(&mut self.src);
2415        uwriteln!(self.src, "Ok(())");
2416        uwriteln!(self.src, "}}");
2417    }
2418
2419    fn qualifier(&self) -> Option<String> {
2420        self.current_interface
2421            .map(|(_, key, _)| self.resolve.name_world_key(key))
2422    }
2423
2424    fn generate_add_function_to_linker(&mut self, owner: TypeOwner, func: &Function, linker: &str) {
2425        let gate = FeatureGate::open(&mut self.src, &func.stability);
2426        uwrite!(
2427            self.src,
2428            "{linker}.{}(\"{}\", ",
2429            match self.import_call_style(func) {
2430                CallStyle::Sync => "func_wrap",
2431                CallStyle::Async => "func_wrap_async",
2432                CallStyle::Concurrent => "func_wrap_concurrent",
2433            },
2434            func.name
2435        );
2436        self.generate_guest_import_closure(owner, func);
2437        uwriteln!(self.src, ")?;");
2438        gate.close(&mut self.src);
2439    }
2440
2441    fn generate_guest_import_closure(&mut self, owner: TypeOwner, func: &Function) {
2442        // Generate the closure that's passed to a `Linker`, the final piece of
2443        // codegen here.
2444
2445        let style = self.import_call_style(func);
2446
2447        let wt = self.generator.wasmtime_path();
2448        if let CallStyle::Concurrent = style {
2449            uwrite!(
2450                self.src,
2451                "move |caller: &mut {wt}::component::Accessor::<T>, ("
2452            );
2453        } else {
2454            uwrite!(
2455                self.src,
2456                "move |mut caller: {wt}::StoreContextMut<'_, T>, ("
2457            );
2458        }
2459        for (i, _param) in func.params.iter().enumerate() {
2460            uwrite!(self.src, "arg{},", i);
2461        }
2462        self.src.push_str(") : (");
2463
2464        for (_, ty) in func.params.iter() {
2465            // Lift is required to be implied for this type, so we can't use
2466            // a borrowed type:
2467            self.print_ty(ty, TypeMode::Owned);
2468            self.src.push_str(", ");
2469        }
2470        self.src.push_str(")| {\n");
2471
2472        if self.generator.opts.tracing {
2473            if let CallStyle::Async | CallStyle::Concurrent = style {
2474                self.src.push_str("use tracing::Instrument;\n");
2475            }
2476
2477            uwrite!(
2478                self.src,
2479                "
2480                   let span = tracing::span!(
2481                       tracing::Level::TRACE,
2482                       \"wit-bindgen import\",
2483                       module = \"{}\",
2484                       function = \"{}\",
2485                   );
2486               ",
2487                match owner {
2488                    TypeOwner::Interface(id) => self.resolve.interfaces[id]
2489                        .name
2490                        .as_deref()
2491                        .unwrap_or("<no module>"),
2492                    TypeOwner::World(id) => &self.resolve.worlds[id].name,
2493                    TypeOwner::None => "<no owner>",
2494                },
2495                func.name,
2496            );
2497        }
2498
2499        match &style {
2500            CallStyle::Async => {
2501                uwriteln!(
2502                    self.src,
2503                    "{wt}::component::__internal::Box::new(async move {{"
2504                );
2505            }
2506            CallStyle::Concurrent => {
2507                uwriteln!(
2508                    self.src,
2509                    "{wt}::component::__internal::Box::pin(async move {{
2510                        let accessor = &mut unsafe {{ caller.with_data(host_getter) }};
2511                    "
2512                );
2513            }
2514            CallStyle::Sync => {
2515                // Only directly enter the span if the function is sync. Otherwise
2516                // we use tracing::Instrument to ensure that the span is not entered
2517                // across an await point.
2518                if self.generator.opts.tracing {
2519                    self.push_str("let _enter = span.enter();\n");
2520                }
2521            }
2522        }
2523
2524        if self.generator.opts.tracing {
2525            let mut event_fields = func
2526                .params
2527                .iter()
2528                .enumerate()
2529                .map(|(i, (name, ty))| {
2530                    let name = to_rust_ident(&name);
2531                    formatting_for_arg(&name, i, *ty, &self.generator.opts, &self.resolve)
2532                })
2533                .collect::<Vec<String>>();
2534            event_fields.push(format!("\"call\""));
2535            uwrite!(
2536                self.src,
2537                "tracing::event!(tracing::Level::TRACE, {});\n",
2538                event_fields.join(", ")
2539            );
2540        }
2541
2542        if !matches!(style, CallStyle::Concurrent) {
2543            self.src
2544                .push_str("let host = &mut host_getter(caller.data_mut());\n");
2545        }
2546        let func_name = rust_function_name(func);
2547        let host_trait = match func.kind.resource() {
2548            None => match owner {
2549                TypeOwner::World(id) => format!(
2550                    "{}Imports",
2551                    rust::to_rust_upper_camel_case(&self.resolve.worlds[id].name)
2552                ),
2553                _ => "Host".to_string(),
2554            },
2555            Some(id) => {
2556                let resource = self.resolve.types[id]
2557                    .name
2558                    .as_ref()
2559                    .unwrap()
2560                    .to_upper_camel_case();
2561                format!("Host{resource}")
2562            }
2563        };
2564
2565        if let CallStyle::Concurrent = &style {
2566            uwrite!(
2567                self.src,
2568                "let r = <D as {host_trait}Concurrent>::{func_name}(accessor, "
2569            );
2570        } else {
2571            uwrite!(self.src, "let r = {host_trait}::{func_name}(host, ");
2572        }
2573
2574        for (i, _) in func.params.iter().enumerate() {
2575            uwrite!(self.src, "arg{},", i);
2576        }
2577
2578        self.src.push_str(match &style {
2579            CallStyle::Sync => ");\n",
2580            CallStyle::Async | CallStyle::Concurrent => ").await;\n",
2581        });
2582
2583        if self.generator.opts.tracing {
2584            uwrite!(
2585                self.src,
2586                "tracing::event!(tracing::Level::TRACE, {}, \"return\");",
2587                formatting_for_results(func.result, &self.generator.opts, &self.resolve)
2588            );
2589        }
2590
2591        if !self.generator.opts.trappable_imports.can_trap(&func) {
2592            if func.result.is_some() {
2593                uwrite!(self.src, "Ok((r,))\n");
2594            } else {
2595                uwrite!(self.src, "Ok(r)\n");
2596            }
2597        } else if let Some((_, err, _)) = self.special_case_trappable_error(func) {
2598            let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err)];
2599            let err_name = err.name.as_ref().unwrap();
2600            let owner = match err.owner {
2601                TypeOwner::Interface(i) => i,
2602                _ => unimplemented!(),
2603            };
2604            let convert_trait = match self.path_to_interface(owner) {
2605                Some(path) => format!("{path}::Host"),
2606                None => format!("Host"),
2607            };
2608            let convert = format!("{}::convert_{}", convert_trait, err_name.to_snake_case());
2609            uwrite!(
2610                self.src,
2611                "Ok((match r {{
2612                    Ok(a) => Ok(a),
2613                    Err(e) => Err({convert}(host, e)?),
2614                }},))"
2615            );
2616        } else if func.result.is_some() {
2617            uwrite!(self.src, "Ok((r?,))\n");
2618        } else {
2619            uwrite!(self.src, "r\n");
2620        }
2621
2622        match &style {
2623            CallStyle::Sync => (),
2624            CallStyle::Async | CallStyle::Concurrent => {
2625                if self.generator.opts.tracing {
2626                    self.src.push_str("}.instrument(span))\n");
2627                } else {
2628                    self.src.push_str("})\n");
2629                }
2630            }
2631        }
2632
2633        self.src.push_str("}\n");
2634    }
2635
2636    fn generate_function_trait_sig(&mut self, func: &Function, async_sugar: bool) {
2637        let wt = self.generator.wasmtime_path();
2638        self.rustdoc(&func.docs);
2639
2640        let style = self.import_call_style(func);
2641        if let (CallStyle::Async, _) | (CallStyle::Concurrent, true) = (&style, async_sugar) {
2642            self.push_str("async ");
2643        }
2644        self.push_str("fn ");
2645        self.push_str(&rust_function_name(func));
2646        self.push_str(&if let CallStyle::Concurrent = &style {
2647            format!("<T: 'static>(accessor: &mut {wt}::component::Accessor<T, Self>, ")
2648        } else {
2649            "(&mut self, ".to_string()
2650        });
2651        self.generate_function_params(func);
2652        self.push_str(")");
2653        self.push_str(" -> ");
2654
2655        if let (CallStyle::Concurrent, false) = (&style, async_sugar) {
2656            uwrite!(self.src, "impl ::core::future::Future<Output = ");
2657        }
2658
2659        self.generate_function_result(func);
2660
2661        if let CallStyle::Concurrent = style {
2662            if !async_sugar {
2663                self.push_str("> + Send where Self: Sized,");
2664            }
2665        }
2666    }
2667
2668    fn generate_function_params(&mut self, func: &Function) {
2669        for (name, param) in func.params.iter() {
2670            let name = to_rust_ident(name);
2671            self.push_str(&name);
2672            self.push_str(": ");
2673            self.print_ty(param, TypeMode::Owned);
2674            self.push_str(",");
2675        }
2676    }
2677
2678    fn generate_function_result(&mut self, func: &Function) {
2679        if !self.generator.opts.trappable_imports.can_trap(func) {
2680            self.print_result_ty(func.result, TypeMode::Owned);
2681        } else if let Some((r, _id, error_typename)) = self.special_case_trappable_error(func) {
2682            // Functions which have a single result `result<ok,err>` get special
2683            // cased to use the host_wasmtime_rust::Error<err>, making it possible
2684            // for them to trap or use `?` to propagate their errors
2685            self.push_str("Result<");
2686            if let Some(ok) = r.ok {
2687                self.print_ty(&ok, TypeMode::Owned);
2688            } else {
2689                self.push_str("()");
2690            }
2691            self.push_str(",");
2692            self.push_str(&error_typename);
2693            self.push_str(">");
2694        } else {
2695            // All other functions get their return values wrapped in an wasmtime::Result.
2696            // Returning the anyhow::Error case can be used to trap.
2697            let wt = self.generator.wasmtime_path();
2698            uwrite!(self.src, "{wt}::Result<");
2699            self.print_result_ty(func.result, TypeMode::Owned);
2700            self.push_str(">");
2701        }
2702    }
2703
2704    fn extract_typed_function(&mut self, func: &Function) -> (String, String) {
2705        let snake = func_field_name(self.resolve, func);
2706        let sig = self.typedfunc_sig(func, TypeMode::AllBorrowed("'_"));
2707        let extract =
2708            format!("*_instance.get_typed_func::<{sig}>(&mut store, &self.{snake})?.func()");
2709        (snake, extract)
2710    }
2711
2712    fn define_rust_guest_export(
2713        &mut self,
2714        resolve: &Resolve,
2715        ns: Option<&WorldKey>,
2716        func: &Function,
2717    ) {
2718        // Exports must be async if anything could be async, it's just imports
2719        // that get to be optionally async/sync.
2720        let style = self.generator.opts.call_style();
2721        let (async_, async__, await_, concurrent) = match &style {
2722            CallStyle::Async | CallStyle::Concurrent => {
2723                if self.generator.opts.concurrent_exports {
2724                    ("", "INVALID", "INVALID", true)
2725                } else {
2726                    ("async", "_async", ".await", false)
2727                }
2728            }
2729            CallStyle::Sync => ("", "", "", false),
2730        };
2731
2732        self.rustdoc(&func.docs);
2733        let wt = self.generator.wasmtime_path();
2734
2735        uwrite!(
2736            self.src,
2737            "pub {async_} fn call_{}<S: {wt}::AsContextMut>(&self, mut store: S, ",
2738            func.item_name().to_snake_case(),
2739        );
2740
2741        let param_mode = if let CallStyle::Concurrent = &style {
2742            TypeMode::Owned
2743        } else {
2744            TypeMode::AllBorrowed("'_")
2745        };
2746
2747        for (i, param) in func.params.iter().enumerate() {
2748            uwrite!(self.src, "arg{}: ", i);
2749            self.print_ty(&param.1, param_mode);
2750            self.push_str(",");
2751        }
2752
2753        if concurrent {
2754            uwrite!(
2755                self.src,
2756                ") -> impl {wt}::component::__internal::Future<Output = {wt}::Result<"
2757            );
2758        } else {
2759            uwrite!(self.src, ") -> {wt}::Result<");
2760        }
2761        self.print_result_ty(func.result, TypeMode::Owned);
2762        if concurrent {
2763            uwrite!(self.src, ">> + Send + 'static + use<S>");
2764        } else {
2765            uwrite!(self.src, ">");
2766        }
2767
2768        match style {
2769            CallStyle::Concurrent => {
2770                uwrite!(
2771                    self.src,
2772                    " where <S as {wt}::AsContext>::Data: Send + 'static",
2773                );
2774            }
2775            CallStyle::Async => {
2776                uwrite!(self.src, " where <S as {wt}::AsContext>::Data: Send");
2777            }
2778            CallStyle::Sync => {}
2779        }
2780        uwrite!(self.src, "{{\n");
2781
2782        // TODO: support tracing concurrent calls
2783        if self.generator.opts.tracing && !concurrent {
2784            if let CallStyle::Async | CallStyle::Concurrent = &style {
2785                self.src.push_str("use tracing::Instrument;\n");
2786            }
2787
2788            let ns = match ns {
2789                Some(key) => resolve.name_world_key(key),
2790                None => "default".to_string(),
2791            };
2792            self.src.push_str(&format!(
2793                "
2794                   let span = tracing::span!(
2795                       tracing::Level::TRACE,
2796                       \"wit-bindgen export\",
2797                       module = \"{ns}\",
2798                       function = \"{}\",
2799                   );
2800               ",
2801                func.name,
2802            ));
2803
2804            if !matches!(&style, CallStyle::Async | CallStyle::Concurrent) {
2805                self.src.push_str(
2806                    "
2807                   let _enter = span.enter();
2808                   ",
2809                );
2810            }
2811        }
2812
2813        self.src.push_str("let callee = unsafe {\n");
2814        uwrite!(
2815            self.src,
2816            "{wt}::component::TypedFunc::<{}>",
2817            self.typedfunc_sig(func, param_mode)
2818        );
2819        let projection_to_func = if func.kind.resource().is_some() {
2820            ".funcs"
2821        } else {
2822            ""
2823        };
2824        uwriteln!(
2825            self.src,
2826            "::new_unchecked(self{projection_to_func}.{})",
2827            func_field_name(self.resolve, func),
2828        );
2829        self.src.push_str("};\n");
2830
2831        if concurrent {
2832            if func.result.is_some() {
2833                uwrite!(self.src, "{wt}::component::__internal::FutureExt::map(");
2834            }
2835            uwrite!(self.src, "callee.call_concurrent(store.as_context_mut(), (");
2836            for (i, _) in func.params.iter().enumerate() {
2837                uwrite!(self.src, "arg{i}, ");
2838            }
2839            self.src.push_str("))");
2840
2841            if func.result.is_some() {
2842                self.src.push_str(", |v| v.map(|(v,)| v))");
2843            }
2844        } else {
2845            self.src.push_str("let (");
2846            if func.result.is_some() {
2847                uwrite!(self.src, "ret0,");
2848            }
2849            uwrite!(
2850                self.src,
2851                ") = callee.call{async__}(store.as_context_mut(), ("
2852            );
2853            for (i, _) in func.params.iter().enumerate() {
2854                uwrite!(self.src, "arg{}, ", i);
2855            }
2856
2857            let instrument = if matches!(&style, CallStyle::Async | CallStyle::Concurrent)
2858                && self.generator.opts.tracing
2859            {
2860                ".instrument(span.clone())"
2861            } else {
2862                ""
2863            };
2864            uwriteln!(self.src, ")){instrument}{await_}?;");
2865
2866            let instrument = if matches!(&style, CallStyle::Async | CallStyle::Concurrent)
2867                && self.generator.opts.tracing
2868            {
2869                ".instrument(span)"
2870            } else {
2871                ""
2872            };
2873
2874            uwriteln!(
2875                self.src,
2876                "callee.post_return{async__}(store.as_context_mut()){instrument}{await_}?;"
2877            );
2878
2879            self.src.push_str("Ok(");
2880            if func.result.is_some() {
2881                self.src.push_str("ret0");
2882            } else {
2883                self.src.push_str("()");
2884            }
2885            self.src.push_str(")\n");
2886        }
2887
2888        // End function body
2889        self.src.push_str("}\n");
2890    }
2891
2892    fn rustdoc(&mut self, docs: &Docs) {
2893        let docs = match &docs.contents {
2894            Some(docs) => docs,
2895            None => return,
2896        };
2897        for line in docs.trim().lines() {
2898            self.push_str("/// ");
2899            self.push_str(line);
2900            self.push_str("\n");
2901        }
2902    }
2903
2904    fn path_to_root(&self) -> String {
2905        let mut path_to_root = String::new();
2906        if let Some((_, key, is_export)) = self.current_interface {
2907            match key {
2908                WorldKey::Name(_) => {
2909                    path_to_root.push_str("super::");
2910                }
2911                WorldKey::Interface(_) => {
2912                    path_to_root.push_str("super::super::super::");
2913                }
2914            }
2915            if is_export {
2916                path_to_root.push_str("super::");
2917            }
2918        }
2919        path_to_root
2920    }
2921
2922    fn import_call_style(&self, func: &Function) -> CallStyle {
2923        self.generator
2924            .opts
2925            .import_call_style(self.qualifier().as_deref(), &func.name)
2926    }
2927
2928    fn partition_concurrent_funcs<'b>(
2929        &self,
2930        funcs: impl IntoIterator<Item = &'b Function>,
2931    ) -> FunctionPartitioning<'b> {
2932        let (concurrent, sync) =
2933            funcs
2934                .into_iter()
2935                .partition(|func| match self.import_call_style(func) {
2936                    CallStyle::Concurrent => true,
2937                    CallStyle::Async | CallStyle::Sync => false,
2938                });
2939        FunctionPartitioning { concurrent, sync }
2940    }
2941
2942    fn generate_trait(
2943        &mut self,
2944        trait_name: &str,
2945        functions: &[&Function],
2946        extra_functions: &[ExtraTraitMethod<'_>],
2947        resources: &[(TypeId, &str)],
2948    ) -> GeneratedTrait {
2949        let mut ret = GeneratedTrait::default();
2950        let wt = self.generator.wasmtime_path();
2951        let is_maybe_async = matches!(
2952            self.generator.opts.call_style(),
2953            CallStyle::Async | CallStyle::Concurrent
2954        );
2955        let partition = self.partition_concurrent_funcs(functions.iter().copied());
2956        ret.any_concurrent = !partition.concurrent.is_empty();
2957
2958        let mut concurrent_supertraits = vec![format!("{wt}::component::HasData")];
2959        let mut sync_supertraits = vec![];
2960        if is_maybe_async {
2961            concurrent_supertraits.push("Send".to_string());
2962            sync_supertraits.push("Send".to_string());
2963        }
2964        for (id, name) in resources {
2965            let camel = name.to_upper_camel_case();
2966            sync_supertraits.push(format!("Host{camel}"));
2967            let funcs = self.partition_concurrent_funcs(get_resource_functions(self.resolve, *id));
2968            if !funcs.concurrent.is_empty() {
2969                ret.any_concurrent = true;
2970                concurrent_supertraits.push(format!("Host{camel}Concurrent"));
2971            }
2972        }
2973
2974        if ret.any_concurrent {
2975            uwriteln!(
2976                self.src,
2977                "#[{wt}::component::__internal::trait_variant_make(::core::marker::Send)]",
2978            );
2979            uwriteln!(
2980                self.src,
2981                "pub trait {trait_name}Concurrent: {} {{",
2982                concurrent_supertraits.join(" + "),
2983            );
2984            ret.concurrent_name = Some(format!("{trait_name}Concurrent"));
2985            for func in partition.concurrent.iter() {
2986                self.generate_function_trait_sig(func, false);
2987                self.push_str(";\n");
2988            }
2989            uwriteln!(self.src, "}}");
2990        }
2991
2992        if is_maybe_async {
2993            uwriteln!(
2994                self.src,
2995                "#[{wt}::component::__internal::trait_variant_make(::core::marker::Send)]",
2996            );
2997        }
2998        uwriteln!(
2999            self.src,
3000            "pub trait {trait_name}: {} {{",
3001            sync_supertraits.join(" + ")
3002        );
3003        ret.name = trait_name.to_string();
3004        for func in partition.sync.iter() {
3005            self.generate_function_trait_sig(func, false);
3006            self.push_str(";\n");
3007        }
3008
3009        for extra in extra_functions {
3010            match extra {
3011                ExtraTraitMethod::ResourceDrop { name } => {
3012                    let camel = name.to_upper_camel_case();
3013                    if let CallStyle::Async | CallStyle::Concurrent = self
3014                        .generator
3015                        .opts
3016                        .drop_call_style(self.qualifier().as_deref(), name)
3017                    {
3018                        uwrite!(self.src, "async ");
3019                    }
3020                    uwrite!(
3021                        self.src,
3022                        "fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()>;"
3023                    );
3024                }
3025                ExtraTraitMethod::ErrorConvert { name, id } => {
3026                    let root = self.path_to_root();
3027                    let custom_name = &self.generator.trappable_errors[id];
3028                    let snake = name.to_snake_case();
3029                    let camel = name.to_upper_camel_case();
3030                    uwriteln!(
3031                        self.src,
3032                        "
3033fn convert_{snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{camel}>;
3034                        "
3035                    );
3036                }
3037            }
3038        }
3039
3040        uwriteln!(self.src, "}}");
3041
3042        if self.generator.opts.skip_mut_forwarding_impls {
3043            return ret;
3044        }
3045
3046        // Generate impl HostResource for &mut HostResource
3047        let maybe_send = if is_maybe_async { "+ Send" } else { "" };
3048        uwriteln!(
3049            self.src,
3050            "impl <_T: {trait_name} + ?Sized {maybe_send}> {trait_name} for &mut _T {{"
3051        );
3052        for func in partition.sync.iter() {
3053            let call_style = self.import_call_style(func);
3054            self.generate_function_trait_sig(func, true);
3055            uwrite!(
3056                self.src,
3057                "{{ {trait_name}::{}(*self,",
3058                rust_function_name(func)
3059            );
3060            for (name, _) in func.params.iter() {
3061                uwrite!(self.src, "{},", to_rust_ident(name));
3062            }
3063            uwrite!(self.src, ")");
3064            if let CallStyle::Async = &call_style {
3065                uwrite!(self.src, ".await");
3066            }
3067            uwriteln!(self.src, "}}");
3068        }
3069        for extra in extra_functions {
3070            match extra {
3071                ExtraTraitMethod::ResourceDrop { name } => {
3072                    let camel = name.to_upper_camel_case();
3073                    let mut await_ = "";
3074                    if let CallStyle::Async | CallStyle::Concurrent = self
3075                        .generator
3076                        .opts
3077                        .drop_call_style(self.qualifier().as_deref(), name)
3078                    {
3079                        self.src.push_str("async ");
3080                        await_ = ".await";
3081                    }
3082                    uwriteln!(
3083                        self.src,
3084                        "
3085fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()> {{
3086    {trait_name}::drop(*self, rep){await_}
3087}}
3088                        ",
3089                    );
3090                }
3091                ExtraTraitMethod::ErrorConvert { name, id } => {
3092                    let root = self.path_to_root();
3093                    let custom_name = &self.generator.trappable_errors[id];
3094                    let snake = name.to_snake_case();
3095                    let camel = name.to_upper_camel_case();
3096                    uwriteln!(
3097                        self.src,
3098                        "
3099fn convert_{snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{camel}> {{
3100    {trait_name}::convert_{snake}(*self, err)
3101}}
3102                        ",
3103                    );
3104                }
3105            }
3106        }
3107        uwriteln!(self.src, "}}");
3108
3109        ret
3110    }
3111}
3112
3113enum ExtraTraitMethod<'a> {
3114    ResourceDrop { name: &'a str },
3115    ErrorConvert { name: &'a str, id: TypeId },
3116}
3117
3118struct FunctionPartitioning<'a> {
3119    sync: Vec<&'a Function>,
3120    concurrent: Vec<&'a Function>,
3121}
3122
3123#[derive(Default)]
3124struct GeneratedTrait {
3125    name: String,
3126    concurrent_name: Option<String>,
3127    any_concurrent: bool,
3128}
3129
3130impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
3131    fn resolve(&self) -> &'a Resolve {
3132        self.resolve
3133    }
3134
3135    fn ownership(&self) -> Ownership {
3136        self.generator.opts.ownership
3137    }
3138
3139    fn path_to_interface(&self, interface: InterfaceId) -> Option<String> {
3140        if let Some((cur, _, _)) = self.current_interface {
3141            if cur == interface {
3142                return None;
3143            }
3144        }
3145        let mut path_to_root = self.path_to_root();
3146        match &self.generator.interface_names[&interface] {
3147            InterfaceName::Remapped { name_at_root, .. } => path_to_root.push_str(name_at_root),
3148            InterfaceName::Path(path) => {
3149                for (i, name) in path.iter().enumerate() {
3150                    if i > 0 {
3151                        path_to_root.push_str("::");
3152                    }
3153                    path_to_root.push_str(name);
3154                }
3155            }
3156        }
3157        Some(path_to_root)
3158    }
3159
3160    fn push_str(&mut self, s: &str) {
3161        self.src.push_str(s);
3162    }
3163
3164    fn info(&self, ty: TypeId) -> TypeInfo {
3165        self.generator.types.get(ty)
3166    }
3167
3168    fn is_imported_interface(&self, interface: InterfaceId) -> bool {
3169        self.generator.interface_last_seen_as_import[&interface]
3170    }
3171
3172    fn wasmtime_path(&self) -> String {
3173        self.generator.wasmtime_path()
3174    }
3175}
3176
3177#[derive(Default)]
3178struct LinkOptionsBuilder {
3179    unstable_features: BTreeSet<String>,
3180}
3181impl LinkOptionsBuilder {
3182    fn has_any(&self) -> bool {
3183        !self.unstable_features.is_empty()
3184    }
3185    fn add_world(&mut self, resolve: &Resolve, id: &WorldId) {
3186        let world = &resolve.worlds[*id];
3187
3188        self.add_stability(&world.stability);
3189
3190        for (_, import) in world.imports.iter() {
3191            match import {
3192                WorldItem::Interface { id, stability } => {
3193                    self.add_stability(stability);
3194                    self.add_interface(resolve, id);
3195                }
3196                WorldItem::Function(f) => {
3197                    self.add_stability(&f.stability);
3198                }
3199                WorldItem::Type(t) => {
3200                    self.add_type(resolve, t);
3201                }
3202            }
3203        }
3204    }
3205    fn add_interface(&mut self, resolve: &Resolve, id: &InterfaceId) {
3206        let interface = &resolve.interfaces[*id];
3207
3208        self.add_stability(&interface.stability);
3209
3210        for (_, t) in interface.types.iter() {
3211            self.add_type(resolve, t);
3212        }
3213        for (_, f) in interface.functions.iter() {
3214            self.add_stability(&f.stability);
3215        }
3216    }
3217    fn add_type(&mut self, resolve: &Resolve, id: &TypeId) {
3218        let t = &resolve.types[*id];
3219        self.add_stability(&t.stability);
3220    }
3221    fn add_stability(&mut self, stability: &Stability) {
3222        match stability {
3223            Stability::Unstable { feature, .. } => {
3224                self.unstable_features.insert(feature.clone());
3225            }
3226            Stability::Stable { .. } | Stability::Unknown => {}
3227        }
3228    }
3229    fn write_struct(&self, src: &mut Source) {
3230        if !self.has_any() {
3231            return;
3232        }
3233
3234        let mut unstable_features = self.unstable_features.iter().cloned().collect::<Vec<_>>();
3235        unstable_features.sort();
3236
3237        uwriteln!(
3238            src,
3239            "
3240            /// Link-time configurations.
3241            #[derive(Clone, Debug, Default)]
3242            pub struct LinkOptions {{
3243            "
3244        );
3245
3246        for feature in unstable_features.iter() {
3247            let feature_rust_name = feature.to_snake_case();
3248            uwriteln!(src, "{feature_rust_name}: bool,");
3249        }
3250
3251        uwriteln!(src, "}}");
3252        uwriteln!(src, "impl LinkOptions {{");
3253
3254        for feature in unstable_features.iter() {
3255            let feature_rust_name = feature.to_snake_case();
3256            uwriteln!(
3257                src,
3258                "
3259                /// Enable members marked as `@unstable(feature = {feature})`
3260                pub fn {feature_rust_name}(&mut self, enabled: bool) -> &mut Self {{
3261                    self.{feature_rust_name} = enabled;
3262                    self
3263                }}
3264            "
3265            );
3266        }
3267
3268        uwriteln!(src, "}}");
3269    }
3270    fn write_impl_from_world(&self, src: &mut Source, path: &str) {
3271        if !self.has_any() {
3272            return;
3273        }
3274
3275        let mut unstable_features = self.unstable_features.iter().cloned().collect::<Vec<_>>();
3276        unstable_features.sort();
3277
3278        uwriteln!(
3279            src,
3280            "
3281            impl core::convert::From<LinkOptions> for {path}::LinkOptions {{
3282                fn from(src: LinkOptions) -> Self {{
3283                    (&src).into()
3284                }}
3285            }}
3286
3287            impl core::convert::From<&LinkOptions> for {path}::LinkOptions {{
3288                fn from(src: &LinkOptions) -> Self {{
3289                    let mut dest = Self::default();
3290        "
3291        );
3292
3293        for feature in unstable_features.iter() {
3294            let feature_rust_name = feature.to_snake_case();
3295            uwriteln!(src, "dest.{feature_rust_name}(src.{feature_rust_name});");
3296        }
3297
3298        uwriteln!(
3299            src,
3300            "
3301                    dest
3302                }}
3303            }}
3304        "
3305        );
3306    }
3307}
3308
3309struct FeatureGate {
3310    close: bool,
3311}
3312impl FeatureGate {
3313    fn open(src: &mut Source, stability: &Stability) -> FeatureGate {
3314        let close = if let Stability::Unstable { feature, .. } = stability {
3315            let feature_rust_name = feature.to_snake_case();
3316            uwrite!(src, "if options.{feature_rust_name} {{");
3317            true
3318        } else {
3319            false
3320        };
3321        Self { close }
3322    }
3323
3324    fn close(self, src: &mut Source) {
3325        if self.close {
3326            uwriteln!(src, "}}");
3327        }
3328    }
3329}
3330
3331/// Produce a string for tracing a function argument.
3332fn formatting_for_arg(
3333    name: &str,
3334    index: usize,
3335    ty: Type,
3336    opts: &Opts,
3337    resolve: &Resolve,
3338) -> String {
3339    if !opts.verbose_tracing && type_contains_lists(ty, resolve) {
3340        return format!("{name} = tracing::field::debug(\"...\")");
3341    }
3342
3343    // Normal tracing.
3344    format!("{name} = tracing::field::debug(&arg{index})")
3345}
3346
3347/// Produce a string for tracing function results.
3348fn formatting_for_results(result: Option<Type>, opts: &Opts, resolve: &Resolve) -> String {
3349    let contains_lists = match result {
3350        Some(ty) => type_contains_lists(ty, resolve),
3351        None => false,
3352    };
3353
3354    if !opts.verbose_tracing && contains_lists {
3355        return format!("result = tracing::field::debug(\"...\")");
3356    }
3357
3358    // Normal tracing.
3359    format!("result = tracing::field::debug(&r)")
3360}
3361
3362/// Test whether the given type contains lists.
3363///
3364/// Here, a `string` is not considered a list.
3365fn type_contains_lists(ty: Type, resolve: &Resolve) -> bool {
3366    match ty {
3367        Type::Id(id) => match &resolve.types[id].kind {
3368            TypeDefKind::Resource
3369            | TypeDefKind::Unknown
3370            | TypeDefKind::Flags(_)
3371            | TypeDefKind::Handle(_)
3372            | TypeDefKind::Enum(_)
3373            | TypeDefKind::Stream(_)
3374            | TypeDefKind::Future(_) => false,
3375            TypeDefKind::Option(ty) => type_contains_lists(*ty, resolve),
3376            TypeDefKind::Result(Result_ { ok, err }) => {
3377                option_type_contains_lists(*ok, resolve)
3378                    || option_type_contains_lists(*err, resolve)
3379            }
3380            TypeDefKind::Record(record) => record
3381                .fields
3382                .iter()
3383                .any(|field| type_contains_lists(field.ty, resolve)),
3384            TypeDefKind::Tuple(tuple) => tuple
3385                .types
3386                .iter()
3387                .any(|ty| type_contains_lists(*ty, resolve)),
3388            TypeDefKind::Variant(variant) => variant
3389                .cases
3390                .iter()
3391                .any(|case| option_type_contains_lists(case.ty, resolve)),
3392            TypeDefKind::Type(ty) => type_contains_lists(*ty, resolve),
3393            TypeDefKind::List(_) => true,
3394            TypeDefKind::FixedSizeList(..) => todo!(),
3395        },
3396
3397        // Technically strings are lists too, but we ignore that here because
3398        // they're usually short.
3399        _ => false,
3400    }
3401}
3402
3403fn option_type_contains_lists(ty: Option<Type>, resolve: &Resolve) -> bool {
3404    match ty {
3405        Some(ty) => type_contains_lists(ty, resolve),
3406        None => false,
3407    }
3408}
3409
3410/// When an interface `use`s a type from another interface, it creates a new TypeId
3411/// referring to the definition TypeId. Chase this chain of references down to
3412/// a TypeId for type's definition.
3413fn resolve_type_definition_id(resolve: &Resolve, mut id: TypeId) -> TypeId {
3414    loop {
3415        match resolve.types[id].kind {
3416            TypeDefKind::Type(Type::Id(def_id)) => id = def_id,
3417            _ => return id,
3418        }
3419    }
3420}
3421
3422fn rust_function_name(func: &Function) -> String {
3423    match func.kind {
3424        FunctionKind::Constructor(_) => "new".to_string(),
3425        FunctionKind::Method(_)
3426        | FunctionKind::Static(_)
3427        | FunctionKind::AsyncMethod(_)
3428        | FunctionKind::AsyncStatic(_)
3429        | FunctionKind::Freestanding
3430        | FunctionKind::AsyncFreestanding => to_rust_ident(func.item_name()),
3431    }
3432}
3433
3434fn func_field_name(resolve: &Resolve, func: &Function) -> String {
3435    let mut name = String::new();
3436    match func.kind {
3437        FunctionKind::Method(id) | FunctionKind::AsyncMethod(id) => {
3438            name.push_str("method-");
3439            name.push_str(resolve.types[id].name.as_ref().unwrap());
3440            name.push_str("-");
3441        }
3442        FunctionKind::Static(id) | FunctionKind::AsyncStatic(id) => {
3443            name.push_str("static-");
3444            name.push_str(resolve.types[id].name.as_ref().unwrap());
3445            name.push_str("-");
3446        }
3447        FunctionKind::Constructor(id) => {
3448            name.push_str("constructor-");
3449            name.push_str(resolve.types[id].name.as_ref().unwrap());
3450            name.push_str("-");
3451        }
3452        FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {}
3453    }
3454    name.push_str(func.item_name());
3455    name.to_snake_case()
3456}
3457
3458fn get_resources<'a>(
3459    resolve: &'a Resolve,
3460    id: InterfaceId,
3461) -> impl Iterator<Item = (TypeId, &'a str)> + 'a {
3462    resolve.interfaces[id]
3463        .types
3464        .iter()
3465        .filter_map(move |(name, ty)| match &resolve.types[*ty].kind {
3466            TypeDefKind::Resource => Some((*ty, name.as_str())),
3467            _ => None,
3468        })
3469}
3470
3471fn get_resource_functions<'a>(resolve: &'a Resolve, resource_id: TypeId) -> Vec<&'a Function> {
3472    let resource = &resolve.types[resource_id];
3473    match resource.owner {
3474        TypeOwner::World(id) => resolve.worlds[id]
3475            .imports
3476            .values()
3477            .filter_map(|item| match item {
3478                WorldItem::Function(f) => Some(f),
3479                _ => None,
3480            })
3481            .filter(|f| f.kind.resource() == Some(resource_id))
3482            .collect(),
3483        TypeOwner::Interface(id) => resolve.interfaces[id]
3484            .functions
3485            .values()
3486            .filter(|f| f.kind.resource() == Some(resource_id))
3487            .collect::<Vec<_>>(),
3488        TypeOwner::None => {
3489            panic!("A resource must be owned by a world or interface");
3490        }
3491    }
3492}
3493
3494fn get_world_resources<'a>(
3495    resolve: &'a Resolve,
3496    id: WorldId,
3497) -> impl Iterator<Item = (TypeId, &'a str)> + 'a {
3498    resolve.worlds[id]
3499        .imports
3500        .iter()
3501        .filter_map(move |(name, item)| match item {
3502            WorldItem::Type(id) => match resolve.types[*id].kind {
3503                TypeDefKind::Resource => Some(match name {
3504                    WorldKey::Name(s) => (*id, s.as_str()),
3505                    WorldKey::Interface(_) => unreachable!(),
3506                }),
3507                _ => None,
3508            },
3509            _ => None,
3510        })
3511}