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