Skip to main content

wasmtime_internal_wit_bindgen/
lib.rs

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
8use crate::rust::{RustGenerator, TypeMode, to_rust_ident, to_rust_upper_camel_case};
9use crate::types::{TypeInfo, Types};
10use anyhow::bail;
11use heck::*;
12use indexmap::{IndexMap, IndexSet};
13use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
14use std::fmt::Write as _;
15use std::io::{Read, Write};
16use std::mem;
17use std::process::{Command, Stdio};
18use wit_parser::*;
19
20macro_rules! uwrite {
21    ($dst:expr, $($arg:tt)*) => {
22        write!($dst, $($arg)*).unwrap()
23    };
24}
25
26macro_rules! uwriteln {
27    ($dst:expr, $($arg:tt)*) => {
28        writeln!($dst, $($arg)*).unwrap()
29    };
30}
31
32mod config;
33mod rust;
34mod source;
35mod types;
36
37pub use config::{FunctionConfig, FunctionFilter, FunctionFlags};
38use source::Source;
39
40#[derive(Clone)]
41enum 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)]
67struct 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
86struct ImportInterface {
87    id: InterfaceId,
88    contents: String,
89    name: InterfaceName,
90    all_func_flags: FunctionFlags,
91}
92
93#[derive(Default)]
94struct Exports {
95    fields: BTreeMap<String, ExportField>,
96    modules: Vec<(InterfaceId, String, InterfaceName)>,
97    funcs: Vec<String>,
98}
99
100struct ExportField {
101    ty: String,
102    ty_index: String,
103    load: String,
104    get_index: String,
105}
106
107#[derive(Default, Debug, Clone, Copy)]
108pub 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)]
127pub 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)]
195pub 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
203impl Opts {
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
227impl Wasmtime {
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    }
242    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.
283    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
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
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
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.
581pub 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
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.
757pub struct {camel}Pre<T: 'static> {{
758    instance_pre: {wt}::component::InstancePre<T>,
759    indices: {camel}Indices,
760}}
761
762impl<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
771impl<_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                "
813impl<_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
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
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.
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
1115    fn wasmtime_path(&self) -> String {
1116        self.opts
1117            .wasmtime_crate
1118            .clone()
1119            .unwrap_or("wasmtime".to_string())
1120    }
1121}
1122
1123enum LookupItem<'a> {
1124    None,
1125    Name(&'a str),
1126    InterfaceNoPop,
1127}
1128
1129fn 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
1276impl Wasmtime {
1277    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
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
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
1317    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
1324    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
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
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
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
1588struct 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
1596impl<'a> 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
1607    fn types_imported(&self) -> bool {
1608        match self.current_interface {
1609            Some((_, _, is_export)) => !is_export,
1610            None => true,
1611        }
1612    }
1613
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
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
2403    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
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
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
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
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
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
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
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
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
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
2883    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
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
2919    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                            "
2972fn 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                            "
2982fn 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                        "
3057fn 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
3154enum ExtraTraitMethod<'a> {
3155    ResourceDrop { name: &'a str },
3156    ErrorConvert { name: &'a str, id: TypeId },
3157}
3158
3159struct FunctionPartitioning<'a> {
3160    without_store: Vec<(&'a Function, FunctionFlags)>,
3161    with_store: Vec<(&'a Function, FunctionFlags)>,
3162}
3163
3164#[derive(Default)]
3165struct GeneratedTrait {
3166    name: String,
3167    with_store_name: Option<String>,
3168    all_func_flags: FunctionFlags,
3169}
3170
3171impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
3172    fn resolve(&self) -> &'a Resolve {
3173        self.resolve
3174    }
3175
3176    fn ownership(&self) -> Ownership {
3177        self.generator.opts.ownership
3178    }
3179
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
3201    fn push_str(&mut self, s: &str) {
3202        self.src.push_str(s);
3203    }
3204
3205    fn info(&self, ty: TypeId) -> TypeInfo {
3206        self.generator.types.get(ty)
3207    }
3208
3209    fn is_imported_interface(&self, interface: InterfaceId) -> bool {
3210        self.generator.interface_last_seen_as_import[&interface]
3211    }
3212
3213    fn wasmtime_path(&self) -> String {
3214        self.generator.wasmtime_path()
3215    }
3216}
3217
3218#[derive(Default)]
3219struct LinkOptionsBuilder {
3220    unstable_features: BTreeSet<String>,
3221}
3222impl LinkOptionsBuilder {
3223    fn has_any(&self) -> bool {
3224        !self.unstable_features.is_empty()
3225    }
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    }
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    }
3258    fn add_type(&mut self, resolve: &Resolve, id: &TypeId) {
3259        let t = &resolve.types[*id];
3260        self.add_stability(&t.stability);
3261    }
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    }
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    }
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
3350struct FeatureGate {
3351    close: bool,
3352}
3353impl FeatureGate {
3354    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
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.
3373fn 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.
3389fn 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.
3406fn 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
3447fn 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.
3457fn 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
3466fn 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
3478fn 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
3502fn 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
3515fn 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
3538fn 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}