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