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