wasmtime_wit_bindgen/
lib.rs

1use crate::rust::{to_rust_ident, to_rust_upper_camel_case, RustGenerator, TypeMode};
2use crate::types::{TypeInfo, Types};
3use anyhow::bail;
4use heck::*;
5use indexmap::{IndexMap, IndexSet};
6use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
7use std::fmt::Write as _;
8use std::io::{Read, Write};
9use std::mem;
10use std::process::{Command, Stdio};
11use wit_parser::*;
12
13macro_rules! uwrite {
14    ($dst:expr, $($arg:tt)*) => {
15        write!($dst, $($arg)*).unwrap()
16    };
17}
18
19macro_rules! uwriteln {
20    ($dst:expr, $($arg:tt)*) => {
21        writeln!($dst, $($arg)*).unwrap()
22    };
23}
24
25mod rust;
26mod source;
27mod types;
28use source::Source;
29
30#[derive(Clone)]
31enum InterfaceName {
32    /// This interface was remapped using `with` to some other Rust code.
33    Remapped {
34        /// This is the `::`-separated string which is the path to the mapped
35        /// item relative to the root of the `bindgen!` macro invocation.
36        ///
37        /// This path currently starts with `__with_name$N` and will then
38        /// optionally have `::` projections through to the actual item
39        /// depending on how `with` was configured.
40        name_at_root: String,
41
42        /// This is currently only used for exports and is the relative path to
43        /// where this mapped name would be located if `with` were not
44        /// specified. Basically it's the same as the `Path` variant of this
45        /// enum if the mapping weren't present.
46        local_path: Vec<String>,
47    },
48
49    /// This interface is generated in the module hierarchy specified.
50    ///
51    /// The path listed here is the path, from the root of the `bindgen!` macro,
52    /// to where this interface is generated.
53    Path(Vec<String>),
54}
55
56#[derive(Default)]
57struct Wasmtime {
58    src: Source,
59    opts: Opts,
60    /// A list of all interfaces which were imported by this world.
61    ///
62    /// The first value here is the contents of the module that this interface
63    /// generated. The second value is the name of the interface as also present
64    /// in `self.interface_names`.
65    import_interfaces: Vec<(String, InterfaceName)>,
66    import_functions: Vec<ImportFunction>,
67    exports: Exports,
68    types: Types,
69    sizes: SizeAlign,
70    interface_names: HashMap<InterfaceId, InterfaceName>,
71    interface_last_seen_as_import: HashMap<InterfaceId, bool>,
72    trappable_errors: IndexMap<TypeId, String>,
73    // Track the with options that were used. Remapped interfaces provided via `with`
74    // are required to be used.
75    used_with_opts: HashSet<String>,
76    // Track the imports that matched the `trappable_imports` spec.
77    used_trappable_imports_opts: HashSet<String>,
78}
79
80struct ImportFunction {
81    func: Function,
82    add_to_linker: String,
83    sig: Option<String>,
84}
85
86#[derive(Default)]
87struct Exports {
88    fields: BTreeMap<String, ExportField>,
89    modules: Vec<(String, InterfaceName)>,
90    funcs: Vec<String>,
91}
92
93struct ExportField {
94    ty: String,
95    ty_pre: String,
96    getter: String,
97    getter_pre: String,
98}
99
100#[derive(Default, Debug, Clone, Copy)]
101pub enum Ownership {
102    /// Generated types will be composed entirely of owning fields, regardless
103    /// of whether they are used as parameters to guest exports or not.
104    #[default]
105    Owning,
106
107    /// Generated types used as parameters to guest exports will be "deeply
108    /// borrowing", i.e. contain references rather than owned values when
109    /// applicable.
110    Borrowing {
111        /// Whether or not to generate "duplicate" type definitions for a single
112        /// WIT type if necessary, for example if it's used as both an import
113        /// and an export, or if it's used both as a parameter to an export and
114        /// a return value from an export.
115        duplicate_if_necessary: bool,
116    },
117}
118
119#[derive(Default, Debug, Clone)]
120pub struct Opts {
121    /// Whether or not `rustfmt` is executed to format generated code.
122    pub rustfmt: bool,
123
124    /// Whether or not to emit `tracing` macro calls on function entry/exit.
125    pub tracing: bool,
126
127    /// Whether or not to use async rust functions and traits.
128    pub async_: AsyncConfig,
129
130    /// A list of "trappable errors" which are used to replace the `E` in
131    /// `result<T, E>` found in WIT.
132    pub trappable_error_type: Vec<TrappableError>,
133
134    /// Whether to generate owning or borrowing type definitions.
135    pub ownership: Ownership,
136
137    /// Whether or not to generate code for only the interfaces of this wit file or not.
138    pub only_interfaces: bool,
139
140    /// Configuration of which imports are allowed to generate a trap.
141    pub trappable_imports: TrappableImports,
142
143    /// Remapping of interface names to rust module names.
144    /// TODO: is there a better type to use for the value of this map?
145    pub with: HashMap<String, String>,
146
147    /// Additional derive attributes to add to generated types. If using in a CLI, this flag can be
148    /// specified multiple times to add multiple attributes.
149    ///
150    /// These derive attributes will be added to any generated structs or enums
151    pub additional_derive_attributes: Vec<String>,
152
153    /// Evaluate to a string literal containing the generated code rather than the generated tokens
154    /// themselves. Mostly useful for Wasmtime internal debugging and development.
155    pub stringify: bool,
156
157    /// Temporary option to skip `impl<T: Trait> Trait for &mut T` for the
158    /// `wasmtime-wasi` crate while that's given a chance to update its b
159    /// indings.
160    pub skip_mut_forwarding_impls: bool,
161
162    /// Indicates that the `T` in `Store<T>` should be send even if async is not
163    /// enabled.
164    ///
165    /// This is helpful when sync bindings depend on generated functions from
166    /// async bindings as is the case with WASI in-tree.
167    pub require_store_data_send: bool,
168
169    /// Path to the `wasmtime` crate if it's not the default path.
170    pub wasmtime_crate: Option<String>,
171}
172
173#[derive(Debug, Clone)]
174pub struct TrappableError {
175    /// Full path to the error, such as `wasi:io/streams/error`.
176    pub wit_path: String,
177
178    /// The name, in Rust, of the error type to generate.
179    pub rust_type_name: String,
180}
181
182#[derive(Default, Debug, Clone)]
183pub enum AsyncConfig {
184    /// No functions are `async`.
185    #[default]
186    None,
187    /// All generated functions should be `async`.
188    All,
189    /// These imported functions should not be async, but everything else is.
190    AllExceptImports(HashSet<String>),
191    /// These functions are the only imports that are async, all other imports
192    /// are sync.
193    ///
194    /// Note that all exports are still async in this situation.
195    OnlyImports(HashSet<String>),
196}
197
198impl AsyncConfig {
199    pub fn is_import_async(&self, f: &str) -> bool {
200        match self {
201            AsyncConfig::None => false,
202            AsyncConfig::All => true,
203            AsyncConfig::AllExceptImports(set) => !set.contains(f),
204            AsyncConfig::OnlyImports(set) => set.contains(f),
205        }
206    }
207
208    pub fn maybe_async(&self) -> bool {
209        match self {
210            AsyncConfig::None => false,
211            AsyncConfig::All | AsyncConfig::AllExceptImports(_) | AsyncConfig::OnlyImports(_) => {
212                true
213            }
214        }
215    }
216}
217
218#[derive(Default, Debug, Clone)]
219pub enum TrappableImports {
220    /// No imports are allowed to trap.
221    #[default]
222    None,
223    /// All imports may trap.
224    All,
225    /// Only the specified set of functions may trap.
226    Only(HashSet<String>),
227}
228
229impl TrappableImports {
230    fn can_trap(&self, f: &Function) -> bool {
231        match self {
232            TrappableImports::None => false,
233            TrappableImports::All => true,
234            TrappableImports::Only(set) => set.contains(&f.name),
235        }
236    }
237}
238
239impl Opts {
240    pub fn generate(&self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> {
241        let mut r = Wasmtime::default();
242        r.sizes.fill(resolve);
243        r.opts = self.clone();
244        r.generate(resolve, world)
245    }
246
247    fn is_store_data_send(&self) -> bool {
248        self.async_.maybe_async() || self.require_store_data_send
249    }
250}
251
252impl Wasmtime {
253    fn name_interface(
254        &mut self,
255        resolve: &Resolve,
256        id: InterfaceId,
257        name: &WorldKey,
258        is_export: bool,
259    ) -> bool {
260        let mut path = Vec::new();
261        if is_export {
262            path.push("exports".to_string());
263        }
264        match name {
265            WorldKey::Name(name) => {
266                path.push(name.to_snake_case());
267            }
268            WorldKey::Interface(_) => {
269                let iface = &resolve.interfaces[id];
270                let pkgname = &resolve.packages[iface.package.unwrap()].name;
271                path.push(pkgname.namespace.to_snake_case());
272                path.push(self.name_package_module(resolve, iface.package.unwrap()));
273                path.push(to_rust_ident(iface.name.as_ref().unwrap()));
274            }
275        }
276        let entry = if let Some(name_at_root) = self.lookup_replacement(resolve, name, None) {
277            InterfaceName::Remapped {
278                name_at_root,
279                local_path: path,
280            }
281        } else {
282            InterfaceName::Path(path)
283        };
284
285        let remapped = matches!(entry, InterfaceName::Remapped { .. });
286        self.interface_names.insert(id, entry);
287        remapped
288    }
289
290    /// If the package `id` is the only package with its namespace/name combo
291    /// then pass through the name unmodified. If, however, there are multiple
292    /// versions of this package then the package module is going to get version
293    /// information.
294    fn name_package_module(&self, resolve: &Resolve, id: PackageId) -> String {
295        let pkg = &resolve.packages[id];
296        let versions_with_same_name = resolve
297            .packages
298            .iter()
299            .filter_map(|(_, p)| {
300                if p.name.namespace == pkg.name.namespace && p.name.name == pkg.name.name {
301                    Some(&p.name.version)
302                } else {
303                    None
304                }
305            })
306            .collect::<Vec<_>>();
307        let base = pkg.name.name.to_snake_case();
308        if versions_with_same_name.len() == 1 {
309            return base;
310        }
311
312        let version = match &pkg.name.version {
313            Some(version) => version,
314            // If this package didn't have a version then don't mangle its name
315            // and other packages with the same name but with versions present
316            // will have their names mangled.
317            None => return base,
318        };
319
320        // Here there's multiple packages with the same name that differ only in
321        // version, so the version needs to be mangled into the Rust module name
322        // that we're generating. This in theory could look at all of
323        // `versions_with_same_name` and produce a minimal diff, e.g. for 0.1.0
324        // and 0.2.0 this could generate "foo1" and "foo2", but for now
325        // a simpler path is chosen to generate "foo0_1_0" and "foo0_2_0".
326        let version = version
327            .to_string()
328            .replace('.', "_")
329            .replace('-', "_")
330            .replace('+', "_")
331            .to_snake_case();
332        format!("{base}{version}")
333    }
334
335    fn generate(&mut self, resolve: &Resolve, id: WorldId) -> anyhow::Result<String> {
336        self.types.analyze(resolve, id);
337
338        // Resolve the `trappable_error_type` configuration values to `TypeId`
339        // values. This is done by iterating over each `trappable_error_type`
340        // and then locating the interface that it corresponds to as well as the
341        // type within that interface.
342        //
343        // Note that `LookupItem::InterfaceNoPop` is used here as the full
344        // hierarchical behavior of `lookup_keys` isn't used as the interface
345        // must be named here.
346        'outer: for (i, te) in self.opts.trappable_error_type.iter().enumerate() {
347            let error_name = format!("_TrappableError{i}");
348            for (id, iface) in resolve.interfaces.iter() {
349                for (key, projection) in lookup_keys(
350                    resolve,
351                    &WorldKey::Interface(id),
352                    LookupItem::InterfaceNoPop,
353                ) {
354                    assert!(projection.is_empty());
355
356                    // If `wit_path` looks like `{key}/{type_name}` where
357                    // `type_name` is a type within `iface` then we've found a
358                    // match. Otherwise continue to the next lookup key if there
359                    // is one, and failing that continue to the next interface.
360                    let suffix = match te.wit_path.strip_prefix(&key) {
361                        Some(s) => s,
362                        None => continue,
363                    };
364                    let suffix = match suffix.strip_prefix('/') {
365                        Some(s) => s,
366                        None => continue,
367                    };
368                    if let Some(id) = iface.types.get(suffix) {
369                        uwriteln!(self.src, "type {error_name} = {};", te.rust_type_name);
370                        let prev = self.trappable_errors.insert(*id, error_name);
371                        assert!(prev.is_none());
372                        continue 'outer;
373                    }
374                }
375            }
376
377            bail!(
378                "failed to locate a WIT error type corresponding to the \
379                   `trappable_error_type` name `{}` provided",
380                te.wit_path
381            )
382        }
383
384        // Convert all entries in `with` as relative to the root of where the
385        // macro itself is invoked. This emits a `pub use` to bring the name
386        // into scope under an "anonymous name" which then replaces the `with`
387        // map entry.
388        let mut with = self.opts.with.iter_mut().collect::<Vec<_>>();
389        with.sort();
390        for (i, (_k, v)) in with.into_iter().enumerate() {
391            let name = format!("__with_name{i}");
392            uwriteln!(self.src, "#[doc(hidden)]\npub use {v} as {name};");
393            *v = name;
394        }
395
396        let world = &resolve.worlds[id];
397        for (name, import) in world.imports.iter() {
398            if !self.opts.only_interfaces || matches!(import, WorldItem::Interface { .. }) {
399                self.import(resolve, id, name, import);
400            }
401        }
402
403        for (name, export) in world.exports.iter() {
404            if !self.opts.only_interfaces || matches!(export, WorldItem::Interface { .. }) {
405                self.export(resolve, name, export);
406            }
407        }
408        self.finish(resolve, id)
409    }
410
411    fn import(&mut self, resolve: &Resolve, world: WorldId, name: &WorldKey, item: &WorldItem) {
412        let mut gen = InterfaceGenerator::new(self, resolve);
413        match item {
414            WorldItem::Function(func) => {
415                // Only generate a trait signature for free functions since
416                // resource-related functions get their trait signatures
417                // during `type_resource`.
418                let sig = if let FunctionKind::Freestanding = func.kind {
419                    gen.generate_function_trait_sig(func);
420                    Some(mem::take(&mut gen.src).into())
421                } else {
422                    None
423                };
424                gen.generate_add_function_to_linker(TypeOwner::World(world), func, "linker");
425                let add_to_linker = gen.src.into();
426                self.import_functions.push(ImportFunction {
427                    func: func.clone(),
428                    sig,
429                    add_to_linker,
430                });
431            }
432            WorldItem::Interface { id, .. } => {
433                gen.gen.interface_last_seen_as_import.insert(*id, true);
434                gen.current_interface = Some((*id, name, false));
435                let snake = match name {
436                    WorldKey::Name(s) => s.to_snake_case(),
437                    WorldKey::Interface(id) => resolve.interfaces[*id]
438                        .name
439                        .as_ref()
440                        .unwrap()
441                        .to_snake_case(),
442                };
443                let module = if gen.gen.name_interface(resolve, *id, name, false) {
444                    // If this interface is remapped then that means that it was
445                    // provided via the `with` key in the bindgen configuration.
446                    // That means that bindings generation is skipped here. To
447                    // accommodate future bindgens depending on this bindgen
448                    // though we still generate a module which reexports the
449                    // original module. This helps maintain the same output
450                    // structure regardless of whether `with` is used.
451                    let name_at_root = match &gen.gen.interface_names[id] {
452                        InterfaceName::Remapped { name_at_root, .. } => name_at_root,
453                        InterfaceName::Path(_) => unreachable!(),
454                    };
455                    let path_to_root = gen.path_to_root();
456                    format!(
457                        "
458                            pub mod {snake} {{
459                                #[allow(unused_imports)]
460                                pub use {path_to_root}{name_at_root}::*;
461                            }}
462                        "
463                    )
464                } else {
465                    // If this interface is not remapped then it's time to
466                    // actually generate bindings here.
467                    gen.types(*id);
468                    let key_name = resolve.name_world_key(name);
469                    gen.generate_add_to_linker(*id, &key_name);
470
471                    let module = &gen.src[..];
472                    let wt = gen.gen.wasmtime_path();
473
474                    format!(
475                        "
476                            #[allow(clippy::all)]
477                            pub mod {snake} {{
478                                #[allow(unused_imports)]
479                                use {wt}::component::__internal::anyhow;
480
481                                {module}
482                            }}
483                        "
484                    )
485                };
486                self.import_interfaces
487                    .push((module, self.interface_names[id].clone()));
488            }
489            WorldItem::Type(ty) => {
490                let name = match name {
491                    WorldKey::Name(name) => name,
492                    WorldKey::Interface(_) => unreachable!(),
493                };
494                gen.define_type(name, *ty);
495                let body = mem::take(&mut gen.src);
496                self.src.push_str(&body);
497            }
498        };
499    }
500
501    fn export(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) {
502        let wt = self.wasmtime_path();
503        let mut gen = InterfaceGenerator::new(self, resolve);
504        let field;
505        let ty;
506        let ty_pre;
507        let getter;
508        let getter_pre;
509        match item {
510            WorldItem::Function(func) => {
511                gen.define_rust_guest_export(resolve, None, func);
512                let body = mem::take(&mut gen.src).into();
513                getter = gen.extract_typed_function(func).1;
514                assert!(gen.src.is_empty());
515                self.exports.funcs.push(body);
516                ty_pre = format!("{wt}::component::ComponentExportIndex");
517                field = func_field_name(resolve, func);
518                ty = format!("{wt}::component::Func");
519                getter_pre = format!(
520                    "_component.export_index(None, \"{}\")
521                        .ok_or_else(|| anyhow::anyhow!(\"no function export `{0}` found\"))?.1",
522                    func.name
523                );
524            }
525            WorldItem::Type(_) => unreachable!(),
526            WorldItem::Interface { id, .. } => {
527                gen.gen.interface_last_seen_as_import.insert(*id, false);
528                gen.gen.name_interface(resolve, *id, name, true);
529                gen.current_interface = Some((*id, name, true));
530                gen.types(*id);
531                let struct_name = "Guest";
532                let iface = &resolve.interfaces[*id];
533                let iface_name = match name {
534                    WorldKey::Name(name) => name,
535                    WorldKey::Interface(_) => iface.name.as_ref().unwrap(),
536                };
537                uwriteln!(gen.src, "pub struct {struct_name} {{");
538                for (_, func) in iface.functions.iter() {
539                    uwriteln!(
540                        gen.src,
541                        "{}: {wt}::component::Func,",
542                        func_field_name(resolve, func)
543                    );
544                }
545                uwriteln!(gen.src, "}}");
546
547                uwriteln!(gen.src, "#[derive(Clone)]");
548                uwriteln!(gen.src, "pub struct {struct_name}Pre {{");
549                for (_, func) in iface.functions.iter() {
550                    uwriteln!(
551                        gen.src,
552                        "{}: {wt}::component::ComponentExportIndex,",
553                        func_field_name(resolve, func)
554                    );
555                }
556                uwriteln!(gen.src, "}}");
557
558                uwriteln!(gen.src, "impl {struct_name}Pre {{");
559                let instance_name = resolve.name_world_key(name);
560                uwrite!(
561                    gen.src,
562                    "
563pub fn new(
564    component: &{wt}::component::Component,
565) -> {wt}::Result<{struct_name}Pre> {{
566    let _component = component;
567    let (_, instance) = component.export_index(None, \"{instance_name}\")
568        .ok_or_else(|| anyhow::anyhow!(\"no exported instance named `{instance_name}`\"))?;
569    let _lookup = |name: &str| {{
570        _component.export_index(Some(&instance), name)
571            .map(|p| p.1)
572            .ok_or_else(|| {{
573                anyhow::anyhow!(
574                    \"instance export `{instance_name}` does \\
575                      not have export `{{name}}`\"
576                )
577            }})
578    }};
579                    "
580                );
581                let mut fields = Vec::new();
582                for (_, func) in iface.functions.iter() {
583                    let name = func_field_name(resolve, func);
584                    uwriteln!(gen.src, "let {name} = _lookup(\"{}\")?;", func.name);
585                    fields.push(name);
586                }
587                uwriteln!(gen.src, "Ok({struct_name}Pre {{");
588                for name in fields {
589                    uwriteln!(gen.src, "{name},");
590                }
591                uwriteln!(gen.src, "}})");
592                uwriteln!(gen.src, "}}");
593
594                uwrite!(
595                    gen.src,
596                    "
597                        pub fn load(
598                            &self,
599                            mut store: impl {wt}::AsContextMut,
600                            instance: &{wt}::component::Instance,
601                        ) -> {wt}::Result<{struct_name}> {{
602                            let mut store = store.as_context_mut();
603                            let _ = &mut store;
604                            let _instance = instance;
605                    "
606                );
607                let mut fields = Vec::new();
608                for (_, func) in iface.functions.iter() {
609                    let (name, getter) = gen.extract_typed_function(func);
610                    uwriteln!(gen.src, "let {name} = {getter};");
611                    fields.push(name);
612                }
613                uwriteln!(gen.src, "Ok({struct_name} {{");
614                for name in fields {
615                    uwriteln!(gen.src, "{name},");
616                }
617                uwriteln!(gen.src, "}})");
618                uwriteln!(gen.src, "}}"); // end `fn new`
619                uwriteln!(gen.src, "}}"); // end `impl {struct_name}Pre`
620
621                uwriteln!(gen.src, "impl {struct_name} {{");
622                let mut resource_methods = IndexMap::new();
623
624                for (_, func) in iface.functions.iter() {
625                    match func.kind {
626                        FunctionKind::Freestanding => {
627                            gen.define_rust_guest_export(resolve, Some(name), func);
628                        }
629                        FunctionKind::Method(id)
630                        | FunctionKind::Constructor(id)
631                        | FunctionKind::Static(id) => {
632                            resource_methods.entry(id).or_insert(Vec::new()).push(func);
633                        }
634                    }
635                }
636
637                for (id, _) in resource_methods.iter() {
638                    let name = resolve.types[*id].name.as_ref().unwrap();
639                    let snake = name.to_snake_case();
640                    let camel = name.to_upper_camel_case();
641                    uwriteln!(
642                        gen.src,
643                        "pub fn {snake}(&self) -> Guest{camel}<'_> {{
644                            Guest{camel} {{ funcs: self }}
645                        }}"
646                    );
647                }
648
649                uwriteln!(gen.src, "}}");
650
651                for (id, methods) in resource_methods {
652                    let resource_name = resolve.types[id].name.as_ref().unwrap();
653                    let camel = resource_name.to_upper_camel_case();
654                    uwriteln!(gen.src, "impl Guest{camel}<'_> {{");
655                    for method in methods {
656                        gen.define_rust_guest_export(resolve, Some(name), method);
657                    }
658                    uwriteln!(gen.src, "}}");
659                }
660
661                let module = &gen.src[..];
662                let snake = to_rust_ident(iface_name);
663
664                let module = format!(
665                    "
666                        #[allow(clippy::all)]
667                        pub mod {snake} {{
668                            #[allow(unused_imports)]
669                            use {wt}::component::__internal::anyhow;
670
671                            {module}
672                        }}
673                    "
674                );
675                let pkgname = match name {
676                    WorldKey::Name(_) => None,
677                    WorldKey::Interface(_) => {
678                        Some(resolve.packages[iface.package.unwrap()].name.clone())
679                    }
680                };
681                self.exports
682                    .modules
683                    .push((module, self.interface_names[id].clone()));
684
685                let (path, method_name) = match pkgname {
686                    Some(pkgname) => (
687                        format!(
688                            "exports::{}::{}::{snake}::{struct_name}",
689                            pkgname.namespace.to_snake_case(),
690                            self.name_package_module(resolve, iface.package.unwrap()),
691                        ),
692                        format!(
693                            "{}_{}_{snake}",
694                            pkgname.namespace.to_snake_case(),
695                            self.name_package_module(resolve, iface.package.unwrap())
696                        ),
697                    ),
698                    None => (format!("exports::{snake}::{struct_name}"), snake.clone()),
699                };
700                field = format!("interface{}", self.exports.fields.len());
701                getter = format!("self.{field}.load(&mut store, &_instance)?");
702                self.exports.funcs.push(format!(
703                    "
704                        pub fn {method_name}(&self) -> &{path} {{
705                            &self.{field}
706                        }}
707                    ",
708                ));
709                ty_pre = format!("{path}Pre");
710                ty = path;
711                getter_pre = format!("{ty_pre}::new(_component)?");
712            }
713        }
714        let prev = self.exports.fields.insert(
715            field,
716            ExportField {
717                ty,
718                ty_pre,
719                getter,
720                getter_pre,
721            },
722        );
723        assert!(prev.is_none());
724    }
725
726    fn build_world_struct(&mut self, resolve: &Resolve, world: WorldId) {
727        let wt = self.wasmtime_path();
728        let world_name = &resolve.worlds[world].name;
729        let camel = to_rust_upper_camel_case(&world_name);
730        let (async_, async__, where_clause, await_) = if self.opts.async_.maybe_async() {
731            ("async", "_async", "where _T: Send", ".await")
732        } else {
733            ("", "", "", "")
734        };
735        uwriteln!(
736            self.src,
737            "
738            /// Auto-generated bindings for a pre-instantiated version of a
739            /// component which implements the world `{world_name}`.
740            ///
741            /// This structure is created through [`{camel}Pre::new`] which
742            /// takes a [`InstancePre`]({wt}::component::InstancePre) that
743            /// has been created through a [`Linker`]({wt}::component::Linker).
744            pub struct {camel}Pre<T> {{"
745        );
746        uwriteln!(self.src, "instance_pre: {wt}::component::InstancePre<T>,");
747        for (name, field) in self.exports.fields.iter() {
748            uwriteln!(self.src, "{name}: {},", field.ty_pre);
749        }
750        self.src.push_str("}\n");
751
752        uwriteln!(self.src, "impl<T> Clone for {camel}Pre<T> {{");
753        uwriteln!(self.src, "fn clone(&self) -> Self {{");
754        uwriteln!(self.src, "Self {{ instance_pre: self.instance_pre.clone(),");
755        for (name, _field) in self.exports.fields.iter() {
756            uwriteln!(self.src, "{name}: self.{name}.clone(),");
757        }
758        uwriteln!(self.src, "}}"); // `Self ...
759        uwriteln!(self.src, "}}"); // `fn clone`
760        uwriteln!(self.src, "}}"); // `impl Clone`
761
762        uwriteln!(
763            self.src,
764            "
765                /// Auto-generated bindings for an instance a component which
766                /// implements the world `{world_name}`.
767                ///
768                /// This structure is created through either
769                /// [`{camel}::instantiate{async__}`] or by first creating
770                /// a [`{camel}Pre`] followed by using
771                /// [`{camel}Pre::instantiate{async__}`].
772                pub struct {camel} {{"
773        );
774        for (name, field) in self.exports.fields.iter() {
775            uwriteln!(self.src, "{name}: {},", field.ty);
776        }
777        self.src.push_str("}\n");
778
779        self.world_imports_trait(resolve, world);
780
781        uwriteln!(self.src, "const _: () = {{");
782        uwriteln!(
783            self.src,
784            "
785                #[allow(unused_imports)]
786                use {wt}::component::__internal::anyhow;
787            "
788        );
789
790        uwriteln!(
791            self.src,
792            "impl<_T> {camel}Pre<_T> {{
793                /// Creates a new copy of `{camel}Pre` bindings which can then
794                /// be used to instantiate into a particular store.
795                ///
796                /// This method may fail if the component behind `instance_pre`
797                /// does not have the required exports.
798                pub fn new(
799                    instance_pre: {wt}::component::InstancePre<_T>,
800                ) -> {wt}::Result<Self> {{
801                    let _component = instance_pre.component();
802            ",
803        );
804        for (name, field) in self.exports.fields.iter() {
805            uwriteln!(self.src, "let {name} = {};", field.getter_pre);
806        }
807        uwriteln!(self.src, "Ok({camel}Pre {{");
808        uwriteln!(self.src, "instance_pre,");
809        for (name, _) in self.exports.fields.iter() {
810            uwriteln!(self.src, "{name},");
811        }
812        uwriteln!(self.src, "}})");
813        uwriteln!(self.src, "}}"); // close `fn new`
814
815        uwriteln!(
816            self.src,
817            "
818                /// Instantiates a new instance of [`{camel}`] within the
819                /// `store` provided.
820                ///
821                /// This function will use `self` as the pre-instantiated
822                /// instance to perform instantiation. Afterwards the preloaded
823                /// indices in `self` are used to lookup all exports on the
824                /// resulting instance.
825                pub {async_} fn instantiate{async__}(
826                    &self,
827                    mut store: impl {wt}::AsContextMut<Data = _T>,
828                ) -> {wt}::Result<{camel}>
829                    {where_clause}
830                {{
831                    let mut store = store.as_context_mut();
832                    let _instance = self.instance_pre.instantiate{async__}(&mut store){await_}?;
833            ",
834        );
835        for (name, field) in self.exports.fields.iter() {
836            uwriteln!(self.src, "let {name} = {};", field.getter);
837        }
838        uwriteln!(self.src, "Ok({camel} {{");
839        for (name, _) in self.exports.fields.iter() {
840            uwriteln!(self.src, "{name},");
841        }
842        uwriteln!(self.src, "}})");
843        uwriteln!(self.src, "}}"); // close `fn new`
844        uwriteln!(
845            self.src,
846            "
847                pub fn engine(&self) -> &{wt}::Engine {{
848                    self.instance_pre.engine()
849                }}
850
851                pub fn instance_pre(&self) -> &{wt}::component::InstancePre<_T> {{
852                    &self.instance_pre
853                }}
854            ",
855        );
856
857        uwriteln!(self.src, "}}");
858
859        uwriteln!(
860            self.src,
861            "impl {camel} {{
862                /// Convenience wrapper around [`{camel}Pre::new`] and
863                /// [`{camel}Pre::instantiate{async__}`].
864                pub {async_} fn instantiate{async__}<_T>(
865                    mut store: impl {wt}::AsContextMut<Data = _T>,
866                    component: &{wt}::component::Component,
867                    linker: &{wt}::component::Linker<_T>,
868                ) -> {wt}::Result<{camel}>
869                    {where_clause}
870                {{
871                    let pre = linker.instantiate_pre(component)?;
872                    {camel}Pre::new(pre)?.instantiate{async__}(store){await_}
873                }}
874            ",
875        );
876        self.world_add_to_linker(resolve, world);
877
878        for func in self.exports.funcs.iter() {
879            self.src.push_str(func);
880        }
881
882        uwriteln!(self.src, "}}"); // close `impl {camel}`
883
884        uwriteln!(self.src, "}};"); // close `const _: () = ...
885    }
886
887    fn finish(&mut self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> {
888        let remapping_keys = self.opts.with.keys().cloned().collect::<HashSet<String>>();
889
890        let mut unused_keys = remapping_keys
891            .difference(&self.used_with_opts)
892            .map(|s| s.as_str())
893            .collect::<Vec<&str>>();
894
895        unused_keys.sort();
896
897        if !unused_keys.is_empty() {
898            anyhow::bail!("interfaces were specified in the `with` config option but are not referenced in the target world: {unused_keys:?}");
899        }
900
901        if let TrappableImports::Only(only) = &self.opts.trappable_imports {
902            let mut unused_imports = Vec::from_iter(
903                only.difference(&self.used_trappable_imports_opts)
904                    .map(|s| s.as_str()),
905            );
906
907            if !unused_imports.is_empty() {
908                unused_imports.sort();
909                anyhow::bail!("names specified in the `trappable_imports` config option but are not referenced in the target world: {unused_imports:?}");
910            }
911        }
912
913        if !self.opts.only_interfaces {
914            self.build_world_struct(resolve, world)
915        }
916
917        let imports = mem::take(&mut self.import_interfaces);
918        self.emit_modules(imports);
919
920        let exports = mem::take(&mut self.exports.modules);
921        self.emit_modules(exports);
922
923        let mut src = mem::take(&mut self.src);
924        if self.opts.rustfmt {
925            let mut child = Command::new("rustfmt")
926                .arg("--edition=2018")
927                .stdin(Stdio::piped())
928                .stdout(Stdio::piped())
929                .spawn()
930                .expect("failed to spawn `rustfmt`");
931            child
932                .stdin
933                .take()
934                .unwrap()
935                .write_all(src.as_bytes())
936                .unwrap();
937            src.as_mut_string().truncate(0);
938            child
939                .stdout
940                .take()
941                .unwrap()
942                .read_to_string(src.as_mut_string())
943                .unwrap();
944            let status = child.wait().unwrap();
945            assert!(status.success());
946        }
947
948        Ok(src.into())
949    }
950
951    fn emit_modules(&mut self, modules: Vec<(String, InterfaceName)>) {
952        #[derive(Default)]
953        struct Module {
954            submodules: BTreeMap<String, Module>,
955            contents: Vec<String>,
956        }
957        let mut map = Module::default();
958        for (module, name) in modules {
959            let path = match name {
960                InterfaceName::Remapped { local_path, .. } => local_path,
961                InterfaceName::Path(path) => path,
962            };
963            let mut cur = &mut map;
964            for name in path[..path.len() - 1].iter() {
965                cur = cur
966                    .submodules
967                    .entry(name.clone())
968                    .or_insert(Module::default());
969            }
970            cur.contents.push(module);
971        }
972
973        emit(&mut self.src, map);
974
975        fn emit(me: &mut Source, module: Module) {
976            for (name, submodule) in module.submodules {
977                uwriteln!(me, "pub mod {name} {{");
978                emit(me, submodule);
979                uwriteln!(me, "}}");
980            }
981            for submodule in module.contents {
982                uwriteln!(me, "{submodule}");
983            }
984        }
985    }
986
987    /// Attempts to find the `key`, possibly with the resource projection
988    /// `item`, within the `with` map provided to bindings configuration.
989    fn lookup_replacement(
990        &mut self,
991        resolve: &Resolve,
992        key: &WorldKey,
993        item: Option<&str>,
994    ) -> Option<String> {
995        let item = match item {
996            Some(item) => LookupItem::Name(item),
997            None => LookupItem::None,
998        };
999
1000        for (lookup, mut projection) in lookup_keys(resolve, key, item) {
1001            if let Some(renamed) = self.opts.with.get(&lookup) {
1002                projection.push(renamed.clone());
1003                projection.reverse();
1004                self.used_with_opts.insert(lookup);
1005                return Some(projection.join("::"));
1006            }
1007        }
1008
1009        None
1010    }
1011
1012    fn wasmtime_path(&self) -> String {
1013        self.opts
1014            .wasmtime_crate
1015            .clone()
1016            .unwrap_or("wasmtime".to_string())
1017    }
1018}
1019
1020enum LookupItem<'a> {
1021    None,
1022    Name(&'a str),
1023    InterfaceNoPop,
1024}
1025
1026fn lookup_keys(
1027    resolve: &Resolve,
1028    key: &WorldKey,
1029    item: LookupItem<'_>,
1030) -> Vec<(String, Vec<String>)> {
1031    struct Name<'a> {
1032        prefix: Prefix,
1033        item: Option<&'a str>,
1034    }
1035
1036    #[derive(Copy, Clone)]
1037    enum Prefix {
1038        Namespace(PackageId),
1039        UnversionedPackage(PackageId),
1040        VersionedPackage(PackageId),
1041        UnversionedInterface(InterfaceId),
1042        VersionedInterface(InterfaceId),
1043    }
1044
1045    let prefix = match key {
1046        WorldKey::Interface(id) => Prefix::VersionedInterface(*id),
1047
1048        // Non-interface-keyed names don't get the lookup logic below,
1049        // they're relatively uncommon so only lookup the precise key here.
1050        WorldKey::Name(key) => {
1051            let to_lookup = match item {
1052                LookupItem::Name(item) => format!("{key}/{item}"),
1053                LookupItem::None | LookupItem::InterfaceNoPop => key.to_string(),
1054            };
1055            return vec![(to_lookup, Vec::new())];
1056        }
1057    };
1058
1059    // Here names are iteratively attempted as `key` + `item` is "walked to
1060    // its root" and each attempt is consulted in `self.opts.with`. This
1061    // loop will start at the leaf, the most specific path, and then walk to
1062    // the root, popping items, trying to find a result.
1063    //
1064    // Each time a name is "popped" the projection from the next path is
1065    // pushed onto `projection`. This means that if we actually find a match
1066    // then `projection` is a collection of namespaces that results in the
1067    // final replacement name.
1068    let (interface_required, item) = match item {
1069        LookupItem::None => (false, None),
1070        LookupItem::Name(s) => (false, Some(s)),
1071        LookupItem::InterfaceNoPop => (true, None),
1072    };
1073    let mut name = Name { prefix, item };
1074    let mut projection = Vec::new();
1075    let mut ret = Vec::new();
1076    loop {
1077        let lookup = name.lookup_key(resolve);
1078        ret.push((lookup, projection.clone()));
1079        if !name.pop(resolve, &mut projection) {
1080            break;
1081        }
1082        if interface_required {
1083            match name.prefix {
1084                Prefix::VersionedInterface(_) | Prefix::UnversionedInterface(_) => {}
1085                _ => break,
1086            }
1087        }
1088    }
1089
1090    return ret;
1091
1092    impl<'a> Name<'a> {
1093        fn lookup_key(&self, resolve: &Resolve) -> String {
1094            let mut s = self.prefix.lookup_key(resolve);
1095            if let Some(item) = self.item {
1096                s.push_str("/");
1097                s.push_str(item);
1098            }
1099            s
1100        }
1101
1102        fn pop(&mut self, resolve: &'a Resolve, projection: &mut Vec<String>) -> bool {
1103            match (self.item, self.prefix) {
1104                // If this is a versioned resource name, try the unversioned
1105                // resource name next.
1106                (Some(_), Prefix::VersionedInterface(id)) => {
1107                    self.prefix = Prefix::UnversionedInterface(id);
1108                    true
1109                }
1110                // If this is an unversioned resource name then time to
1111                // ignore the resource itself and move on to the next most
1112                // specific item, versioned interface names.
1113                (Some(item), Prefix::UnversionedInterface(id)) => {
1114                    self.prefix = Prefix::VersionedInterface(id);
1115                    self.item = None;
1116                    projection.push(item.to_upper_camel_case());
1117                    true
1118                }
1119                (Some(_), _) => unreachable!(),
1120                (None, _) => self.prefix.pop(resolve, projection),
1121            }
1122        }
1123    }
1124
1125    impl Prefix {
1126        fn lookup_key(&self, resolve: &Resolve) -> String {
1127            match *self {
1128                Prefix::Namespace(id) => resolve.packages[id].name.namespace.clone(),
1129                Prefix::UnversionedPackage(id) => {
1130                    let mut name = resolve.packages[id].name.clone();
1131                    name.version = None;
1132                    name.to_string()
1133                }
1134                Prefix::VersionedPackage(id) => resolve.packages[id].name.to_string(),
1135                Prefix::UnversionedInterface(id) => {
1136                    let id = resolve.id_of(id).unwrap();
1137                    match id.find('@') {
1138                        Some(i) => id[..i].to_string(),
1139                        None => id,
1140                    }
1141                }
1142                Prefix::VersionedInterface(id) => resolve.id_of(id).unwrap(),
1143            }
1144        }
1145
1146        fn pop(&mut self, resolve: &Resolve, projection: &mut Vec<String>) -> bool {
1147            *self = match *self {
1148                // try the unversioned interface next
1149                Prefix::VersionedInterface(id) => Prefix::UnversionedInterface(id),
1150                // try this interface's versioned package next
1151                Prefix::UnversionedInterface(id) => {
1152                    let iface = &resolve.interfaces[id];
1153                    let name = iface.name.as_ref().unwrap();
1154                    projection.push(to_rust_ident(name));
1155                    Prefix::VersionedPackage(iface.package.unwrap())
1156                }
1157                // try the unversioned package next
1158                Prefix::VersionedPackage(id) => Prefix::UnversionedPackage(id),
1159                // try this package's namespace next
1160                Prefix::UnversionedPackage(id) => {
1161                    let name = &resolve.packages[id].name;
1162                    projection.push(to_rust_ident(&name.name));
1163                    Prefix::Namespace(id)
1164                }
1165                // nothing left to try any more
1166                Prefix::Namespace(_) => return false,
1167            };
1168            true
1169        }
1170    }
1171}
1172
1173impl Wasmtime {
1174    fn has_world_imports_trait(&self, resolve: &Resolve, world: WorldId) -> bool {
1175        !self.import_functions.is_empty() || get_world_resources(resolve, world).count() > 0
1176    }
1177
1178    fn world_imports_trait(&mut self, resolve: &Resolve, world: WorldId) {
1179        if !self.has_world_imports_trait(resolve, world) {
1180            return;
1181        }
1182
1183        let wt = self.wasmtime_path();
1184        let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
1185        if self.opts.async_.maybe_async() {
1186            uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]")
1187        }
1188        uwrite!(self.src, "pub trait {world_camel}Imports");
1189        let mut supertraits = vec![];
1190        if self.opts.async_.maybe_async() {
1191            supertraits.push("Send".to_string());
1192        }
1193        for resource in get_world_resources(resolve, world) {
1194            supertraits.push(format!("Host{}", resource.to_upper_camel_case()));
1195        }
1196        if !supertraits.is_empty() {
1197            uwrite!(self.src, ": {}", supertraits.join(" + "));
1198        }
1199        uwriteln!(self.src, " {{");
1200        for f in self.import_functions.iter() {
1201            if let Some(sig) = &f.sig {
1202                self.src.push_str(sig);
1203                self.src.push_str(";\n");
1204            }
1205        }
1206        uwriteln!(self.src, "}}");
1207
1208        uwriteln!(
1209            self.src,
1210            "
1211                pub trait {world_camel}ImportsGetHost<T>:
1212                    Fn(T) -> <Self as {world_camel}ImportsGetHost<T>>::Host
1213                        + Send
1214                        + Sync
1215                        + Copy
1216                        + 'static
1217                {{
1218                    type Host: {world_camel}Imports;
1219                }}
1220
1221                impl<F, T, O> {world_camel}ImportsGetHost<T> for F
1222                where
1223                    F: Fn(T) -> O + Send + Sync + Copy + 'static,
1224                    O: {world_camel}Imports
1225                {{
1226                    type Host = O;
1227                }}
1228            "
1229        );
1230
1231        // Generate impl WorldImports for &mut WorldImports
1232        let (async_trait, maybe_send) = if self.opts.async_.maybe_async() {
1233            (
1234                format!("#[{wt}::component::__internal::async_trait]\n"),
1235                "+ Send",
1236            )
1237        } else {
1238            (String::new(), "")
1239        };
1240        if !self.opts.skip_mut_forwarding_impls {
1241            uwriteln!(
1242                self.src,
1243                "{async_trait}impl<_T: {world_camel}Imports + ?Sized {maybe_send}> {world_camel}Imports for &mut _T {{"
1244            );
1245            // Forward each method call to &mut T
1246            for f in self.import_functions.iter() {
1247                if let Some(sig) = &f.sig {
1248                    self.src.push_str(sig);
1249                    uwrite!(
1250                        self.src,
1251                        "{{ {world_camel}Imports::{}(*self,",
1252                        rust_function_name(&f.func)
1253                    );
1254                    for (name, _) in f.func.params.iter() {
1255                        uwrite!(self.src, "{},", to_rust_ident(name));
1256                    }
1257                    uwrite!(self.src, ")");
1258                    if self.opts.async_.is_import_async(&f.func.name) {
1259                        uwrite!(self.src, ".await");
1260                    }
1261                    uwriteln!(self.src, "}}");
1262                }
1263            }
1264            uwriteln!(self.src, "}}");
1265        }
1266    }
1267
1268    fn import_interface_paths(&self) -> Vec<String> {
1269        self.import_interfaces
1270            .iter()
1271            .map(|(_, name)| match name {
1272                InterfaceName::Path(path) => path.join("::"),
1273                InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(),
1274            })
1275            .collect()
1276    }
1277
1278    fn world_host_traits(&self, resolve: &Resolve, world: WorldId) -> Vec<String> {
1279        let mut traits = self
1280            .import_interface_paths()
1281            .iter()
1282            .map(|path| format!("{path}::Host"))
1283            .collect::<Vec<_>>();
1284        if self.has_world_imports_trait(resolve, world) {
1285            let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
1286            traits.push(format!("{world_camel}Imports"));
1287        }
1288        if self.opts.async_.maybe_async() {
1289            traits.push("Send".to_string());
1290        }
1291        traits
1292    }
1293
1294    fn world_add_to_linker(&mut self, resolve: &Resolve, world: WorldId) {
1295        let has_world_imports_trait = self.has_world_imports_trait(resolve, world);
1296        if self.import_interfaces.is_empty() && !has_world_imports_trait {
1297            return;
1298        }
1299
1300        let camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
1301        let data_bounds = if self.opts.is_store_data_send() {
1302            "T: Send,"
1303        } else {
1304            ""
1305        };
1306        let wt = self.wasmtime_path();
1307        if has_world_imports_trait {
1308            uwrite!(
1309                self.src,
1310                "
1311                    pub fn add_to_linker_imports_get_host<T>(
1312                        linker: &mut {wt}::component::Linker<T>,
1313                        host_getter: impl for<'a> {camel}ImportsGetHost<&'a mut T>,
1314                    ) -> {wt}::Result<()>
1315                        where {data_bounds}
1316                    {{
1317                        let mut linker = linker.root();
1318                "
1319            );
1320            for name in get_world_resources(resolve, world) {
1321                let camel = name.to_upper_camel_case();
1322                uwriteln!(
1323                    self.src,
1324                    "
1325                        linker.resource(
1326                            \"{name}\",
1327                            {wt}::component::ResourceType::host::<{camel}>(),
1328                            move |mut store, rep| -> {wt}::Result<()> {{
1329                                Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep))
1330                            }},
1331                        )?;"
1332                );
1333            }
1334            for f in self.import_functions.iter() {
1335                self.src.push_str(&f.add_to_linker);
1336                self.src.push_str("\n");
1337            }
1338            uwriteln!(self.src, "Ok(())\n}}");
1339        }
1340
1341        let host_bounds = format!("U: {}", self.world_host_traits(resolve, world).join(" + "));
1342
1343        if !self.opts.skip_mut_forwarding_impls {
1344            uwriteln!(
1345                self.src,
1346                "
1347                    pub fn add_to_linker<T, U>(
1348                        linker: &mut {wt}::component::Linker<T>,
1349                        get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
1350                    ) -> {wt}::Result<()>
1351                        where
1352                            {data_bounds}
1353                            {host_bounds}
1354                    {{
1355                "
1356            );
1357            if has_world_imports_trait {
1358                uwriteln!(
1359                    self.src,
1360                    "Self::add_to_linker_imports_get_host(linker, get)?;"
1361                );
1362            }
1363            for path in self.import_interface_paths() {
1364                uwriteln!(self.src, "{path}::add_to_linker(linker, get)?;");
1365            }
1366            uwriteln!(self.src, "Ok(())\n}}");
1367        }
1368    }
1369}
1370
1371struct InterfaceGenerator<'a> {
1372    src: Source,
1373    gen: &'a mut Wasmtime,
1374    resolve: &'a Resolve,
1375    current_interface: Option<(InterfaceId, &'a WorldKey, bool)>,
1376}
1377
1378impl<'a> InterfaceGenerator<'a> {
1379    fn new(gen: &'a mut Wasmtime, resolve: &'a Resolve) -> InterfaceGenerator<'a> {
1380        InterfaceGenerator {
1381            src: Source::default(),
1382            gen,
1383            resolve,
1384            current_interface: None,
1385        }
1386    }
1387
1388    fn types_imported(&self) -> bool {
1389        match self.current_interface {
1390            Some((_, _, is_export)) => !is_export,
1391            None => true,
1392        }
1393    }
1394
1395    fn types(&mut self, id: InterfaceId) {
1396        for (name, id) in self.resolve.interfaces[id].types.iter() {
1397            self.define_type(name, *id);
1398        }
1399    }
1400
1401    fn define_type(&mut self, name: &str, id: TypeId) {
1402        let ty = &self.resolve.types[id];
1403        match &ty.kind {
1404            TypeDefKind::Record(record) => self.type_record(id, name, record, &ty.docs),
1405            TypeDefKind::Flags(flags) => self.type_flags(id, name, flags, &ty.docs),
1406            TypeDefKind::Tuple(tuple) => self.type_tuple(id, name, tuple, &ty.docs),
1407            TypeDefKind::Enum(enum_) => self.type_enum(id, name, enum_, &ty.docs),
1408            TypeDefKind::Variant(variant) => self.type_variant(id, name, variant, &ty.docs),
1409            TypeDefKind::Option(t) => self.type_option(id, name, t, &ty.docs),
1410            TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs),
1411            TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs),
1412            TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs),
1413            TypeDefKind::Future(_) => todo!("generate for future"),
1414            TypeDefKind::Stream(_) => todo!("generate for stream"),
1415            TypeDefKind::Handle(handle) => self.type_handle(id, name, handle, &ty.docs),
1416            TypeDefKind::Resource => self.type_resource(id, name, ty, &ty.docs),
1417            TypeDefKind::Unknown => unreachable!(),
1418        }
1419    }
1420
1421    fn type_handle(&mut self, id: TypeId, name: &str, handle: &Handle, docs: &Docs) {
1422        self.rustdoc(docs);
1423        let name = name.to_upper_camel_case();
1424        uwriteln!(self.src, "pub type {name} = ");
1425        self.print_handle(handle);
1426        self.push_str(";\n");
1427        self.assert_type(id, &name);
1428    }
1429
1430    fn type_resource(&mut self, id: TypeId, name: &str, resource: &TypeDef, docs: &Docs) {
1431        let camel = name.to_upper_camel_case();
1432        let wt = self.gen.wasmtime_path();
1433
1434        if self.types_imported() {
1435            self.rustdoc(docs);
1436
1437            let replacement = match self.current_interface {
1438                Some((_, key, _)) => self.gen.lookup_replacement(self.resolve, key, Some(name)),
1439                None => {
1440                    self.gen.used_with_opts.insert(name.into());
1441                    self.gen.opts.with.get(name).cloned()
1442                }
1443            };
1444            match replacement {
1445                Some(path) => {
1446                    uwriteln!(
1447                        self.src,
1448                        "pub use {}{path} as {camel};",
1449                        self.path_to_root()
1450                    );
1451                }
1452                None => {
1453                    uwriteln!(self.src, "pub enum {camel} {{}}");
1454                }
1455            }
1456
1457            // Generate resource trait
1458            if self.gen.opts.async_.maybe_async() {
1459                uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]")
1460            }
1461            uwriteln!(self.src, "pub trait Host{camel} {{");
1462
1463            let mut functions = match resource.owner {
1464                TypeOwner::World(id) => self.resolve.worlds[id]
1465                    .imports
1466                    .values()
1467                    .filter_map(|item| match item {
1468                        WorldItem::Function(f) => Some(f),
1469                        _ => None,
1470                    })
1471                    .collect(),
1472                TypeOwner::Interface(id) => self.resolve.interfaces[id]
1473                    .functions
1474                    .values()
1475                    .collect::<Vec<_>>(),
1476                TypeOwner::None => {
1477                    panic!("A resource must be owned by a world or interface");
1478                }
1479            };
1480
1481            functions.retain(|func| match func.kind {
1482                FunctionKind::Freestanding => false,
1483                FunctionKind::Method(resource)
1484                | FunctionKind::Static(resource)
1485                | FunctionKind::Constructor(resource) => id == resource,
1486            });
1487
1488            for func in &functions {
1489                self.generate_function_trait_sig(func);
1490                self.push_str(";\n");
1491            }
1492
1493            uwrite!(
1494                self.src,
1495                "fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()>;"
1496            );
1497
1498            uwriteln!(self.src, "}}");
1499
1500            // Generate impl HostResource for &mut HostResource
1501            if !self.gen.opts.skip_mut_forwarding_impls {
1502                let (async_trait, maybe_send) = if self.gen.opts.async_.maybe_async() {
1503                    (
1504                        format!("#[{wt}::component::__internal::async_trait]\n"),
1505                        "+ Send",
1506                    )
1507                } else {
1508                    (String::new(), "")
1509                };
1510                uwriteln!(
1511                    self.src,
1512                    "{async_trait}impl <_T: Host{camel} + ?Sized {maybe_send}> Host{camel} for &mut _T {{"
1513                );
1514                for func in &functions {
1515                    self.generate_function_trait_sig(func);
1516                    uwrite!(
1517                        self.src,
1518                        "{{ Host{camel}::{}(*self,",
1519                        rust_function_name(func)
1520                    );
1521                    for (name, _) in func.params.iter() {
1522                        uwrite!(self.src, "{},", to_rust_ident(name));
1523                    }
1524                    uwrite!(self.src, ")");
1525                    if self.gen.opts.async_.is_import_async(&func.name) {
1526                        uwrite!(self.src, ".await");
1527                    }
1528                    uwriteln!(self.src, "}}");
1529                }
1530                uwriteln!(self.src, "
1531                    fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()> {{
1532                        Host{camel}::drop(*self, rep)
1533                    }}",
1534                );
1535                uwriteln!(self.src, "}}");
1536            }
1537        } else {
1538            self.rustdoc(docs);
1539            uwriteln!(
1540                self.src,
1541                "
1542                    pub type {camel} = {wt}::component::ResourceAny;
1543
1544                    pub struct Guest{camel}<'a> {{
1545                        funcs: &'a Guest,
1546                    }}
1547                "
1548            );
1549        }
1550    }
1551
1552    fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) {
1553        let info = self.info(id);
1554        let wt = self.gen.wasmtime_path();
1555
1556        // We use a BTree set to make sure we don't have any duplicates and we have a stable order
1557        let additional_derives: BTreeSet<String> = self
1558            .gen
1559            .opts
1560            .additional_derive_attributes
1561            .iter()
1562            .cloned()
1563            .collect();
1564
1565        for (name, mode) in self.modes_of(id) {
1566            let lt = self.lifetime_for(&info, mode);
1567            self.rustdoc(docs);
1568
1569            let mut derives = additional_derives.clone();
1570
1571            uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1572            if lt.is_none() {
1573                uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1574            }
1575            uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1576            self.push_str("#[component(record)]\n");
1577            if let Some(path) = &self.gen.opts.wasmtime_crate {
1578                uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1579            }
1580
1581            if info.is_copy() {
1582                derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
1583            } else if info.is_clone() {
1584                derives.insert("Clone".to_string());
1585            }
1586
1587            if !derives.is_empty() {
1588                self.push_str("#[derive(");
1589                self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1590                self.push_str(")]\n")
1591            }
1592
1593            self.push_str(&format!("pub struct {}", name));
1594            self.print_generics(lt);
1595            self.push_str(" {\n");
1596            for field in record.fields.iter() {
1597                self.rustdoc(&field.docs);
1598                self.push_str(&format!("#[component(name = \"{}\")]\n", field.name));
1599                self.push_str("pub ");
1600                self.push_str(&to_rust_ident(&field.name));
1601                self.push_str(": ");
1602                self.print_ty(&field.ty, mode);
1603                self.push_str(",\n");
1604            }
1605            self.push_str("}\n");
1606
1607            self.push_str("impl");
1608            self.print_generics(lt);
1609            self.push_str(" core::fmt::Debug for ");
1610            self.push_str(&name);
1611            self.print_generics(lt);
1612            self.push_str(" {\n");
1613            self.push_str(
1614                "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1615            );
1616            self.push_str(&format!("f.debug_struct(\"{}\")", name));
1617            for field in record.fields.iter() {
1618                self.push_str(&format!(
1619                    ".field(\"{}\", &self.{})",
1620                    field.name,
1621                    to_rust_ident(&field.name)
1622                ));
1623            }
1624            self.push_str(".finish()\n");
1625            self.push_str("}\n");
1626            self.push_str("}\n");
1627
1628            if info.error {
1629                self.push_str("impl");
1630                self.print_generics(lt);
1631                self.push_str(" core::fmt::Display for ");
1632                self.push_str(&name);
1633                self.print_generics(lt);
1634                self.push_str(" {\n");
1635                self.push_str(
1636                    "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1637                );
1638                self.push_str("write!(f, \"{:?}\", self)\n");
1639                self.push_str("}\n");
1640                self.push_str("}\n");
1641
1642                if cfg!(feature = "std") {
1643                    self.push_str("impl std::error::Error for ");
1644                    self.push_str(&name);
1645                    self.push_str("{}\n");
1646                }
1647            }
1648            self.assert_type(id, &name);
1649        }
1650    }
1651
1652    fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) {
1653        let info = self.info(id);
1654        for (name, mode) in self.modes_of(id) {
1655            let lt = self.lifetime_for(&info, mode);
1656            self.rustdoc(docs);
1657            self.push_str(&format!("pub type {}", name));
1658            self.print_generics(lt);
1659            self.push_str(" = (");
1660            for ty in tuple.types.iter() {
1661                self.print_ty(ty, mode);
1662                self.push_str(",");
1663            }
1664            self.push_str(");\n");
1665            self.assert_type(id, &name);
1666        }
1667    }
1668
1669    fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
1670        self.rustdoc(docs);
1671        let wt = self.gen.wasmtime_path();
1672        let rust_name = to_rust_upper_camel_case(name);
1673        uwriteln!(self.src, "{wt}::component::flags!(\n");
1674        self.src.push_str(&format!("{rust_name} {{\n"));
1675        for flag in flags.flags.iter() {
1676            // TODO wasmtime-component-macro doesn't support docs for flags rn
1677            uwrite!(
1678                self.src,
1679                "#[component(name=\"{}\")] const {};\n",
1680                flag.name,
1681                flag.name.to_shouty_snake_case()
1682            );
1683        }
1684        self.src.push_str("}\n");
1685        self.src.push_str(");\n\n");
1686        self.assert_type(id, &rust_name);
1687    }
1688
1689    fn type_variant(&mut self, id: TypeId, _name: &str, variant: &Variant, docs: &Docs) {
1690        self.print_rust_enum(
1691            id,
1692            variant.cases.iter().map(|c| {
1693                (
1694                    c.name.to_upper_camel_case(),
1695                    Some(c.name.clone()),
1696                    &c.docs,
1697                    c.ty.as_ref(),
1698                )
1699            }),
1700            docs,
1701            "variant",
1702        );
1703    }
1704
1705    fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) {
1706        let info = self.info(id);
1707
1708        for (name, mode) in self.modes_of(id) {
1709            self.rustdoc(docs);
1710            let lt = self.lifetime_for(&info, mode);
1711            self.push_str(&format!("pub type {}", name));
1712            self.print_generics(lt);
1713            self.push_str("= Option<");
1714            self.print_ty(payload, mode);
1715            self.push_str(">;\n");
1716            self.assert_type(id, &name);
1717        }
1718    }
1719
1720    // Emit a double-check that the wit-parser-understood size of a type agrees
1721    // with the Wasmtime-understood size of a type.
1722    fn assert_type(&mut self, id: TypeId, name: &str) {
1723        self.push_str("const _: () = {\n");
1724        let wt = self.gen.wasmtime_path();
1725        uwriteln!(
1726            self.src,
1727            "assert!({} == <{name} as {wt}::component::ComponentType>::SIZE32);",
1728            self.gen.sizes.size(&Type::Id(id)),
1729        );
1730        uwriteln!(
1731            self.src,
1732            "assert!({} == <{name} as {wt}::component::ComponentType>::ALIGN32);",
1733            self.gen.sizes.align(&Type::Id(id)),
1734        );
1735        self.push_str("};\n");
1736    }
1737
1738    fn print_rust_enum<'b>(
1739        &mut self,
1740        id: TypeId,
1741        cases: impl IntoIterator<Item = (String, Option<String>, &'b Docs, Option<&'b Type>)> + Clone,
1742        docs: &Docs,
1743        derive_component: &str,
1744    ) where
1745        Self: Sized,
1746    {
1747        let info = self.info(id);
1748        let wt = self.gen.wasmtime_path();
1749
1750        // We use a BTree set to make sure we don't have any duplicates and we have a stable order
1751        let additional_derives: BTreeSet<String> = self
1752            .gen
1753            .opts
1754            .additional_derive_attributes
1755            .iter()
1756            .cloned()
1757            .collect();
1758
1759        for (name, mode) in self.modes_of(id) {
1760            let name = to_rust_upper_camel_case(&name);
1761
1762            let mut derives = additional_derives.clone();
1763
1764            self.rustdoc(docs);
1765            let lt = self.lifetime_for(&info, mode);
1766            uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1767            if lt.is_none() {
1768                uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1769            }
1770            uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1771            self.push_str(&format!("#[component({})]\n", derive_component));
1772            if let Some(path) = &self.gen.opts.wasmtime_crate {
1773                uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1774            }
1775            if info.is_copy() {
1776                derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
1777            } else if info.is_clone() {
1778                derives.insert("Clone".to_string());
1779            }
1780
1781            if !derives.is_empty() {
1782                self.push_str("#[derive(");
1783                self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1784                self.push_str(")]\n")
1785            }
1786
1787            self.push_str(&format!("pub enum {name}"));
1788            self.print_generics(lt);
1789            self.push_str("{\n");
1790            for (case_name, component_name, docs, payload) in cases.clone() {
1791                self.rustdoc(docs);
1792                if let Some(n) = component_name {
1793                    self.push_str(&format!("#[component(name = \"{}\")] ", n));
1794                }
1795                self.push_str(&case_name);
1796                if let Some(ty) = payload {
1797                    self.push_str("(");
1798                    self.print_ty(ty, mode);
1799                    self.push_str(")")
1800                }
1801                self.push_str(",\n");
1802            }
1803            self.push_str("}\n");
1804
1805            self.print_rust_enum_debug(
1806                id,
1807                mode,
1808                &name,
1809                cases
1810                    .clone()
1811                    .into_iter()
1812                    .map(|(name, _attr, _docs, ty)| (name, ty)),
1813            );
1814
1815            if info.error {
1816                self.push_str("impl");
1817                self.print_generics(lt);
1818                self.push_str(" core::fmt::Display for ");
1819                self.push_str(&name);
1820                self.print_generics(lt);
1821                self.push_str(" {\n");
1822                self.push_str(
1823                    "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1824                );
1825                self.push_str("write!(f, \"{:?}\", self)");
1826                self.push_str("}\n");
1827                self.push_str("}\n");
1828                self.push_str("\n");
1829
1830                if cfg!(feature = "std") {
1831                    self.push_str("impl");
1832                    self.print_generics(lt);
1833                    self.push_str(" std::error::Error for ");
1834                    self.push_str(&name);
1835                    self.print_generics(lt);
1836                    self.push_str(" {}\n");
1837                }
1838            }
1839
1840            self.assert_type(id, &name);
1841        }
1842    }
1843
1844    fn print_rust_enum_debug<'b>(
1845        &mut self,
1846        id: TypeId,
1847        mode: TypeMode,
1848        name: &str,
1849        cases: impl IntoIterator<Item = (String, Option<&'b Type>)>,
1850    ) where
1851        Self: Sized,
1852    {
1853        let info = self.info(id);
1854        let lt = self.lifetime_for(&info, mode);
1855        self.push_str("impl");
1856        self.print_generics(lt);
1857        self.push_str(" core::fmt::Debug for ");
1858        self.push_str(name);
1859        self.print_generics(lt);
1860        self.push_str(" {\n");
1861        self.push_str("fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n");
1862        self.push_str("match self {\n");
1863        for (case_name, payload) in cases {
1864            self.push_str(name);
1865            self.push_str("::");
1866            self.push_str(&case_name);
1867            if payload.is_some() {
1868                self.push_str("(e)");
1869            }
1870            self.push_str(" => {\n");
1871            self.push_str(&format!("f.debug_tuple(\"{}::{}\")", name, case_name));
1872            if payload.is_some() {
1873                self.push_str(".field(e)");
1874            }
1875            self.push_str(".finish()\n");
1876            self.push_str("}\n");
1877        }
1878        self.push_str("}\n");
1879        self.push_str("}\n");
1880        self.push_str("}\n");
1881    }
1882
1883    fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) {
1884        let info = self.info(id);
1885
1886        for (name, mode) in self.modes_of(id) {
1887            self.rustdoc(docs);
1888            let lt = self.lifetime_for(&info, mode);
1889            self.push_str(&format!("pub type {}", name));
1890            self.print_generics(lt);
1891            self.push_str("= Result<");
1892            self.print_optional_ty(result.ok.as_ref(), mode);
1893            self.push_str(",");
1894            self.print_optional_ty(result.err.as_ref(), mode);
1895            self.push_str(">;\n");
1896            self.assert_type(id, &name);
1897        }
1898    }
1899
1900    fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
1901        let info = self.info(id);
1902        let wt = self.gen.wasmtime_path();
1903
1904        // We use a BTree set to make sure we don't have any duplicates and have a stable order
1905        let mut derives: BTreeSet<String> = self
1906            .gen
1907            .opts
1908            .additional_derive_attributes
1909            .iter()
1910            .cloned()
1911            .collect();
1912
1913        derives.extend(
1914            ["Clone", "Copy", "PartialEq", "Eq"]
1915                .into_iter()
1916                .map(|s| s.to_string()),
1917        );
1918
1919        let name = to_rust_upper_camel_case(name);
1920        self.rustdoc(docs);
1921        uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1922        uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1923        uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1924        self.push_str("#[component(enum)]\n");
1925        if let Some(path) = &self.gen.opts.wasmtime_crate {
1926            uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1927        }
1928
1929        self.push_str("#[derive(");
1930        self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1931        self.push_str(")]\n");
1932
1933        self.push_str(&format!("pub enum {} {{\n", name));
1934        for case in enum_.cases.iter() {
1935            self.rustdoc(&case.docs);
1936            self.push_str(&format!("#[component(name = \"{}\")]", case.name));
1937            self.push_str(&case.name.to_upper_camel_case());
1938            self.push_str(",\n");
1939        }
1940        self.push_str("}\n");
1941
1942        // Auto-synthesize an implementation of the standard `Error` trait for
1943        // error-looking types based on their name.
1944        if info.error {
1945            self.push_str("impl ");
1946            self.push_str(&name);
1947            self.push_str("{\n");
1948
1949            self.push_str("pub fn name(&self) -> &'static str {\n");
1950            self.push_str("match self {\n");
1951            for case in enum_.cases.iter() {
1952                self.push_str(&name);
1953                self.push_str("::");
1954                self.push_str(&case.name.to_upper_camel_case());
1955                self.push_str(" => \"");
1956                self.push_str(case.name.as_str());
1957                self.push_str("\",\n");
1958            }
1959            self.push_str("}\n");
1960            self.push_str("}\n");
1961
1962            self.push_str("pub fn message(&self) -> &'static str {\n");
1963            self.push_str("match self {\n");
1964            for case in enum_.cases.iter() {
1965                self.push_str(&name);
1966                self.push_str("::");
1967                self.push_str(&case.name.to_upper_camel_case());
1968                self.push_str(" => \"");
1969                if let Some(contents) = &case.docs.contents {
1970                    self.push_str(contents.trim());
1971                }
1972                self.push_str("\",\n");
1973            }
1974            self.push_str("}\n");
1975            self.push_str("}\n");
1976
1977            self.push_str("}\n");
1978
1979            self.push_str("impl core::fmt::Debug for ");
1980            self.push_str(&name);
1981            self.push_str(
1982                "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1983            );
1984            self.push_str("f.debug_struct(\"");
1985            self.push_str(&name);
1986            self.push_str("\")\n");
1987            self.push_str(".field(\"code\", &(*self as i32))\n");
1988            self.push_str(".field(\"name\", &self.name())\n");
1989            self.push_str(".field(\"message\", &self.message())\n");
1990            self.push_str(".finish()\n");
1991            self.push_str("}\n");
1992            self.push_str("}\n");
1993
1994            self.push_str("impl core::fmt::Display for ");
1995            self.push_str(&name);
1996            self.push_str(
1997                "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1998            );
1999            self.push_str("write!(f, \"{} (error {})\", self.name(), *self as i32)");
2000            self.push_str("}\n");
2001            self.push_str("}\n");
2002            self.push_str("\n");
2003            if cfg!(feature = "std") {
2004                self.push_str("impl std::error::Error for ");
2005                self.push_str(&name);
2006                self.push_str("{}\n");
2007            }
2008        } else {
2009            self.print_rust_enum_debug(
2010                id,
2011                TypeMode::Owned,
2012                &name,
2013                enum_
2014                    .cases
2015                    .iter()
2016                    .map(|c| (c.name.to_upper_camel_case(), None)),
2017            )
2018        }
2019        self.assert_type(id, &name);
2020    }
2021
2022    fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
2023        let info = self.info(id);
2024        for (name, mode) in self.modes_of(id) {
2025            self.rustdoc(docs);
2026            self.push_str(&format!("pub type {}", name));
2027            let lt = self.lifetime_for(&info, mode);
2028            self.print_generics(lt);
2029            self.push_str(" = ");
2030            self.print_ty(ty, mode);
2031            self.push_str(";\n");
2032            let def_id = resolve_type_definition_id(self.resolve, id);
2033            if !matches!(self.resolve().types[def_id].kind, TypeDefKind::Resource) {
2034                self.assert_type(id, &name);
2035            }
2036        }
2037    }
2038
2039    fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
2040        let info = self.info(id);
2041        for (name, mode) in self.modes_of(id) {
2042            let lt = self.lifetime_for(&info, mode);
2043            self.rustdoc(docs);
2044            self.push_str(&format!("pub type {}", name));
2045            self.print_generics(lt);
2046            self.push_str(" = ");
2047            self.print_list(ty, mode);
2048            self.push_str(";\n");
2049            self.assert_type(id, &name);
2050        }
2051    }
2052
2053    fn print_result_ty(&mut self, results: &Results, mode: TypeMode) {
2054        match results {
2055            Results::Named(rs) => match rs.len() {
2056                0 => self.push_str("()"),
2057                1 => self.print_ty(&rs[0].1, mode),
2058                _ => {
2059                    self.push_str("(");
2060                    for (i, (_, ty)) in rs.iter().enumerate() {
2061                        if i > 0 {
2062                            self.push_str(", ")
2063                        }
2064                        self.print_ty(ty, mode)
2065                    }
2066                    self.push_str(")");
2067                }
2068            },
2069            Results::Anon(ty) => self.print_ty(ty, mode),
2070        }
2071    }
2072
2073    fn special_case_trappable_error(
2074        &mut self,
2075        func: &Function,
2076    ) -> Option<(&'a Result_, TypeId, String)> {
2077        let results = &func.results;
2078
2079        self.gen
2080            .used_trappable_imports_opts
2081            .insert(func.name.clone());
2082
2083        // We fillin a special trappable error type in the case when a function has just one
2084        // result, which is itself a `result<a, e>`, and the `e` is *not* a primitive
2085        // (i.e. defined in std) type, and matches the typename given by the user.
2086        let mut i = results.iter_types();
2087        let id = match i.next()? {
2088            Type::Id(id) => id,
2089            _ => return None,
2090        };
2091        if i.next().is_some() {
2092            return None;
2093        }
2094        let result = match &self.resolve.types[*id].kind {
2095            TypeDefKind::Result(r) => r,
2096            _ => return None,
2097        };
2098        let error_typeid = match result.err? {
2099            Type::Id(id) => resolve_type_definition_id(&self.resolve, id),
2100            _ => return None,
2101        };
2102
2103        let name = self.gen.trappable_errors.get(&error_typeid)?;
2104
2105        let mut path = self.path_to_root();
2106        uwrite!(path, "{name}");
2107        Some((result, error_typeid, path))
2108    }
2109
2110    fn generate_add_to_linker(&mut self, id: InterfaceId, name: &str) {
2111        let iface = &self.resolve.interfaces[id];
2112        let owner = TypeOwner::Interface(id);
2113        let wt = self.gen.wasmtime_path();
2114
2115        let is_maybe_async = self.gen.opts.async_.maybe_async();
2116        if is_maybe_async {
2117            uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]")
2118        }
2119        // Generate the `pub trait` which represents the host functionality for
2120        // this import which additionally inherits from all resource traits
2121        // for this interface defined by `type_resource`.
2122        uwrite!(self.src, "pub trait Host");
2123        let mut host_supertraits = vec![];
2124        if is_maybe_async {
2125            host_supertraits.push("Send".to_string());
2126        }
2127        for resource in get_resources(self.resolve, id) {
2128            host_supertraits.push(format!("Host{}", resource.to_upper_camel_case()));
2129        }
2130        if !host_supertraits.is_empty() {
2131            uwrite!(self.src, ": {}", host_supertraits.join(" + "));
2132        }
2133        uwriteln!(self.src, " {{");
2134        for (_, func) in iface.functions.iter() {
2135            match func.kind {
2136                FunctionKind::Freestanding => {}
2137                _ => continue,
2138            }
2139            self.generate_function_trait_sig(func);
2140            self.push_str(";\n");
2141        }
2142
2143        // Generate `convert_*` functions to convert custom trappable errors
2144        // into the representation required by Wasmtime's component API.
2145        let mut required_conversion_traits = IndexSet::new();
2146        let mut errors_converted = IndexMap::new();
2147        let mut my_error_types = iface
2148            .types
2149            .iter()
2150            .filter(|(_, id)| self.gen.trappable_errors.contains_key(*id))
2151            .map(|(_, id)| *id)
2152            .collect::<Vec<_>>();
2153        my_error_types.extend(
2154            iface
2155                .functions
2156                .iter()
2157                .filter_map(|(_, func)| self.special_case_trappable_error(func))
2158                .map(|(_, id, _)| id),
2159        );
2160        let root = self.path_to_root();
2161        for err_id in my_error_types {
2162            let custom_name = &self.gen.trappable_errors[&err_id];
2163            let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err_id)];
2164            let err_name = err.name.as_ref().unwrap();
2165            let err_snake = err_name.to_snake_case();
2166            let err_camel = err_name.to_upper_camel_case();
2167            let owner = match err.owner {
2168                TypeOwner::Interface(i) => i,
2169                _ => unimplemented!(),
2170            };
2171            match self.path_to_interface(owner) {
2172                Some(path) => {
2173                    required_conversion_traits.insert(format!("{path}::Host"));
2174                }
2175                None => {
2176                    if errors_converted.insert(err_name, err_id).is_none() {
2177                        uwriteln!(
2178                            self.src,
2179                            "fn convert_{err_snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{err_camel}>;"
2180                        );
2181                    }
2182                }
2183            }
2184        }
2185        uwriteln!(self.src, "}}");
2186
2187        let (data_bounds, mut host_bounds) = if self.gen.opts.is_store_data_send() {
2188            ("T: Send,", "Host + Send".to_string())
2189        } else {
2190            ("", "Host".to_string())
2191        };
2192        for ty in required_conversion_traits {
2193            uwrite!(host_bounds, " + {ty}");
2194        }
2195
2196        uwriteln!(
2197            self.src,
2198            "
2199                pub trait GetHost<T>:
2200                    Fn(T) -> <Self as GetHost<T>>::Host
2201                        + Send
2202                        + Sync
2203                        + Copy
2204                        + 'static
2205                {{
2206                    type Host: {host_bounds};
2207                }}
2208
2209                impl<F, T, O> GetHost<T> for F
2210                where
2211                    F: Fn(T) -> O + Send + Sync + Copy + 'static,
2212                    O: {host_bounds},
2213                {{
2214                    type Host = O;
2215                }}
2216
2217                pub fn add_to_linker_get_host<T>(
2218                    linker: &mut {wt}::component::Linker<T>,
2219                    host_getter: impl for<'a> GetHost<&'a mut T>,
2220                ) -> {wt}::Result<()>
2221                    where {data_bounds}
2222                {{
2223            "
2224        );
2225        uwriteln!(self.src, "let mut inst = linker.instance(\"{name}\")?;");
2226
2227        for name in get_resources(self.resolve, id) {
2228            let camel = name.to_upper_camel_case();
2229            uwriteln!(
2230                self.src,
2231                "inst.resource(
2232                    \"{name}\",
2233                    {wt}::component::ResourceType::host::<{camel}>(),
2234                    move |mut store, rep| -> {wt}::Result<()> {{
2235                        Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep))
2236                    }},
2237                )?;"
2238            )
2239        }
2240
2241        for (_, func) in iface.functions.iter() {
2242            self.generate_add_function_to_linker(owner, func, "inst");
2243        }
2244        uwriteln!(self.src, "Ok(())");
2245        uwriteln!(self.src, "}}");
2246
2247        if !self.gen.opts.skip_mut_forwarding_impls {
2248            // Generate add_to_linker (with closure)
2249            uwriteln!(
2250                self.src,
2251                "
2252                pub fn add_to_linker<T, U>(
2253                    linker: &mut {wt}::component::Linker<T>,
2254                    get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
2255                ) -> {wt}::Result<()>
2256                    where
2257                        U: {host_bounds}, {data_bounds}
2258                {{
2259                    add_to_linker_get_host(linker, get)
2260                }}
2261                "
2262            );
2263
2264            // Generate impl Host for &mut Host
2265            let (async_trait, maybe_send) = if is_maybe_async {
2266                (
2267                    format!("#[{wt}::component::__internal::async_trait]"),
2268                    "+ Send",
2269                )
2270            } else {
2271                (String::new(), "")
2272            };
2273
2274            uwriteln!(
2275                self.src,
2276                "{async_trait}impl<_T: Host + ?Sized {maybe_send}> Host for &mut _T {{"
2277            );
2278            // Forward each method call to &mut T
2279            for (_, func) in iface.functions.iter() {
2280                match func.kind {
2281                    FunctionKind::Freestanding => {}
2282                    _ => continue,
2283                }
2284                self.generate_function_trait_sig(func);
2285                uwrite!(self.src, "{{ Host::{}(*self,", rust_function_name(func));
2286                for (name, _) in func.params.iter() {
2287                    uwrite!(self.src, "{},", to_rust_ident(name));
2288                }
2289                uwrite!(self.src, ")");
2290                if self.gen.opts.async_.is_import_async(&func.name) {
2291                    uwrite!(self.src, ".await");
2292                }
2293                uwriteln!(self.src, "}}");
2294            }
2295            for (err_name, err_id) in errors_converted {
2296                uwriteln!(
2297                    self.src,
2298                    "fn convert_{err_snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{err_camel}> {{
2299                        Host::convert_{err_snake}(*self, err)
2300                    }}",
2301                    custom_name = self.gen.trappable_errors[&err_id],
2302                    err_snake = err_name.to_snake_case(),
2303                    err_camel = err_name.to_upper_camel_case(),
2304                );
2305            }
2306            uwriteln!(self.src, "}}");
2307        }
2308    }
2309
2310    fn generate_add_function_to_linker(&mut self, owner: TypeOwner, func: &Function, linker: &str) {
2311        uwrite!(
2312            self.src,
2313            "{linker}.{}(\"{}\", ",
2314            if self.gen.opts.async_.is_import_async(&func.name) {
2315                "func_wrap_async"
2316            } else {
2317                "func_wrap"
2318            },
2319            func.name
2320        );
2321        self.generate_guest_import_closure(owner, func);
2322        uwriteln!(self.src, ")?;")
2323    }
2324
2325    fn generate_guest_import_closure(&mut self, owner: TypeOwner, func: &Function) {
2326        // Generate the closure that's passed to a `Linker`, the final piece of
2327        // codegen here.
2328
2329        let wt = self.gen.wasmtime_path();
2330        uwrite!(
2331            self.src,
2332            "move |mut caller: {wt}::StoreContextMut<'_, T>, ("
2333        );
2334        for (i, _param) in func.params.iter().enumerate() {
2335            uwrite!(self.src, "arg{},", i);
2336        }
2337        self.src.push_str(") : (");
2338
2339        for (_, ty) in func.params.iter() {
2340            // Lift is required to be impled for this type, so we can't use
2341            // a borrowed type:
2342            self.print_ty(ty, TypeMode::Owned);
2343            self.src.push_str(", ");
2344        }
2345        self.src.push_str(") |");
2346        if self.gen.opts.async_.is_import_async(&func.name) {
2347            uwriteln!(
2348                self.src,
2349                " {wt}::component::__internal::Box::new(async move {{ "
2350            );
2351        } else {
2352            self.src.push_str(" { \n");
2353        }
2354
2355        if self.gen.opts.tracing {
2356            uwrite!(
2357                self.src,
2358                "
2359                   let span = tracing::span!(
2360                       tracing::Level::TRACE,
2361                       \"wit-bindgen import\",
2362                       module = \"{}\",
2363                       function = \"{}\",
2364                   );
2365                   let _enter = span.enter();
2366               ",
2367                match owner {
2368                    TypeOwner::Interface(id) => self.resolve.interfaces[id]
2369                        .name
2370                        .as_deref()
2371                        .unwrap_or("<no module>"),
2372                    TypeOwner::World(id) => &self.resolve.worlds[id].name,
2373                    TypeOwner::None => "<no owner>",
2374                },
2375                func.name,
2376            );
2377            let mut event_fields = func
2378                .params
2379                .iter()
2380                .enumerate()
2381                .map(|(i, (name, _ty))| {
2382                    let name = to_rust_ident(&name);
2383                    format!("{name} = tracing::field::debug(&arg{i})")
2384                })
2385                .collect::<Vec<String>>();
2386            event_fields.push(format!("\"call\""));
2387            uwrite!(
2388                self.src,
2389                "tracing::event!(tracing::Level::TRACE, {});\n",
2390                event_fields.join(", ")
2391            );
2392        }
2393
2394        self.src
2395            .push_str("let host = &mut host_getter(caller.data_mut());\n");
2396        let func_name = rust_function_name(func);
2397        let host_trait = match func.kind {
2398            FunctionKind::Freestanding => match owner {
2399                TypeOwner::World(id) => format!(
2400                    "{}Imports",
2401                    self.resolve.worlds[id].name.to_upper_camel_case()
2402                ),
2403                _ => "Host".to_string(),
2404            },
2405            FunctionKind::Method(id) | FunctionKind::Static(id) | FunctionKind::Constructor(id) => {
2406                let resource = self.resolve.types[id]
2407                    .name
2408                    .as_ref()
2409                    .unwrap()
2410                    .to_upper_camel_case();
2411                format!("Host{resource}")
2412            }
2413        };
2414        uwrite!(self.src, "let r = {host_trait}::{func_name}(host, ");
2415
2416        for (i, _) in func.params.iter().enumerate() {
2417            uwrite!(self.src, "arg{},", i);
2418        }
2419        if self.gen.opts.async_.is_import_async(&func.name) {
2420            uwrite!(self.src, ").await;\n");
2421        } else {
2422            uwrite!(self.src, ");\n");
2423        }
2424
2425        if self.gen.opts.tracing {
2426            uwrite!(
2427                self.src,
2428                "tracing::event!(tracing::Level::TRACE, result = tracing::field::debug(&r), \"return\");"
2429            );
2430        }
2431
2432        if !self.gen.opts.trappable_imports.can_trap(&func) {
2433            if func.results.iter_types().len() == 1 {
2434                uwrite!(self.src, "Ok((r,))\n");
2435            } else {
2436                uwrite!(self.src, "Ok(r)\n");
2437            }
2438        } else if let Some((_, err, _)) = self.special_case_trappable_error(func) {
2439            let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err)];
2440            let err_name = err.name.as_ref().unwrap();
2441            let owner = match err.owner {
2442                TypeOwner::Interface(i) => i,
2443                _ => unimplemented!(),
2444            };
2445            let convert_trait = match self.path_to_interface(owner) {
2446                Some(path) => format!("{path}::Host"),
2447                None => format!("Host"),
2448            };
2449            let convert = format!("{}::convert_{}", convert_trait, err_name.to_snake_case());
2450            uwrite!(
2451                self.src,
2452                "Ok((match r {{
2453                    Ok(a) => Ok(a),
2454                    Err(e) => Err({convert}(host, e)?),
2455                }},))"
2456            );
2457        } else if func.results.iter_types().len() == 1 {
2458            uwrite!(self.src, "Ok((r?,))\n");
2459        } else {
2460            uwrite!(self.src, "r\n");
2461        }
2462
2463        if self.gen.opts.async_.is_import_async(&func.name) {
2464            // Need to close Box::new and async block
2465            self.src.push_str("})");
2466        } else {
2467            self.src.push_str("}");
2468        }
2469    }
2470
2471    fn generate_function_trait_sig(&mut self, func: &Function) {
2472        let wt = self.gen.wasmtime_path();
2473        self.rustdoc(&func.docs);
2474
2475        if self.gen.opts.async_.is_import_async(&func.name) {
2476            self.push_str("async ");
2477        }
2478        self.push_str("fn ");
2479        self.push_str(&rust_function_name(func));
2480        self.push_str("(&mut self, ");
2481        for (name, param) in func.params.iter() {
2482            let name = to_rust_ident(name);
2483            self.push_str(&name);
2484            self.push_str(": ");
2485            self.print_ty(param, TypeMode::Owned);
2486            self.push_str(",");
2487        }
2488        self.push_str(")");
2489        self.push_str(" -> ");
2490
2491        if !self.gen.opts.trappable_imports.can_trap(func) {
2492            self.print_result_ty(&func.results, TypeMode::Owned);
2493        } else if let Some((r, _id, error_typename)) = self.special_case_trappable_error(func) {
2494            // Functions which have a single result `result<ok,err>` get special
2495            // cased to use the host_wasmtime_rust::Error<err>, making it possible
2496            // for them to trap or use `?` to propagate their errors
2497            self.push_str("Result<");
2498            if let Some(ok) = r.ok {
2499                self.print_ty(&ok, TypeMode::Owned);
2500            } else {
2501                self.push_str("()");
2502            }
2503            self.push_str(",");
2504            self.push_str(&error_typename);
2505            self.push_str(">");
2506        } else {
2507            // All other functions get their return values wrapped in an wasmtime::Result.
2508            // Returning the anyhow::Error case can be used to trap.
2509            uwrite!(self.src, "{wt}::Result<");
2510            self.print_result_ty(&func.results, TypeMode::Owned);
2511            self.push_str(">");
2512        }
2513    }
2514
2515    fn extract_typed_function(&mut self, func: &Function) -> (String, String) {
2516        let prev = mem::take(&mut self.src);
2517        let snake = func_field_name(self.resolve, func);
2518        uwrite!(self.src, "*_instance.get_typed_func::<(");
2519        for (_, ty) in func.params.iter() {
2520            self.print_ty(ty, TypeMode::AllBorrowed("'_"));
2521            self.push_str(", ");
2522        }
2523        self.src.push_str("), (");
2524        for ty in func.results.iter_types() {
2525            self.print_ty(ty, TypeMode::Owned);
2526            self.push_str(", ");
2527        }
2528        uwriteln!(self.src, ")>(&mut store, &self.{snake})?.func()");
2529
2530        let ret = (snake, mem::take(&mut self.src).to_string());
2531        self.src = prev;
2532        ret
2533    }
2534
2535    fn define_rust_guest_export(
2536        &mut self,
2537        resolve: &Resolve,
2538        ns: Option<&WorldKey>,
2539        func: &Function,
2540    ) {
2541        // Exports must be async if anything could be async, it's just imports
2542        // that get to be optionally async/sync.
2543        let is_async = self.gen.opts.async_.maybe_async();
2544
2545        let (async_, async__, await_) = if is_async {
2546            ("async", "_async", ".await")
2547        } else {
2548            ("", "", "")
2549        };
2550
2551        self.rustdoc(&func.docs);
2552        let wt = self.gen.wasmtime_path();
2553
2554        uwrite!(
2555            self.src,
2556            "pub {async_} fn call_{}<S: {wt}::AsContextMut>(&self, mut store: S, ",
2557            func.item_name().to_snake_case(),
2558        );
2559
2560        for (i, param) in func.params.iter().enumerate() {
2561            uwrite!(self.src, "arg{}: ", i);
2562            self.print_ty(&param.1, TypeMode::AllBorrowed("'_"));
2563            self.push_str(",");
2564        }
2565
2566        uwrite!(self.src, ") -> {wt}::Result<");
2567        self.print_result_ty(&func.results, TypeMode::Owned);
2568
2569        if is_async {
2570            uwriteln!(self.src, "> where <S as {wt}::AsContext>::Data: Send {{");
2571        } else {
2572            self.src.push_str("> {\n");
2573        }
2574
2575        if self.gen.opts.tracing {
2576            let ns = match ns {
2577                Some(key) => resolve.name_world_key(key),
2578                None => "default".to_string(),
2579            };
2580            self.src.push_str(&format!(
2581                "
2582                   let span = tracing::span!(
2583                       tracing::Level::TRACE,
2584                       \"wit-bindgen export\",
2585                       module = \"{ns}\",
2586                       function = \"{}\",
2587                   );
2588                   let _enter = span.enter();
2589               ",
2590                func.name,
2591            ));
2592        }
2593
2594        self.src.push_str("let callee = unsafe {\n");
2595        uwrite!(self.src, "{wt}::component::TypedFunc::<(");
2596        for (_, ty) in func.params.iter() {
2597            self.print_ty(ty, TypeMode::AllBorrowed("'_"));
2598            self.push_str(", ");
2599        }
2600        self.src.push_str("), (");
2601        for ty in func.results.iter_types() {
2602            self.print_ty(ty, TypeMode::Owned);
2603            self.push_str(", ");
2604        }
2605        let projection_to_func = match &func.kind {
2606            FunctionKind::Freestanding => "",
2607            _ => ".funcs",
2608        };
2609        uwriteln!(
2610            self.src,
2611            ")>::new_unchecked(self{projection_to_func}.{})",
2612            func_field_name(self.resolve, func),
2613        );
2614        self.src.push_str("};\n");
2615        self.src.push_str("let (");
2616        for (i, _) in func.results.iter_types().enumerate() {
2617            uwrite!(self.src, "ret{},", i);
2618        }
2619        uwrite!(
2620            self.src,
2621            ") = callee.call{async__}(store.as_context_mut(), ("
2622        );
2623        for (i, _) in func.params.iter().enumerate() {
2624            uwrite!(self.src, "arg{}, ", i);
2625        }
2626        uwriteln!(self.src, ")){await_}?;");
2627
2628        uwriteln!(
2629            self.src,
2630            "callee.post_return{async__}(store.as_context_mut()){await_}?;"
2631        );
2632
2633        self.src.push_str("Ok(");
2634        if func.results.iter_types().len() == 1 {
2635            self.src.push_str("ret0");
2636        } else {
2637            self.src.push_str("(");
2638            for (i, _) in func.results.iter_types().enumerate() {
2639                uwrite!(self.src, "ret{},", i);
2640            }
2641            self.src.push_str(")");
2642        }
2643        self.src.push_str(")\n");
2644
2645        // End function body
2646        self.src.push_str("}\n");
2647    }
2648
2649    fn rustdoc(&mut self, docs: &Docs) {
2650        let docs = match &docs.contents {
2651            Some(docs) => docs,
2652            None => return,
2653        };
2654        for line in docs.trim().lines() {
2655            self.push_str("/// ");
2656            self.push_str(line);
2657            self.push_str("\n");
2658        }
2659    }
2660
2661    fn path_to_root(&self) -> String {
2662        let mut path_to_root = String::new();
2663        if let Some((_, key, is_export)) = self.current_interface {
2664            match key {
2665                WorldKey::Name(_) => {
2666                    path_to_root.push_str("super::");
2667                }
2668                WorldKey::Interface(_) => {
2669                    path_to_root.push_str("super::super::super::");
2670                }
2671            }
2672            if is_export {
2673                path_to_root.push_str("super::");
2674            }
2675        }
2676        path_to_root
2677    }
2678}
2679
2680impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
2681    fn resolve(&self) -> &'a Resolve {
2682        self.resolve
2683    }
2684
2685    fn ownership(&self) -> Ownership {
2686        self.gen.opts.ownership
2687    }
2688
2689    fn path_to_interface(&self, interface: InterfaceId) -> Option<String> {
2690        if let Some((cur, _, _)) = self.current_interface {
2691            if cur == interface {
2692                return None;
2693            }
2694        }
2695        let mut path_to_root = self.path_to_root();
2696        match &self.gen.interface_names[&interface] {
2697            InterfaceName::Remapped { name_at_root, .. } => path_to_root.push_str(name_at_root),
2698            InterfaceName::Path(path) => {
2699                for (i, name) in path.iter().enumerate() {
2700                    if i > 0 {
2701                        path_to_root.push_str("::");
2702                    }
2703                    path_to_root.push_str(name);
2704                }
2705            }
2706        }
2707        Some(path_to_root)
2708    }
2709
2710    fn push_str(&mut self, s: &str) {
2711        self.src.push_str(s);
2712    }
2713
2714    fn info(&self, ty: TypeId) -> TypeInfo {
2715        self.gen.types.get(ty)
2716    }
2717
2718    fn is_imported_interface(&self, interface: InterfaceId) -> bool {
2719        self.gen.interface_last_seen_as_import[&interface]
2720    }
2721
2722    fn wasmtime_path(&self) -> String {
2723        self.gen.wasmtime_path()
2724    }
2725}
2726
2727/// When an interface `use`s a type from another interface, it creates a new TypeId
2728/// referring to the definition TypeId. Chase this chain of references down to
2729/// a TypeId for type's definition.
2730fn resolve_type_definition_id(resolve: &Resolve, mut id: TypeId) -> TypeId {
2731    loop {
2732        match resolve.types[id].kind {
2733            TypeDefKind::Type(Type::Id(def_id)) => id = def_id,
2734            _ => return id,
2735        }
2736    }
2737}
2738
2739fn rust_function_name(func: &Function) -> String {
2740    match func.kind {
2741        FunctionKind::Method(_) | FunctionKind::Static(_) => to_rust_ident(func.item_name()),
2742        FunctionKind::Constructor(_) => "new".to_string(),
2743        FunctionKind::Freestanding => to_rust_ident(&func.name),
2744    }
2745}
2746
2747fn func_field_name(resolve: &Resolve, func: &Function) -> String {
2748    let mut name = String::new();
2749    match func.kind {
2750        FunctionKind::Method(id) => {
2751            name.push_str("method-");
2752            name.push_str(resolve.types[id].name.as_ref().unwrap());
2753            name.push_str("-");
2754        }
2755        FunctionKind::Static(id) => {
2756            name.push_str("static-");
2757            name.push_str(resolve.types[id].name.as_ref().unwrap());
2758            name.push_str("-");
2759        }
2760        FunctionKind::Constructor(id) => {
2761            name.push_str("constructor-");
2762            name.push_str(resolve.types[id].name.as_ref().unwrap());
2763            name.push_str("-");
2764        }
2765        FunctionKind::Freestanding => {}
2766    }
2767    name.push_str(func.item_name());
2768    name.to_snake_case()
2769}
2770
2771fn get_resources<'a>(resolve: &'a Resolve, id: InterfaceId) -> impl Iterator<Item = &'a str> + 'a {
2772    resolve.interfaces[id]
2773        .types
2774        .iter()
2775        .filter_map(move |(name, ty)| match resolve.types[*ty].kind {
2776            TypeDefKind::Resource => Some(name.as_str()),
2777            _ => None,
2778        })
2779}
2780
2781fn get_world_resources<'a>(
2782    resolve: &'a Resolve,
2783    id: WorldId,
2784) -> impl Iterator<Item = &'a str> + 'a {
2785    resolve.worlds[id]
2786        .imports
2787        .iter()
2788        .filter_map(move |(name, item)| match item {
2789            WorldItem::Type(id) => match resolve.types[*id].kind {
2790                TypeDefKind::Resource => Some(match name {
2791                    WorldKey::Name(s) => s.as_str(),
2792                    WorldKey::Interface(_) => unreachable!(),
2793                }),
2794                _ => None,
2795            },
2796            _ => None,
2797        })
2798}