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