wasmtime_wit_bindgen/
lib.rs

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