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