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