Skip to main content

wasmtime_internal_wit_bindgen/
lib.rs

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