Skip to main content

wit_bindgen_rust/
lib.rs

1use crate::interface::InterfaceGenerator;
2use anyhow::{Result, bail};
3use core::panic;
4use heck::*;
5use indexmap::{IndexMap, IndexSet};
6use std::collections::{BTreeMap, HashMap, HashSet};
7use std::fmt::{self, Write as _};
8use std::mem;
9use std::path::{Path, PathBuf};
10use std::str::FromStr;
11use wit_bindgen_core::abi::{Bitcast, WasmType};
12use wit_bindgen_core::{
13    AsyncFilterSet, ChainableMethodFilterSet, ChainingMode, Files, InterfaceGenerator as _, Source,
14    Types, WorldGenerator, dealias, name_package_module, uwrite, uwriteln, wit_parser::*,
15};
16
17mod bindgen;
18mod interface;
19
20struct InterfaceName {
21    /// True when this interface name has been remapped through the use of `with` in the `bindgen!`
22    /// macro invocation.
23    remapped: bool,
24
25    /// The string name for this interface.
26    path: String,
27}
28
29#[derive(Default)]
30pub struct RustWasm {
31    types: Types,
32    src_preamble: Source,
33    src: Source,
34    opts: Opts,
35    import_modules: Vec<(String, Vec<String>)>,
36    export_modules: Vec<(String, Vec<String>)>,
37    skip: HashSet<String>,
38    interface_names: HashMap<InterfaceId, InterfaceName>,
39    exported_resources: HashSet<TypeId>,
40    import_funcs_called: bool,
41    with_name_counter: usize,
42    // Track which interfaces and types are generated. Remapped interfaces and types provided via `with`
43    // are required to be used.
44    generated_types: HashSet<String>,
45    // Attribute selectors that matched something, so `finish` can reject the rest.
46    used_type_attr_selectors: HashSet<String>,
47    used_member_attr_selectors: HashSet<String>,
48    world: Option<WorldId>,
49
50    rt_module: IndexSet<RuntimeItem>,
51    export_macros: Vec<(String, String)>,
52
53    /// Maps wit interface and type names to their Rust identifiers
54    with: GenerationConfiguration,
55
56    future_payloads: IndexMap<Option<Type>, String>,
57    stream_payloads: IndexMap<Option<Type>, String>,
58}
59
60#[derive(Default)]
61struct GenerationConfiguration {
62    map: HashMap<String, TypeGeneration>,
63    generate_by_default: bool,
64}
65
66impl GenerationConfiguration {
67    fn get(&self, key: &str) -> Option<&TypeGeneration> {
68        self.map.get(key).or_else(|| {
69            self.generate_by_default
70                .then_some(&TypeGeneration::Generate)
71        })
72    }
73
74    fn insert(&mut self, name: String, generate: TypeGeneration) {
75        self.map.insert(name, generate);
76    }
77
78    fn iter(&self) -> impl Iterator<Item = (&String, &TypeGeneration)> {
79        self.map.iter()
80    }
81}
82
83/// How a wit interface or type should be rendered in Rust
84enum TypeGeneration {
85    /// Uses a Rust identifier defined elsewhere
86    Remap(String),
87    /// Define the interface or type with this bindgen invocation
88    Generate,
89}
90
91impl TypeGeneration {
92    /// Returns true if the interface or type should be defined with this bindgen invocation
93    fn generated(&self) -> bool {
94        match self {
95            TypeGeneration::Generate => true,
96            TypeGeneration::Remap(_) => false,
97        }
98    }
99}
100
101#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
102enum RuntimeItem {
103    AllocCrate,
104    StringType,
105    StdAllocModule,
106    VecType,
107    StringLift,
108    InvalidEnumDiscriminant,
109    CharLift,
110    BoolLift,
111    CabiDealloc,
112    RunCtorsOnce,
113    AsI32,
114    AsI64,
115    AsF32,
116    AsF64,
117    ResourceType,
118    BoxType,
119    WitMapTrait,
120}
121
122#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
123#[cfg_attr(
124    feature = "serde",
125    derive(serde::Deserialize),
126    serde(rename_all = "kebab-case")
127)]
128pub enum ExportKey {
129    World,
130    Name(String),
131}
132
133#[cfg(feature = "clap")]
134fn parse_with(s: &str) -> Result<(String, WithOption), String> {
135    let (k, v) = s.split_once('=').ok_or_else(|| {
136        format!("expected string of form `<key>=<value>[,<key>=<value>...]`; got `{s}`")
137    })?;
138    let v = match v {
139        "generate" => WithOption::Generate,
140        other => WithOption::Path(other.to_string()),
141    };
142    Ok((k.to_string(), v))
143}
144
145// Split on the first `=` only, so the attribute may itself contain `=`.
146#[cfg(feature = "clap")]
147fn parse_attribute(s: &str) -> Result<(String, String), String> {
148    let (sel, attr) = s
149        .split_once('=')
150        .ok_or_else(|| format!("expected string of form `<selector>=<attribute>`; got `{s}`"))?;
151    // An empty attribute would mark the selector used and escape the unused check.
152    if attr.trim().is_empty() {
153        return Err(format!("attribute must not be empty; got `{s}`"));
154    }
155    Ok((sel.to_string(), attr.to_string()))
156}
157
158#[derive(Default, Debug, Clone)]
159#[cfg_attr(feature = "clap", derive(clap::Parser))]
160#[cfg_attr(
161    feature = "serde",
162    derive(serde::Deserialize),
163    serde(default, rename_all = "kebab-case")
164)]
165pub struct Opts {
166    /// Whether or not a formatter is executed to format generated code.
167    #[cfg_attr(feature = "clap", arg(long))]
168    pub format: bool,
169
170    /// If true, code generation should qualify any features that depend on
171    /// `std` with `cfg(feature = "std")`.
172    #[cfg_attr(feature = "clap", arg(long))]
173    pub std_feature: bool,
174
175    /// If true, code generation should pass borrowed string arguments as
176    /// `&[u8]` instead of `&str`. Strings are still required to be valid
177    /// UTF-8, but this avoids the need for Rust code to do its own UTF-8
178    /// validation if it doesn't already have a `&str`.
179    #[cfg_attr(feature = "clap", arg(long))]
180    pub raw_strings: bool,
181
182    /// Names of functions to skip generating bindings for.
183    #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
184    pub skip: Vec<String>,
185
186    /// If true, generate stub implementations for any exported functions,
187    /// interfaces, and/or resources.
188    #[cfg_attr(feature = "clap", arg(long))]
189    pub stubs: bool,
190
191    /// Optionally prefix any export names with the specified value.
192    ///
193    /// This is useful to avoid name conflicts when testing.
194    #[cfg_attr(feature = "clap", arg(long, value_name = "STRING"))]
195    pub export_prefix: Option<String>,
196
197    /// Whether to generate owning or borrowing type definitions.
198    ///
199    /// Valid values include:
200    ///
201    /// - `owning`: Generated types will be composed entirely of owning fields,
202    /// regardless of whether they are used as parameters to imports or not.
203    ///
204    /// - `borrowing`: Generated types used as parameters to imports will be
205    /// "deeply borrowing", i.e. contain references rather than owned values
206    /// when applicable.
207    ///
208    /// - `borrowing-duplicate-if-necessary`: As above, but generating distinct
209    /// types for borrowing and owning, if necessary.
210    #[cfg_attr(feature = "clap", arg(long, default_value_t = Ownership::Owning))]
211    pub ownership: Ownership,
212
213    /// The optional path to the wit-bindgen runtime module to use.
214    ///
215    /// This defaults to `wit_bindgen::rt`.
216    #[cfg_attr(feature = "clap", arg(long, value_name = "PATH"))]
217    pub runtime_path: Option<String>,
218
219    /// The optional path to the map type to use for WIT `map<K, V>`.
220    ///
221    /// The specified type must accept two type parameters `<K, V>` and
222    /// implement the `WitMap<K, V>` trait from the wit-bindgen runtime.
223    /// It must also implement `IntoIterator<Item = (K, V)>` (owned) and
224    /// its reference must implement `IntoIterator` yielding key/value
225    /// pairs.
226    ///
227    /// Defaults to `{runtime_path}::Map` which is `BTreeMap`.
228    #[cfg_attr(feature = "clap", arg(long, value_name = "PATH"))]
229    pub map_type: Option<String>,
230
231    /// The optional path to the bitflags crate to use.
232    ///
233    /// This defaults to `wit_bindgen::bitflags`.
234    #[cfg_attr(feature = "clap", arg(long))]
235    pub bitflags_path: Option<String>,
236
237    /// Additional derive attributes to add to generated types. If using in a CLI, this flag can be
238    /// specified multiple times to add multiple attributes.
239    ///
240    /// These derive attributes will be added to any generated structs or enums
241    #[cfg_attr(feature = "clap", arg(long, short = 'd', value_name = "DERIVE"))]
242    pub additional_derive_attributes: Vec<String>,
243
244    /// Variants and records to ignore when applying additional derive attributes.
245    ///
246    /// These names are specified as they are listed in the wit file, i.e. in kebab case.
247    /// This feature allows some variants and records to use types for which adding traits will cause
248    /// compilation to fail, such as serde::Deserialize on wasi:io/streams.
249    ///
250    #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
251    pub additional_derive_ignore: Vec<String>,
252
253    /// Extra attributes to emit on specific generated types, rather than on all
254    /// types like `additional_derive_attributes`.
255    ///
256    /// Each entry pairs a selector with an attribute. A selector is a type's
257    /// fully qualified name, written as in `with`, so `my:pkg/types/point`,
258    /// carrying `@version` when the package is versioned. A selector matching
259    /// nothing is an error, as with `with`.
260    ///
261    /// Only records, variants, and enums are covered. Attributes are emitted
262    /// verbatim on every form of the type, including the borrowed form under
263    /// `ownership: Borrowing`, so an owned-only derive fails to compile there.
264    ///
265    /// In a CLI, this flag can be specified multiple times as
266    /// `selector=attribute`.
267    #[cfg_attr(feature = "clap", arg(long, value_name = "SELECTOR=ATTR", value_parser = parse_attribute))]
268    pub additional_type_attributes: Vec<(String, String)>,
269
270    /// Extra attributes to emit on specific generated record fields and
271    /// enum/variant cases.
272    ///
273    /// As `additional_type_attributes`, except the selector is a type's fully
274    /// qualified name, a `.`, and the member name.
275    ///
276    /// In a CLI, this flag can be specified multiple times as
277    /// `selector=attribute`.
278    #[cfg_attr(feature = "clap", arg(long, value_name = "SELECTOR=ATTR", value_parser = parse_attribute))]
279    pub additional_member_attributes: Vec<(String, String)>,
280
281    /// Remapping of wit import interface and type names to Rust module names
282    /// and types.
283    ///
284    /// Argument must be of the form `k=v` and this option can be passed
285    /// multiple times or one option can be comma separated, for example
286    /// `k1=v1,k2=v2`.
287    #[cfg_attr(feature = "clap", arg(long, value_parser = parse_with, value_delimiter = ','))]
288    pub with: Vec<(String, WithOption)>,
289
290    /// Indicates that all interfaces not specified in `with` should be
291    /// generated.
292    #[cfg_attr(feature = "clap", arg(long))]
293    pub generate_all: bool,
294
295    /// Add the specified suffix to the name of the custome section containing
296    /// the component type.
297    #[cfg_attr(feature = "clap", arg(long, value_name = "STRING"))]
298    pub type_section_suffix: Option<String>,
299
300    /// Disable a workaround used to prevent libc ctors/dtors from being invoked
301    /// too much.
302    #[cfg_attr(feature = "clap", arg(long))]
303    pub disable_run_ctors_once_workaround: bool,
304
305    /// Changes the default module used in the generated `export!` macro to
306    /// something other than `self`.
307    #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
308    pub default_bindings_module: Option<String>,
309
310    /// Alternative name to use for the `export!` macro if one is generated.
311    #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
312    pub export_macro_name: Option<String>,
313
314    /// Ensures that the `export!` macro will be defined as `pub` so it is a
315    /// candidate for being exported outside of the crate.
316    #[cfg_attr(feature = "clap", arg(long))]
317    pub pub_export_macro: bool,
318
319    /// Whether to generate unused structures, not generated by default (false)
320    #[cfg_attr(feature = "clap", arg(long))]
321    pub generate_unused_types: bool,
322
323    /// Whether or not to generate helper function/constants to help link custom
324    /// sections into the final output.
325    ///
326    /// Disabling this can shave a few bytes off a binary but makes
327    /// library-based usage of `generate!` prone to breakage.
328    #[cfg_attr(feature = "clap", arg(long))]
329    pub disable_custom_section_link_helpers: bool,
330
331    #[cfg_attr(feature = "clap", clap(flatten))]
332    #[cfg_attr(feature = "serde", serde(flatten))]
333    pub async_: AsyncFilterSet,
334
335    /// Find all structurally equal types and only generate one type definition
336    /// for each equivalence class.
337    ///
338    /// Other types in the same class will be type aliases to the generated
339    /// type. This avoids clone when converting between types that are
340    /// structurally equal, which is useful when import and export the same
341    /// interface.
342    #[cfg_attr(
343        feature = "clap",
344        arg(long, require_equals = true, value_name = "true|false")
345    )]
346    pub merge_structurally_equal_types: Option<Option<bool>>,
347
348    #[cfg_attr(feature = "clap", clap(flatten))]
349    #[cfg_attr(feature = "serde", serde(flatten))]
350    pub chainable_methods: ChainableMethodFilterSet,
351}
352
353impl Opts {
354    pub fn build(self) -> RustWasm {
355        let mut r = RustWasm::new();
356        r.skip = self.skip.iter().cloned().collect();
357        r.opts = self;
358        r
359    }
360
361    fn merge_structurally_equal_types(&self) -> bool {
362        const DEFAULT: bool = false;
363        match self.merge_structurally_equal_types {
364            // no option passed, use the default
365            None => DEFAULT,
366            // --merge-structurally-equal-types
367            Some(None) => true,
368            // --merge-structurally-equal-types=val
369            Some(Some(val)) => val,
370        }
371    }
372}
373
374impl RustWasm {
375    /// Generates Rust bindings from the `wit/` directory and writes
376    /// the result into Cargo’s `OUT_DIR`. Intended for use in `build.rs`.
377    ///
378    /// The `world` parameter specifies the world name to select.
379    /// It must be provided unless the main package contains exactly one world.
380    ///
381    /// Returns the full path to the generated bindings file.
382    pub fn generate_to_out_dir(mut self, world: Option<&str>) -> Result<PathBuf> {
383        let mut resolve = Resolve::default();
384        println!("cargo:rerun-if-changed=wit/");
385        let (pkg, _files) = resolve.push_path("wit")?;
386        let main_packages = vec![pkg];
387        let world = resolve.select_world(&main_packages, world)?;
388
389        let mut files = Files::default();
390        self.generate(&mut resolve, world, &mut files)?;
391        let out_dir = std::env::var("OUT_DIR").expect("cargo sets OUT_DIR");
392        let (name, contents) = files
393            .iter()
394            .next()
395            .expect("exactly one file should be generated");
396        let dst = Path::new(&out_dir).join(name);
397        std::fs::write(&dst, contents)?;
398        Ok(dst)
399    }
400
401    fn new() -> RustWasm {
402        RustWasm::default()
403    }
404
405    fn interface<'a>(
406        &'a mut self,
407        identifier: Identifier<'a>,
408        wasm_import_module: &'a str,
409        resolve: &'a Resolve,
410        in_import: bool,
411    ) -> InterfaceGenerator<'a> {
412        let mut sizes = SizeAlign::default();
413        sizes.fill(resolve);
414
415        InterfaceGenerator {
416            identifier,
417            wasm_import_module,
418            src: Source::default(),
419            in_import,
420            r#gen: self,
421            sizes,
422            resolve,
423            return_pointer_area_size: Default::default(),
424            return_pointer_area_align: Default::default(),
425            needs_runtime_module: false,
426            needs_wit_map: false,
427        }
428    }
429
430    fn emit_modules(&mut self, modules: Vec<(String, Vec<String>)>) {
431        #[derive(Default)]
432        struct Module {
433            submodules: BTreeMap<String, Module>,
434            contents: Vec<String>,
435        }
436        let mut map = Module::default();
437        for (module, path) in modules {
438            let mut cur = &mut map;
439            for name in path[..path.len() - 1].iter() {
440                cur = cur
441                    .submodules
442                    .entry(name.clone())
443                    .or_insert(Module::default());
444            }
445            cur.contents.push(module);
446        }
447
448        emit(&mut self.src, map, &self.opts, true);
449        fn emit(me: &mut Source, module: Module, opts: &Opts, toplevel: bool) {
450            for (name, submodule) in module.submodules {
451                if toplevel {
452                    // Disable rustfmt. By default we already format the code
453                    // using prettyplease, so we don't want `cargo fmt` to create
454                    // extra diffs for users to deal with.
455                    if opts.format {
456                        uwriteln!(me, "#[rustfmt::skip]");
457                    }
458
459                    // Ignore dead-code and clippy warnings. If the bindings are
460                    // only used within a crate, and not exported to a different
461                    // crate, some parts may be unused, and that's ok.
462                    uwriteln!(me, "#[allow(dead_code, clippy::all)]");
463                }
464
465                uwriteln!(me, "pub mod {name} {{");
466                emit(me, submodule, opts, false);
467                uwriteln!(me, "}}");
468            }
469            for submodule in module.contents {
470                uwriteln!(me, "{submodule}");
471            }
472        }
473    }
474
475    fn runtime_path(&self) -> &str {
476        self.opts
477            .runtime_path
478            .as_deref()
479            .unwrap_or("wit_bindgen::rt")
480    }
481
482    fn map_type_path(&self) -> String {
483        self.opts
484            .map_type
485            .clone()
486            .unwrap_or_else(|| format!("{}::Map", self.runtime_path()))
487    }
488
489    fn wit_map_path(&self) -> String {
490        format!("{}::WitMap", self.runtime_path())
491    }
492
493    fn bitflags_path(&self) -> String {
494        self.opts
495            .bitflags_path
496            .to_owned()
497            .unwrap_or(format!("{}::bitflags", self.runtime_path()))
498    }
499
500    fn async_support_path(&self) -> String {
501        format!("{}::async_support", self.runtime_path())
502    }
503
504    fn name_interface(
505        &mut self,
506        resolve: &Resolve,
507        id: InterfaceId,
508        name: &WorldKey,
509        is_export: bool,
510    ) -> Result<bool> {
511        let with_name = resolve.name_world_key(name);
512        let remapping = if is_export {
513            &TypeGeneration::Generate
514        } else {
515            match self.with.get(&with_name) {
516                Some(remapping) => remapping,
517                None => bail!(MissingWith(with_name)),
518            }
519        };
520        self.generated_types.insert(with_name);
521        let entry = match remapping {
522            TypeGeneration::Remap(remapped_path) => {
523                let name = format!("__with_name{}", self.with_name_counter);
524                self.with_name_counter += 1;
525                uwriteln!(
526                    self.src,
527                    "#[allow(unfulfilled_lint_expectations, unused_imports)]"
528                );
529                uwriteln!(self.src, "use {remapped_path} as {name};");
530                InterfaceName {
531                    remapped: true,
532                    path: name,
533                }
534            }
535            TypeGeneration::Generate => {
536                let path = compute_module_path(name, resolve, is_export).join("::");
537
538                InterfaceName {
539                    remapped: false,
540                    path,
541                }
542            }
543        };
544
545        let remapped = entry.remapped;
546        let prev = self.interface_names.insert(id, entry);
547        assert!(prev.is_none());
548
549        Ok(remapped)
550    }
551
552    fn finish_runtime_module(&mut self) {
553        if !self.rt_module.is_empty() {
554            // As above, disable rustfmt, as we use prettyplease.
555            if self.opts.format {
556                uwriteln!(self.src, "#[rustfmt::skip]");
557            }
558
559            self.src.push_str("mod _rt {\n");
560            self.src
561                .push_str("#![allow(dead_code, unused_imports, clippy::all)]\n");
562            let mut emitted = IndexSet::new();
563            while !self.rt_module.is_empty() {
564                for item in mem::take(&mut self.rt_module) {
565                    if emitted.insert(item) {
566                        self.emit_runtime_item(item);
567                    }
568                }
569            }
570            self.src.push_str("}\n");
571        }
572
573        if !self.future_payloads.is_empty() {
574            let async_support = self.async_support_path();
575            self.src.push_str(&format!(
576                "\
577pub mod wit_future {{
578    #![allow(dead_code, unused_variables, clippy::all)]
579
580    #[doc(hidden)]
581    pub trait FuturePayload: Unpin + Sized + 'static {{
582        const VTABLE: &'static {async_support}::FutureVtable<Self>;
583    }}"
584            ));
585            for code in self.future_payloads.values() {
586                self.src.push_str(code);
587            }
588            self.src.push_str(&format!(
589                "\
590    /// Creates a new Component Model `future` with the specified payload type.
591    ///
592    /// The `default` function provided computes the default value to be sent in
593    /// this future if no other value was otherwise sent.
594    pub fn new<T: FuturePayload>(default: fn() -> T) -> ({async_support}::FutureWriter<T>, {async_support}::FutureReader<T>) {{
595        unsafe {{ {async_support}::future_new::<T>(default, T::VTABLE) }}
596    }}
597}}
598                ",
599            ));
600        }
601
602        if !self.stream_payloads.is_empty() {
603            let async_support = self.async_support_path();
604            self.src.push_str(&format!(
605                "\
606pub mod wit_stream {{
607    #![allow(dead_code, unused_variables, clippy::all)]
608
609    pub trait StreamPayload: Unpin + Sized + 'static {{
610        const VTABLE: &'static {async_support}::StreamVtable<Self>;
611    }}"
612            ));
613            for code in self.stream_payloads.values() {
614                self.src.push_str(code);
615            }
616            self.src.push_str(
617                &format!("\
618    /// Creates a new Component Model `stream` with the specified payload type.
619    pub fn new<T: StreamPayload>() -> ({async_support}::StreamWriter<T>, {async_support}::StreamReader<T>) {{
620        unsafe {{ {async_support}::stream_new::<T>(T::VTABLE) }}
621    }}
622}}
623                "),
624            );
625        }
626    }
627
628    fn emit_runtime_item(&mut self, item: RuntimeItem) {
629        match item {
630            RuntimeItem::AllocCrate => {
631                uwriteln!(self.src, "extern crate alloc as alloc_crate;");
632            }
633            RuntimeItem::StdAllocModule => {
634                self.rt_module.insert(RuntimeItem::AllocCrate);
635                uwriteln!(self.src, "pub use alloc_crate::alloc;");
636            }
637            RuntimeItem::StringType => {
638                self.rt_module.insert(RuntimeItem::AllocCrate);
639                uwriteln!(self.src, "pub use alloc_crate::string::String;");
640            }
641            RuntimeItem::BoxType => {
642                self.rt_module.insert(RuntimeItem::AllocCrate);
643                uwriteln!(self.src, "pub use alloc_crate::boxed::Box;");
644            }
645            RuntimeItem::VecType => {
646                self.rt_module.insert(RuntimeItem::AllocCrate);
647                uwriteln!(self.src, "pub use alloc_crate::vec::Vec;");
648            }
649            RuntimeItem::CabiDealloc => {
650                self.rt_module.insert(RuntimeItem::StdAllocModule);
651                self.src.push_str(
652                    "\
653pub unsafe fn cabi_dealloc(ptr: *mut u8, size: usize, align: usize) {
654    if size == 0 {
655        return;
656    }
657    unsafe {
658        let layout = alloc::Layout::from_size_align_unchecked(size, align);
659        alloc::dealloc(ptr, layout);
660    }
661}
662                    ",
663                );
664            }
665
666            RuntimeItem::StringLift => {
667                self.rt_module.insert(RuntimeItem::StringType);
668                self.src.push_str(
669                    "\
670pub unsafe fn string_lift(bytes: Vec<u8>) -> String {
671    if cfg!(debug_assertions) {
672        String::from_utf8(bytes).unwrap()
673    } else {
674        unsafe { String::from_utf8_unchecked(bytes) }
675    }
676}
677                    ",
678                );
679            }
680
681            RuntimeItem::InvalidEnumDiscriminant => {
682                self.src.push_str(
683                    "\
684pub unsafe fn invalid_enum_discriminant<T>() -> T {
685    if cfg!(debug_assertions) {
686        panic!(\"invalid enum discriminant\")
687    } else {
688        unsafe { core::hint::unreachable_unchecked() }
689    }
690}
691                    ",
692                );
693            }
694
695            RuntimeItem::CharLift => {
696                self.src.push_str(
697                    "\
698pub unsafe fn char_lift(val: u32) -> char {
699    if cfg!(debug_assertions) {
700        core::char::from_u32(val).unwrap()
701    } else {
702        unsafe { core::char::from_u32_unchecked(val) }
703    }
704}
705                    ",
706                );
707            }
708
709            RuntimeItem::BoolLift => {
710                self.src.push_str(
711                    "\
712pub unsafe fn bool_lift(val: u8) -> bool {
713    if cfg!(debug_assertions) {
714        match val {
715            0 => false,
716            1 => true,
717            _ => panic!(\"invalid bool discriminant\"),
718        }
719    } else {
720        val != 0
721    }
722}
723                    ",
724                );
725            }
726
727            RuntimeItem::RunCtorsOnce => {
728                let rt = self.runtime_path();
729                self.src.push_str(&format!(
730                    r#"
731#[cfg(target_arch = "wasm32")]
732pub fn run_ctors_once() {{
733    {rt}::run_ctors_once();
734}}
735                    "#,
736                ));
737            }
738
739            RuntimeItem::AsI32 => {
740                self.emit_runtime_as_trait(
741                    "i32",
742                    &["i32", "u32", "i16", "u16", "i8", "u8", "char", "usize"],
743                );
744            }
745
746            RuntimeItem::AsI64 => {
747                self.emit_runtime_as_trait("i64", &["i64", "u64"]);
748            }
749
750            RuntimeItem::AsF32 => {
751                self.emit_runtime_as_trait("f32", &["f32"]);
752            }
753
754            RuntimeItem::AsF64 => {
755                self.emit_runtime_as_trait("f64", &["f64"]);
756            }
757
758            RuntimeItem::WitMapTrait => {
759                let rt = self.runtime_path().to_string();
760                uwriteln!(self.src, "pub use {rt}::WitMap;");
761            }
762
763            RuntimeItem::ResourceType => {
764                self.src.push_str(
765                    r#"
766
767use core::fmt;
768use core::marker;
769use core::sync::atomic::{AtomicU32, Ordering::Relaxed};
770
771/// A type which represents a component model resource, either imported or
772/// exported into this component.
773///
774/// This is a low-level wrapper which handles the lifetime of the resource
775/// (namely this has a destructor). The `T` provided defines the component model
776/// intrinsics that this wrapper uses.
777///
778/// One of the chief purposes of this type is to provide `Deref` implementations
779/// to access the underlying data when it is owned.
780///
781/// This type is primarily used in generated code for exported and imported
782/// resources.
783#[repr(transparent)]
784pub struct Resource<T: WasmResource> {
785    // NB: This would ideally be `u32` but it is not. The fact that this has
786    // interior mutability is not exposed in the API of this type except for the
787    // `take_handle` method which is supposed to in theory be private.
788    //
789    // This represents, almost all the time, a valid handle value. When it's
790    // invalid it's stored as `u32::MAX`.
791    handle: AtomicU32,
792    _marker: marker::PhantomData<T>,
793}
794
795/// A trait which all wasm resources implement, namely providing the ability to
796/// drop a resource.
797///
798/// This generally is implemented by generated code, not user-facing code.
799#[allow(clippy::missing_safety_doc)]
800pub unsafe trait WasmResource {
801    /// Invokes the `[resource-drop]...` intrinsic.
802    unsafe fn drop(handle: u32);
803}
804
805impl<T: WasmResource> Resource<T> {
806    #[doc(hidden)]
807    pub unsafe fn from_handle(handle: u32) -> Self {
808        debug_assert!(handle != 0 && handle != u32::MAX);
809        Self {
810            handle: AtomicU32::new(handle),
811            _marker: marker::PhantomData,
812        }
813    }
814
815    /// Takes ownership of the handle owned by `resource`.
816    ///
817    /// Note that this ideally would be `into_handle` taking `Resource<T>` by
818    /// ownership. The code generator does not enable that in all situations,
819    /// unfortunately, so this is provided instead.
820    ///
821    /// Also note that `take_handle` is in theory only ever called on values
822    /// owned by a generated function. For example a generated function might
823    /// take `Resource<T>` as an argument but then call `take_handle` on a
824    /// reference to that argument. In that sense the dynamic nature of
825    /// `take_handle` should only be exposed internally to generated code, not
826    /// to user code.
827    #[doc(hidden)]
828    pub fn take_handle(resource: &Resource<T>) -> u32 {
829        resource.handle.swap(u32::MAX, Relaxed)
830    }
831
832    #[doc(hidden)]
833    pub fn handle(resource: &Resource<T>) -> u32 {
834        resource.handle.load(Relaxed)
835    }
836}
837
838impl<T: WasmResource> fmt::Debug for Resource<T> {
839    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
840        f.debug_struct("Resource")
841            .field("handle", &self.handle)
842            .finish()
843    }
844}
845
846impl<T: WasmResource> Drop for Resource<T> {
847    fn drop(&mut self) {
848        unsafe {
849            match self.handle.load(Relaxed) {
850                // If this handle was "taken" then don't do anything in the
851                // destructor.
852                u32::MAX => {}
853
854                // ... but otherwise do actually destroy it with the imported
855                // component model intrinsic as defined through `T`.
856                other => T::drop(other),
857            }
858        }
859    }
860}
861                    "#,
862                );
863            }
864        }
865    }
866
867    // This is a workaround for in the bindings sometimes we've got `&i32` and
868    // sometimes we've got `i32` but that should all be able to be worked with
869    // as `i32`, so these helper functions are used to boil away the
870    // indirection.
871    fn emit_runtime_as_trait(&mut self, ty: &str, to_convert: &[&str]) {
872        let upcase = ty.to_uppercase();
873        self.src.push_str(&format!(
874            r#"
875pub fn as_{ty}<T: As{upcase}>(t: T) -> {ty} {{
876    t.as_{ty}()
877}}
878
879pub trait As{upcase} {{
880    fn as_{ty}(self) -> {ty};
881}}
882
883impl<'a, T: Copy + As{upcase}> As{upcase} for &'a T {{
884    fn as_{ty}(self) -> {ty} {{
885        (*self).as_{ty}()
886    }}
887}}
888            "#
889        ));
890
891        for to_convert in to_convert {
892            self.src.push_str(&format!(
893                r#"
894impl As{upcase} for {to_convert} {{
895    #[inline]
896    fn as_{ty}(self) -> {ty} {{
897        self as {ty}
898    }}
899}}
900                "#
901            ));
902        }
903    }
904
905    /// Generates an `export!` macro for the `world_id` specified.
906    ///
907    /// This will generate a macro which will then itself invoke all the
908    /// other macros collected in `self.export_macros` prior. All these macros
909    /// are woven together in this single invocation.
910    fn finish_export_macro(&mut self, resolve: &Resolve, world_id: WorldId) {
911        if self.export_macros.is_empty() {
912            return;
913        }
914        let world = &resolve.worlds[world_id];
915        let world_name = world.name.to_snake_case();
916
917        let default_bindings_module = self
918            .opts
919            .default_bindings_module
920            .clone()
921            .unwrap_or("self".to_string());
922        let (macro_export, use_vis) = if self.opts.pub_export_macro {
923            ("#[macro_export]", "pub")
924        } else {
925            ("", "pub(crate)")
926        };
927        let export_macro_name = self
928            .opts
929            .export_macro_name
930            .as_deref()
931            .unwrap_or("export")
932            .to_string();
933        uwriteln!(
934            self.src,
935            r#"
936/// Generates `#[unsafe(no_mangle)]` functions to export the specified type as
937/// the root implementation of all generated traits.
938///
939/// For more information see the documentation of `wit_bindgen::generate!`.
940///
941/// ```rust
942/// # macro_rules! {export_macro_name} {{ ($($t:tt)*) => (); }}
943/// # trait Guest {{}}
944/// struct MyType;
945///
946/// impl Guest for MyType {{
947///     // ...
948/// }}
949///
950/// {export_macro_name}!(MyType);
951/// ```
952#[allow(unused_macros)]
953#[doc(hidden)]
954{macro_export}
955macro_rules! __export_{world_name}_impl {{
956    ($ty:ident) => ({default_bindings_module}::{export_macro_name}!($ty with_types_in {default_bindings_module}););
957    ($ty:ident with_types_in $($path_to_types_root:tt)*) => ("#
958        );
959        for (name, path_to_types) in self.export_macros.iter() {
960            let mut path = "$($path_to_types_root)*".to_string();
961            if !path_to_types.is_empty() {
962                path.push_str("::");
963                path.push_str(path_to_types)
964            }
965            uwriteln!(self.src, "{path}::{name}!($ty with_types_in {path});");
966        }
967
968        // See comments in `finish` for why this conditionally happens here.
969        if self.opts.pub_export_macro {
970            uwriteln!(self.src, "const _: () = {{");
971            self.emit_custom_section(resolve, world_id, "imports and exports", None);
972            uwriteln!(self.src, "}};");
973        }
974
975        uwriteln!(self.src, ")\n}}");
976
977        uwriteln!(
978            self.src,
979            "#[doc(inline)]\n\
980            {use_vis} use __export_{world_name}_impl as {export_macro_name};"
981        );
982
983        if self.opts.stubs {
984            uwriteln!(self.src, "export!(Stub);");
985        }
986    }
987
988    /// Generates a `#[link_section]` custom section to get smuggled through
989    /// `wasm-ld`.
990    ///
991    /// This custom section is an encoding of the component metadata and will be
992    /// used as part of the `wit-component`-based componentization process.
993    ///
994    /// The `section_suffix` here is used to distinguish the multiple sections
995    /// that this generator emits, and `func_name` is an optional function to
996    /// generate next to this which is used to force rustc to at least visit
997    /// this `static` and codegen it.
998    fn emit_custom_section(
999        &mut self,
1000        resolve: &Resolve,
1001        world_id: WorldId,
1002        section_suffix: &str,
1003        func_name: Option<&str>,
1004    ) {
1005        // As above, disable rustfmt, as we use prettyplease.
1006        if self.opts.format {
1007            uwriteln!(self.src, "#[rustfmt::skip]");
1008        }
1009        self.src.push_str("\n#[cfg(target_arch = \"wasm32\")]\n");
1010
1011        // The custom section name here must start with "component-type" but
1012        // otherwise is attempted to be unique here to ensure that this doesn't get
1013        // concatenated to other custom sections by LLD by accident since LLD will
1014        // concatenate custom sections of the same name.
1015        let opts_suffix = self.opts.type_section_suffix.as_deref().unwrap_or("");
1016        let world = &resolve.worlds[world_id];
1017        let world_name = &world.name;
1018        let pkg = &resolve.packages[world.package.unwrap()].name;
1019        let version = env!("CARGO_PKG_VERSION");
1020        self.src.push_str(&format!(
1021            "#[unsafe(link_section = \"component-type:wit-bindgen:{version}:\
1022             {pkg}:{world_name}:{section_suffix}{opts_suffix}\")]\n"
1023        ));
1024
1025        let mut producers = wasm_metadata::Producers::empty();
1026        producers.add(
1027            "processed-by",
1028            env!("CARGO_PKG_NAME"),
1029            env!("CARGO_PKG_VERSION"),
1030        );
1031
1032        let component_type = wit_component::metadata::encode(
1033            resolve,
1034            world_id,
1035            wit_component::StringEncoding::UTF8,
1036            Some(&producers),
1037        )
1038        .unwrap();
1039
1040        self.src.push_str("#[doc(hidden)]\n");
1041        self.src.push_str("#[allow(clippy::octal_escapes)]\n");
1042        self.src.push_str(&format!(
1043            "pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; {}] = *b\"\\\n",
1044            component_type.len()
1045        ));
1046        let old_indent = self.src.set_indent(0);
1047        let mut line_length = 0;
1048        let s = self.src.as_mut_string();
1049        for byte in component_type.iter() {
1050            if line_length >= 80 {
1051                s.push_str("\\\n");
1052                line_length = 0;
1053            }
1054            match byte {
1055                b'\\' => {
1056                    s.push_str("\\\\");
1057                    line_length += 2;
1058                }
1059                b'"' => {
1060                    s.push_str("\\\"");
1061                    line_length += 2;
1062                }
1063                b if b.is_ascii_alphanumeric() || b.is_ascii_punctuation() => {
1064                    s.push(char::from(*byte));
1065                    line_length += 1;
1066                }
1067                0 => {
1068                    s.push_str("\\0");
1069                    line_length += 2;
1070                }
1071                _ => {
1072                    uwrite!(s, "\\x{:02x}", byte);
1073                    line_length += 4;
1074                }
1075            }
1076        }
1077
1078        self.src.push_str("\";\n");
1079        self.src.set_indent(old_indent);
1080
1081        if let Some(func_name) = func_name {
1082            let rt = self.runtime_path().to_string();
1083            uwriteln!(
1084                self.src,
1085                "
1086                #[inline(never)]
1087                #[doc(hidden)]
1088                pub fn {func_name}() {{
1089                    {rt}::maybe_link_cabi_realloc();
1090                }}
1091            ",
1092            );
1093        }
1094    }
1095
1096    fn is_async(
1097        &mut self,
1098        resolve: &Resolve,
1099        interface: Option<&WorldKey>,
1100        func: &Function,
1101        is_import: bool,
1102    ) -> bool {
1103        self.opts
1104            .async_
1105            .is_async(resolve, interface, func, is_import)
1106    }
1107
1108    fn should_return_self(
1109        &mut self,
1110        resolve: &Resolve,
1111        interface: Option<&WorldKey>,
1112        func: &Function,
1113        is_import: bool,
1114    ) -> Option<ChainingMode> {
1115        return self
1116            .opts
1117            .chainable_methods
1118            .should_be_chainable(resolve, interface, func, is_import);
1119    }
1120}
1121
1122impl WorldGenerator for RustWasm {
1123    fn preprocess(&mut self, resolve: &Resolve, world: WorldId) -> Result<()> {
1124        wit_bindgen_core::generated_preamble(&mut self.src_preamble, env!("CARGO_PKG_VERSION"));
1125
1126        // Render some generator options to assist with debugging and/or to help
1127        // recreate it if the original generation command is lost.
1128        uwriteln!(self.src_preamble, "// Options used:");
1129        if self.opts.std_feature {
1130            uwriteln!(self.src_preamble, "//   * std_feature");
1131        }
1132        if self.opts.raw_strings {
1133            uwriteln!(self.src_preamble, "//   * raw_strings");
1134        }
1135        if !self.opts.skip.is_empty() {
1136            uwriteln!(self.src_preamble, "//   * skip: {:?}", self.opts.skip);
1137        }
1138        if self.opts.stubs {
1139            uwriteln!(self.src_preamble, "//   * stubs");
1140        }
1141        if let Some(export_prefix) = &self.opts.export_prefix {
1142            uwriteln!(
1143                self.src_preamble,
1144                "//   * export_prefix: {:?}",
1145                export_prefix
1146            );
1147        }
1148        if let Some(runtime_path) = &self.opts.runtime_path {
1149            uwriteln!(self.src_preamble, "//   * runtime_path: {:?}", runtime_path);
1150        }
1151        if let Some(map_type) = &self.opts.map_type {
1152            uwriteln!(self.src_preamble, "//   * map_type: {:?}", map_type);
1153        }
1154        if let Some(bitflags_path) = &self.opts.bitflags_path {
1155            uwriteln!(
1156                self.src_preamble,
1157                "//   * bitflags_path: {:?}",
1158                bitflags_path
1159            );
1160        }
1161        if !matches!(self.opts.ownership, Ownership::Owning) {
1162            uwriteln!(
1163                self.src_preamble,
1164                "//   * ownership: {:?}",
1165                self.opts.ownership
1166            );
1167        }
1168        if !self.opts.additional_derive_attributes.is_empty() {
1169            uwriteln!(
1170                self.src_preamble,
1171                "//   * additional derives {:?}",
1172                self.opts.additional_derive_attributes
1173            );
1174        }
1175        if !self.opts.additional_derive_ignore.is_empty() {
1176            uwriteln!(
1177                self.src_preamble,
1178                "//   * additional derives ignored {:?}",
1179                self.opts.additional_derive_ignore
1180            );
1181        }
1182        for (selector, attr) in self.opts.additional_type_attributes.iter() {
1183            uwriteln!(
1184                self.src_preamble,
1185                "//   * additional type attribute {selector:?} = {attr:?}"
1186            );
1187        }
1188        for (selector, attr) in self.opts.additional_member_attributes.iter() {
1189            uwriteln!(
1190                self.src_preamble,
1191                "//   * additional member attribute {selector:?} = {attr:?}"
1192            );
1193        }
1194        for (k, v) in self.opts.with.iter() {
1195            uwriteln!(self.src_preamble, "//   * with {k:?} = {v}");
1196        }
1197        if let Some(type_section_suffix) = &self.opts.type_section_suffix {
1198            uwriteln!(
1199                self.src_preamble,
1200                "//   * type_section_suffix: {:?}",
1201                type_section_suffix
1202            );
1203        }
1204        if let Some(default) = &self.opts.default_bindings_module {
1205            uwriteln!(
1206                self.src_preamble,
1207                "//   * default-bindings-module: {default:?}"
1208            );
1209        }
1210        if self.opts.disable_run_ctors_once_workaround {
1211            uwriteln!(
1212                self.src_preamble,
1213                "//   * disable-run-ctors-once-workaround"
1214            );
1215        }
1216        if self.opts.merge_structurally_equal_types() {
1217            uwriteln!(self.src_preamble, "//   * merge_structurally_equal_types");
1218        }
1219        if let Some(s) = &self.opts.export_macro_name {
1220            uwriteln!(self.src_preamble, "//   * export-macro-name: {s}");
1221        }
1222        if self.opts.pub_export_macro {
1223            uwriteln!(self.src_preamble, "//   * pub-export-macro");
1224        }
1225        if self.opts.generate_unused_types {
1226            uwriteln!(self.src_preamble, "//   * generate_unused_types");
1227        }
1228        if self.opts.disable_custom_section_link_helpers {
1229            uwriteln!(
1230                self.src_preamble,
1231                "//   * disable_custom_section_link_helpers"
1232            );
1233        }
1234        for opt in self.opts.async_.debug_opts() {
1235            uwriteln!(self.src_preamble, "//   * async: {opt}");
1236        }
1237        for opt in self.opts.chainable_methods.debug_opts() {
1238            uwriteln!(self.src_preamble, "//   * chainable-methods: {opt}");
1239        }
1240        self.types.analyze(resolve);
1241        self.types.collect_equal_types(resolve, world, &|a| {
1242            // If `--merge-structurally-equal-types` is enabled then any type
1243            // anywhere can be generated as a type alias to anything else.
1244            if self.opts.merge_structurally_equal_types() {
1245                return true;
1246            }
1247
1248            match resolve.types[a].kind {
1249                // These types are all defined with `type Foo = ...` in Rust
1250                // since Rust either has native representations or they live in
1251                // libraries or similar.
1252                TypeDefKind::Type(_)
1253                | TypeDefKind::Handle(_)
1254                | TypeDefKind::List(_)
1255                | TypeDefKind::Tuple(_)
1256                | TypeDefKind::Option(_)
1257                | TypeDefKind::Result(_)
1258                | TypeDefKind::Future(_)
1259                | TypeDefKind::Stream(_)
1260                | TypeDefKind::Map(..)
1261                | TypeDefKind::FixedLengthList(..) => true,
1262
1263                // These types are all defined with fresh new types defined
1264                // in generated bindings and thus can't alias some other
1265                // existing type.
1266                TypeDefKind::Record(_)
1267                | TypeDefKind::Variant(_)
1268                | TypeDefKind::Enum(_)
1269                | TypeDefKind::Flags(_)
1270                | TypeDefKind::Resource
1271                | TypeDefKind::Unknown => false,
1272            }
1273        });
1274        self.world = Some(world);
1275
1276        let world = &resolve.worlds[world];
1277        // Specify that all imports local to the world's package should be
1278        // generated
1279        for (key, item) in world.imports.iter() {
1280            if let WorldItem::Interface { id, .. } = item {
1281                if resolve.interfaces[*id].package == world.package {
1282                    let name = resolve.name_world_key(key);
1283                    if self.with.get(&name).is_none() {
1284                        self.with.insert(name, TypeGeneration::Generate);
1285                    }
1286                }
1287            }
1288        }
1289
1290        for item in world.exports.values() {
1291            let WorldItem::Interface { id, .. } = item else {
1292                continue;
1293            };
1294            for id in resolve.interfaces[*id].types.values().copied() {
1295                let TypeDefKind::Resource = &resolve.types[id].kind else {
1296                    continue;
1297                };
1298                assert!(self.exported_resources.insert(id));
1299            }
1300        }
1301
1302        for (k, v) in self.opts.with.iter() {
1303            self.with.insert(k.clone(), v.clone().into());
1304        }
1305        self.with.generate_by_default = self.opts.generate_all;
1306        for (key, item) in world.imports.iter() {
1307            if let WorldItem::Interface { id, .. } = item {
1308                self.name_interface(resolve, *id, &key, false)?;
1309            }
1310        }
1311        for (key, item) in world.exports.iter() {
1312            if let WorldItem::Interface { id, .. } = item {
1313                self.name_interface(resolve, *id, &key, true)?;
1314            }
1315        }
1316        Ok(())
1317    }
1318
1319    fn import_interface(
1320        &mut self,
1321        resolve: &Resolve,
1322        name: &WorldKey,
1323        id: InterfaceId,
1324        _files: &mut Files,
1325    ) -> Result<()> {
1326        let mut to_define = Vec::new();
1327        for (name, ty_id) in resolve.interfaces[id].types.iter() {
1328            let full_name = full_wit_type_name(resolve, *ty_id);
1329            if let Some(type_gen) = self.with.get(&full_name) {
1330                // skip type definition generation for remapped types
1331                if type_gen.generated() {
1332                    to_define.push((name, ty_id));
1333                }
1334            } else {
1335                to_define.push((name, ty_id));
1336            }
1337            self.generated_types.insert(full_name);
1338        }
1339
1340        let wasm_import_module = resolve.name_world_key(name);
1341        let mut r#gen = self.interface(
1342            Identifier::Interface(id, name),
1343            &wasm_import_module,
1344            resolve,
1345            true,
1346        );
1347        let (snake, module_path) = r#gen.start_append_submodule(name);
1348        if r#gen.r#gen.interface_names[&id].remapped {
1349            return Ok(());
1350        }
1351
1352        for (name, ty_id) in to_define {
1353            r#gen.define_type(&name, *ty_id);
1354        }
1355
1356        r#gen.generate_imports(resolve.interfaces[id].functions.values(), Some(name));
1357
1358        let docs = &resolve.interfaces[id].docs;
1359
1360        r#gen.finish_append_submodule(&snake, module_path, docs);
1361
1362        Ok(())
1363    }
1364
1365    fn import_funcs(
1366        &mut self,
1367        resolve: &Resolve,
1368        world: WorldId,
1369        funcs: &[(&str, &Function)],
1370        _files: &mut Files,
1371    ) {
1372        self.import_funcs_called = true;
1373
1374        let mut r#gen = self.interface(Identifier::World(world), "$root", resolve, true);
1375
1376        r#gen.generate_imports(funcs.iter().map(|(_, func)| *func), None);
1377
1378        let src = r#gen.finish();
1379        self.src.push_str(&src);
1380    }
1381
1382    fn export_interface(
1383        &mut self,
1384        resolve: &Resolve,
1385        name: &WorldKey,
1386        id: InterfaceId,
1387        _files: &mut Files,
1388    ) -> Result<()> {
1389        let mut to_define = Vec::new();
1390        for (ty_name, ty_id) in resolve.interfaces[id].types.iter() {
1391            let full_name = full_wit_type_name(resolve, *ty_id);
1392            to_define.push((ty_name, ty_id));
1393            self.generated_types.insert(full_name);
1394        }
1395
1396        let wasm_import_module = format!("[export]{}", resolve.name_world_key(name));
1397        let mut r#gen = self.interface(
1398            Identifier::Interface(id, name),
1399            &wasm_import_module,
1400            resolve,
1401            false,
1402        );
1403        let (snake, module_path) = r#gen.start_append_submodule(name);
1404        if r#gen.r#gen.interface_names[&id].remapped {
1405            return Ok(());
1406        }
1407
1408        for (ty_name, ty_id) in to_define {
1409            r#gen.define_type(&ty_name, *ty_id);
1410        }
1411
1412        let macro_name =
1413            r#gen.generate_exports(Some((id, name)), resolve.interfaces[id].functions.values())?;
1414
1415        let docs = &resolve.interfaces[id].docs;
1416
1417        r#gen.finish_append_submodule(&snake, module_path, docs);
1418        self.export_macros
1419            .push((macro_name, self.interface_names[&id].path.clone()));
1420
1421        if self.opts.stubs {
1422            let world_id = self.world.unwrap();
1423            let mut r#gen = self.interface(
1424                Identifier::World(world_id),
1425                &wasm_import_module,
1426                resolve,
1427                false,
1428            );
1429            r#gen.generate_stub(Some((id, name)), resolve.interfaces[id].functions.values());
1430            let stub = r#gen.finish();
1431            self.src.push_str(&stub);
1432        }
1433        Ok(())
1434    }
1435
1436    fn export_funcs(
1437        &mut self,
1438        resolve: &Resolve,
1439        world: WorldId,
1440        funcs: &[(&str, &Function)],
1441        _files: &mut Files,
1442    ) -> Result<()> {
1443        let mut r#gen = self.interface(Identifier::World(world), "[export]$root", resolve, false);
1444        let macro_name = r#gen.generate_exports(None, funcs.iter().map(|f| f.1))?;
1445        let src = r#gen.finish();
1446        self.src.push_str(&src);
1447        self.export_macros.push((macro_name, String::new()));
1448
1449        if self.opts.stubs {
1450            let mut r#gen =
1451                self.interface(Identifier::World(world), "[export]$root", resolve, false);
1452            r#gen.generate_stub(None, funcs.iter().map(|f| f.1));
1453            let stub = r#gen.finish();
1454            self.src.push_str(&stub);
1455        }
1456        Ok(())
1457    }
1458
1459    fn import_types(
1460        &mut self,
1461        resolve: &Resolve,
1462        world: WorldId,
1463        types: &[(&str, TypeId)],
1464        _files: &mut Files,
1465    ) {
1466        let mut to_define = Vec::new();
1467        for (name, ty_id) in types {
1468            let full_name = full_wit_type_name(resolve, *ty_id);
1469            if let Some(type_gen) = self.with.get(&full_name) {
1470                // skip type definition generation for remapped types
1471                if type_gen.generated() {
1472                    to_define.push((name, ty_id));
1473                }
1474            } else {
1475                to_define.push((name, ty_id));
1476            }
1477            self.generated_types.insert(full_name);
1478        }
1479        let mut r#gen = self.interface(Identifier::World(world), "$root", resolve, true);
1480        for (name, ty) in to_define {
1481            r#gen.define_type(name, *ty);
1482        }
1483        let src = r#gen.finish();
1484        self.src.push_str(&src);
1485    }
1486
1487    fn finish_imports(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) {
1488        if !self.import_funcs_called {
1489            // We call `import_funcs` even if the world doesn't import any
1490            // functions since one of the side effects of that method is to
1491            // generate `struct`s for any imported resources.
1492            self.import_funcs(resolve, world, &[], files);
1493        }
1494    }
1495
1496    fn finish(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) -> Result<()> {
1497        let name = &resolve.worlds[world].name;
1498
1499        let imports = mem::take(&mut self.import_modules);
1500        self.emit_modules(imports);
1501        let exports = mem::take(&mut self.export_modules);
1502        self.emit_modules(exports);
1503
1504        self.finish_runtime_module();
1505        self.finish_export_macro(resolve, world);
1506
1507        // This is a bit tricky, but we sometimes want to "split" the `world` in
1508        // two and only encode the imports here.
1509        //
1510        // First, a primer. Each invocation of `generate!` has a WIT world as
1511        // input. This is one of the first steps in the build process as wasm
1512        // hasn't even been produced yet. One of the later stages of the build
1513        // process will be to emit a component, currently through the
1514        // `wit-component` crate. That crate relies on custom sections being
1515        // present to describe what WIT worlds were present in the wasm binary.
1516        //
1517        // Additionally a `generate!` macro is not the only thing in a binary.
1518        // There might be multiple `generate!` macros, perhaps even across
1519        // different languages. To handle all this `wit-component` will decode
1520        // each custom section and "union" everything together. Unioning in
1521        // general should work so long as everything has the same structure and
1522        // came from the same source.
1523        //
1524        // The problem here is that if `pub_export_macros` is turned on, meaning
1525        // that the macros are supposed to be used across crates, then neither
1526        // the imports nor the exports of this world are guaranteed to be used.
1527        // For imports that's ok because `wit-component` will drop any unused
1528        // imports automatically. For exports that's a problem because
1529        // `wit-component` unconditionally looks for a definition for all
1530        // exports.
1531        //
1532        // When `pub_export_macros` is turned on, and cross-crate usage of the
1533        // macro is expected, this is solved by emitting two custom sections:
1534        //
1535        // 1. The first section emitted here only has the imports of the world.
1536        //    This slimmed down world should be able to be unioned with the
1537        //    first world trivially and will be GC'd by `wit-component` if not
1538        //    used.
1539        // 2. The second section is emitted as part of the generated `export!`
1540        //    macro invocation. That world has all the export information as
1541        //    well as all the import information.
1542        //
1543        // In the end this is hoped to ensure that usage of crates like `wasi`
1544        // don't accidentally try to export things, for example.
1545        let mut resolve_copy;
1546        let (resolve_to_encode, world_to_encode) = if self.opts.pub_export_macro {
1547            resolve_copy = resolve.clone();
1548            let world_copy = resolve_copy.worlds.alloc(World {
1549                exports: Default::default(),
1550                name: format!("{name}-with-all-of-its-exports-removed"),
1551                ..resolve.worlds[world].clone()
1552            });
1553            (&resolve_copy, world_copy)
1554        } else {
1555            (resolve, world)
1556        };
1557        self.emit_custom_section(
1558            resolve_to_encode,
1559            world_to_encode,
1560            "encoded world",
1561            if self.opts.disable_custom_section_link_helpers {
1562                None
1563            } else {
1564                Some("__link_custom_section_describing_imports")
1565            },
1566        );
1567
1568        if self.opts.stubs {
1569            self.src.push_str("\n#[derive(Debug)]\npub struct Stub;\n");
1570        }
1571
1572        let mut src = mem::take(&mut self.src);
1573        if self.opts.format {
1574            let syntax_tree = syn::parse_file(src.as_str()).unwrap();
1575            *src.as_mut_string() = prettyplease::unparse(&syntax_tree);
1576        }
1577
1578        // Prepend the preamble. We do this after formatting because
1579        // `syn::parse_file` + `prettyplease::unparse` does not preserve comments.
1580        let src_preamble = mem::take(&mut self.src_preamble);
1581        *src.as_mut_string() = format!("{}{}", src_preamble.as_str(), src.as_str());
1582
1583        let module_name = name.to_snake_case();
1584        files.push(&format!("{module_name}.rs"), src.as_bytes());
1585
1586        let remapped_keys = self
1587            .with
1588            .iter()
1589            .map(|(k, _)| k)
1590            .cloned()
1591            .collect::<HashSet<String>>();
1592
1593        let mut unused_keys = remapped_keys
1594            .difference(&self.generated_types)
1595            .collect::<Vec<&String>>();
1596
1597        unused_keys.sort();
1598
1599        if !unused_keys.is_empty() {
1600            bail!("unused remappings provided via `with`: {unused_keys:?}");
1601        }
1602
1603        let mut unused_selectors = self
1604            .opts
1605            .additional_type_attributes
1606            .iter()
1607            .map(|(sel, _)| sel)
1608            .filter(|sel| !self.used_type_attr_selectors.contains(*sel))
1609            .chain(
1610                self.opts
1611                    .additional_member_attributes
1612                    .iter()
1613                    .map(|(sel, _)| sel)
1614                    .filter(|sel| !self.used_member_attr_selectors.contains(*sel)),
1615            )
1616            .collect::<Vec<_>>();
1617        unused_selectors.sort();
1618        unused_selectors.dedup();
1619        if !unused_selectors.is_empty() {
1620            bail!(
1621                "unused selectors provided via `additional_type_attributes` / \
1622                 `additional_member_attributes`: {unused_selectors:?}"
1623            );
1624        }
1625
1626        // Error about unused async configuration to help catch configuration
1627        // errors.
1628        self.opts.async_.ensure_all_used()?;
1629        self.opts.chainable_methods.ensure_all_used()?;
1630
1631        Ok(())
1632    }
1633}
1634
1635pub(crate) fn compute_module_path(
1636    name: &WorldKey,
1637    resolve: &Resolve,
1638    is_export: bool,
1639) -> Vec<String> {
1640    let mut path = Vec::new();
1641    if is_export {
1642        path.push("exports".to_string());
1643    }
1644    match name {
1645        WorldKey::Name(name) => {
1646            path.push(to_rust_ident(name));
1647        }
1648        WorldKey::Interface(id) => {
1649            let iface = &resolve.interfaces[*id];
1650            let pkg = iface.package.unwrap();
1651            let pkgname = resolve.packages[pkg].name.clone();
1652            path.push(to_rust_ident(&pkgname.namespace));
1653            path.push(name_package_module(resolve, pkg));
1654            path.push(to_rust_ident(iface.name.as_ref().unwrap()));
1655        }
1656    }
1657    path
1658}
1659
1660enum Identifier<'a> {
1661    World(WorldId),
1662    Interface(InterfaceId, &'a WorldKey),
1663    StreamOrFuturePayload,
1664}
1665
1666fn group_by_resource<'a>(
1667    funcs: impl Iterator<Item = &'a Function>,
1668) -> BTreeMap<Option<TypeId>, Vec<&'a Function>> {
1669    let mut by_resource = BTreeMap::<_, Vec<_>>::new();
1670    for func in funcs {
1671        by_resource
1672            .entry(func.kind.resource())
1673            .or_default()
1674            .push(func);
1675    }
1676    by_resource
1677}
1678
1679#[derive(Default, Debug, Clone, Copy)]
1680#[cfg_attr(
1681    feature = "serde",
1682    derive(serde::Deserialize),
1683    serde(rename_all = "kebab-case")
1684)]
1685pub enum Ownership {
1686    /// Generated types will be composed entirely of owning fields, regardless
1687    /// of whether they are used as parameters to imports or not.
1688    #[default]
1689    Owning,
1690
1691    /// Generated types used as parameters to imports will be "deeply
1692    /// borrowing", i.e. contain references rather than owned values when
1693    /// applicable.
1694    Borrowing {
1695        /// Whether or not to generate "duplicate" type definitions for a single
1696        /// WIT type if necessary, for example if it's used as both an import
1697        /// and an export, or if it's used both as a parameter to an import and
1698        /// a return value from an import.
1699        duplicate_if_necessary: bool,
1700    },
1701}
1702
1703impl FromStr for Ownership {
1704    type Err = String;
1705
1706    fn from_str(s: &str) -> Result<Self, Self::Err> {
1707        match s {
1708            "owning" => Ok(Self::Owning),
1709            "borrowing" => Ok(Self::Borrowing {
1710                duplicate_if_necessary: false,
1711            }),
1712            "borrowing-duplicate-if-necessary" => Ok(Self::Borrowing {
1713                duplicate_if_necessary: true,
1714            }),
1715            _ => Err(format!(
1716                "unrecognized ownership: `{s}`; \
1717                 expected `owning`, `borrowing`, or `borrowing-duplicate-if-necessary`"
1718            )),
1719        }
1720    }
1721}
1722
1723impl fmt::Display for Ownership {
1724    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1725        f.write_str(match self {
1726            Ownership::Owning => "owning",
1727            Ownership::Borrowing {
1728                duplicate_if_necessary: false,
1729            } => "borrowing",
1730            Ownership::Borrowing {
1731                duplicate_if_necessary: true,
1732            } => "borrowing-duplicate-if-necessary",
1733        })
1734    }
1735}
1736
1737/// Options for with "with" remappings.
1738#[derive(Debug, Clone)]
1739#[cfg_attr(
1740    feature = "serde",
1741    derive(serde::Deserialize),
1742    serde(rename_all = "kebab-case")
1743)]
1744pub enum WithOption {
1745    Path(String),
1746    Generate,
1747}
1748
1749impl std::fmt::Display for WithOption {
1750    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1751        match self {
1752            WithOption::Path(p) => f.write_fmt(format_args!("\"{p}\"")),
1753            WithOption::Generate => f.write_str("generate"),
1754        }
1755    }
1756}
1757
1758impl From<WithOption> for TypeGeneration {
1759    fn from(opt: WithOption) -> Self {
1760        match opt {
1761            WithOption::Path(p) => TypeGeneration::Remap(p),
1762            WithOption::Generate => TypeGeneration::Generate,
1763        }
1764    }
1765}
1766
1767#[derive(Default)]
1768struct FnSig {
1769    async_: bool,
1770    unsafe_: bool,
1771    private: bool,
1772    use_item_name: bool,
1773    generics: Option<String>,
1774    self_arg: Option<String>,
1775    self_is_first_param: bool,
1776}
1777
1778impl FnSig {
1779    fn update_for_func(&mut self, func: &Function, return_self: Option<ChainingMode>) {
1780        if let FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) = &func.kind {
1781            self.self_arg = Some(
1782                match return_self {
1783                    Some(ChainingMode::Owning) => "self",
1784                    _ => "&self",
1785                }
1786                .into(),
1787            );
1788            self.self_is_first_param = true;
1789        }
1790    }
1791}
1792
1793pub fn to_rust_ident(name: &str) -> String {
1794    match name {
1795        // Escape Rust keywords.
1796        // Source: https://doc.rust-lang.org/reference/keywords.html
1797        "as" => "as_".into(),
1798        "break" => "break_".into(),
1799        "const" => "const_".into(),
1800        "continue" => "continue_".into(),
1801        "crate" => "crate_".into(),
1802        "else" => "else_".into(),
1803        "enum" => "enum_".into(),
1804        "extern" => "extern_".into(),
1805        "false" => "false_".into(),
1806        "fn" => "fn_".into(),
1807        "for" => "for_".into(),
1808        "if" => "if_".into(),
1809        "impl" => "impl_".into(),
1810        "in" => "in_".into(),
1811        "let" => "let_".into(),
1812        "loop" => "loop_".into(),
1813        "match" => "match_".into(),
1814        "mod" => "mod_".into(),
1815        "move" => "move_".into(),
1816        "mut" => "mut_".into(),
1817        "pub" => "pub_".into(),
1818        "ref" => "ref_".into(),
1819        "return" => "return_".into(),
1820        "self" => "self_".into(),
1821        "static" => "static_".into(),
1822        "struct" => "struct_".into(),
1823        "super" => "super_".into(),
1824        "trait" => "trait_".into(),
1825        "true" => "true_".into(),
1826        "type" => "type_".into(),
1827        "unsafe" => "unsafe_".into(),
1828        "use" => "use_".into(),
1829        "where" => "where_".into(),
1830        "while" => "while_".into(),
1831        "async" => "async_".into(),
1832        "await" => "await_".into(),
1833        "dyn" => "dyn_".into(),
1834        "abstract" => "abstract_".into(),
1835        "become" => "become_".into(),
1836        "box" => "box_".into(),
1837        "do" => "do_".into(),
1838        "final" => "final_".into(),
1839        "macro" => "macro_".into(),
1840        "override" => "override_".into(),
1841        "priv" => "priv_".into(),
1842        "typeof" => "typeof_".into(),
1843        "unsized" => "unsized_".into(),
1844        "virtual" => "virtual_".into(),
1845        "yield" => "yield_".into(),
1846        "try" => "try_".into(),
1847        s => s.to_snake_case(),
1848    }
1849}
1850
1851fn to_upper_camel_case(name: &str) -> String {
1852    match name {
1853        // The name "Guest" is reserved for traits generated by exported
1854        // interfaces, so remap types defined in wit to something else.
1855        "guest" => "Guest_".to_string(),
1856        s => s.to_upper_camel_case(),
1857    }
1858}
1859
1860fn wasm_type(ty: WasmType) -> &'static str {
1861    match ty {
1862        WasmType::I32 => "i32",
1863        WasmType::I64 => "i64",
1864        WasmType::F32 => "f32",
1865        WasmType::F64 => "f64",
1866        WasmType::Pointer => "*mut u8",
1867        WasmType::Length => "usize",
1868
1869        // `PointerOrI64` can hold either a `u64` or a pointer with provenance.
1870        // Neither a `u64` nor a pointer type can portably do both, so we use
1871        // `MaybeUninit<u64>`, since `MaybeUninit` is [documented] to preserve
1872        // provenance.
1873        // [documented]: https://github.com/rust-lang/rfcs/blob/master/text/3559-rust-has-provenance.md#reference-level-explanation
1874        WasmType::PointerOrI64 => "::core::mem::MaybeUninit::<u64>",
1875    }
1876}
1877
1878fn declare_import(
1879    wasm_import_module: &str,
1880    wasm_import_name: &str,
1881    rust_name: &str,
1882    params: &[WasmType],
1883    results: &[WasmType],
1884) -> String {
1885    let mut sig = "(".to_owned();
1886    for param in params.iter() {
1887        sig.push_str("_: ");
1888        sig.push_str(wasm_type(*param));
1889        sig.push_str(", ");
1890    }
1891    sig.push(')');
1892    assert!(results.len() < 2);
1893    for result in results.iter() {
1894        sig.push_str(" -> ");
1895        sig.push_str(wasm_type(*result));
1896    }
1897    format!(
1898        "
1899            #[cfg(target_arch = \"wasm32\")]
1900            #[link(wasm_import_module = \"{wasm_import_module}\")]
1901            unsafe extern \"C\" {{
1902                #[link_name = \"{wasm_import_name}\"]
1903                fn {rust_name}{sig};
1904            }}
1905
1906            #[cfg(not(target_arch = \"wasm32\"))]
1907            unsafe extern \"C\" fn {rust_name}{sig} {{ unreachable!() }}
1908        "
1909    )
1910}
1911
1912fn int_repr(repr: Int) -> &'static str {
1913    match repr {
1914        Int::U8 => "u8",
1915        Int::U16 => "u16",
1916        Int::U32 => "u32",
1917        Int::U64 => "u64",
1918    }
1919}
1920
1921fn bitcast(casts: &[Bitcast], operands: &[String], results: &mut Vec<String>) {
1922    for (cast, operand) in casts.iter().zip(operands) {
1923        results.push(perform_cast(operand, cast));
1924    }
1925}
1926
1927fn perform_cast(operand: &str, cast: &Bitcast) -> String {
1928    match cast {
1929        Bitcast::None => operand.to_owned(),
1930        Bitcast::I32ToI64 => format!("i64::from({operand})"),
1931        Bitcast::F32ToI32 => format!("({operand}).to_bits() as i32"),
1932        Bitcast::F64ToI64 => format!("({operand}).to_bits() as i64"),
1933        Bitcast::I64ToI32 => format!("{operand} as i32"),
1934        Bitcast::I32ToF32 => format!("f32::from_bits({operand} as u32)"),
1935        Bitcast::I64ToF64 => format!("f64::from_bits({operand} as u64)"),
1936        Bitcast::F32ToI64 => format!("i64::from(({operand}).to_bits())"),
1937        Bitcast::I64ToF32 => format!("f32::from_bits({operand} as u32)"),
1938
1939        // Convert an `i64` into a `MaybeUninit<u64>`.
1940        Bitcast::I64ToP64 => format!("::core::mem::MaybeUninit::new({operand} as u64)"),
1941        // Convert a `MaybeUninit<u64>` holding an `i64` value back into
1942        // the `i64` value.
1943        Bitcast::P64ToI64 => format!("{operand}.assume_init() as i64"),
1944
1945        // Convert a pointer value into a `MaybeUninit<u64>`.
1946        Bitcast::PToP64 => {
1947            format!(
1948                "{{
1949                        let mut t = ::core::mem::MaybeUninit::<u64>::uninit();
1950                        t.as_mut_ptr().cast::<*mut u8>().write({operand});
1951                        t
1952                    }}"
1953            )
1954        }
1955        // Convert a `MaybeUninit<u64>` holding a pointer value back into
1956        // the pointer value.
1957        Bitcast::P64ToP => {
1958            format!("{operand}.as_ptr().cast::<*mut u8>().read()")
1959        }
1960        // Convert an `i32` or a `usize` into a pointer.
1961        Bitcast::I32ToP | Bitcast::LToP => {
1962            format!("{operand} as *mut u8")
1963        }
1964        // Convert a pointer or length holding an `i32` value back into the `i32`.
1965        Bitcast::PToI32 | Bitcast::LToI32 => {
1966            format!("{operand} as i32")
1967        }
1968        // Convert an `i32`, `i64`, or pointer holding a `usize` value back into the `usize`.
1969        Bitcast::I32ToL | Bitcast::I64ToL | Bitcast::PToL => {
1970            format!("{operand} as usize")
1971        }
1972        // Convert a `usize` into an `i64`.
1973        Bitcast::LToI64 => {
1974            format!("{operand} as i64")
1975        }
1976        Bitcast::Sequence(sequence) => {
1977            let [first, second] = &**sequence;
1978            perform_cast(&perform_cast(operand, first), second)
1979        }
1980    }
1981}
1982
1983enum RustFlagsRepr {
1984    U8,
1985    U16,
1986    U32,
1987    U64,
1988    U128,
1989}
1990
1991impl RustFlagsRepr {
1992    fn new(f: &Flags) -> RustFlagsRepr {
1993        match f.repr() {
1994            FlagsRepr::U8 => RustFlagsRepr::U8,
1995            FlagsRepr::U16 => RustFlagsRepr::U16,
1996            FlagsRepr::U32(1) => RustFlagsRepr::U32,
1997            FlagsRepr::U32(2) => RustFlagsRepr::U64,
1998            FlagsRepr::U32(3 | 4) => RustFlagsRepr::U128,
1999            FlagsRepr::U32(n) => panic!("unsupported number of flags: {}", n * 32),
2000        }
2001    }
2002}
2003
2004impl fmt::Display for RustFlagsRepr {
2005    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2006        match self {
2007            RustFlagsRepr::U8 => "u8".fmt(f),
2008            RustFlagsRepr::U16 => "u16".fmt(f),
2009            RustFlagsRepr::U32 => "u32".fmt(f),
2010            RustFlagsRepr::U64 => "u64".fmt(f),
2011            RustFlagsRepr::U128 => "u128".fmt(f),
2012        }
2013    }
2014}
2015
2016#[derive(Debug, Clone)]
2017pub struct MissingWith(pub String);
2018
2019impl fmt::Display for MissingWith {
2020    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2021        write!(f, "missing `with` mapping for the key `{}`", self.0)
2022    }
2023}
2024
2025impl std::error::Error for MissingWith {}
2026
2027// bail!("no remapping found for {with_name:?} - use the `generate!` macro's `with` option to force the interface to be generated or specify where it is already defined:
2028// ```
2029// with: {{\n\t{with_name:?}: generate\n}}
2030// ```")
2031
2032/// Returns the full WIT type name with fully qualified interface name
2033fn full_wit_type_name(resolve: &Resolve, id: TypeId) -> String {
2034    let id = dealias(resolve, id);
2035    let type_def = &resolve.types[id];
2036    let interface_name = match type_def.owner {
2037        TypeOwner::World(w) => Some(resolve.worlds[w].name.clone()),
2038        TypeOwner::Interface(id) => resolve.id_of(id),
2039        TypeOwner::None => None,
2040    };
2041    match interface_name {
2042        Some(interface_name) => format!("{}/{}", interface_name, type_def.name.clone().unwrap()),
2043        None => type_def.name.clone().unwrap(),
2044    }
2045}
2046
2047enum ConstructorReturnType {
2048    /// Resource constructor is infallible. E.g.:
2049    /// ```wit
2050    /// resource R {
2051    ///    constructor(..);
2052    /// }
2053    /// ```
2054    Self_,
2055
2056    /// Resource constructor is fallible. E.g.:
2057    /// ```wit
2058    /// resource R {
2059    ///    constructor(..) -> result<R, err>;
2060    /// }
2061    /// ```
2062    Result { err: Option<Type> },
2063}
2064
2065fn classify_constructor_return_type(
2066    resolve: &Resolve,
2067    resource_id: TypeId,
2068    result: &Option<Type>,
2069) -> ConstructorReturnType {
2070    fn classify(
2071        resolve: &Resolve,
2072        resource_id: TypeId,
2073        result: &Option<Type>,
2074    ) -> Option<ConstructorReturnType> {
2075        let resource_id = dealias(resolve, resource_id);
2076        let typedef = match result.as_ref()? {
2077            Type::Id(id) => &resolve.types[dealias(resolve, *id)],
2078            _ => return None,
2079        };
2080
2081        match &typedef.kind {
2082            TypeDefKind::Handle(Handle::Own(id)) if dealias(resolve, *id) == resource_id => {
2083                Some(ConstructorReturnType::Self_)
2084            }
2085            TypeDefKind::Result(Result_ { ok, err }) => {
2086                let ok_typedef = match ok.as_ref()? {
2087                    Type::Id(id) => &resolve.types[dealias(resolve, *id)],
2088                    _ => return None,
2089                };
2090
2091                match &ok_typedef.kind {
2092                    TypeDefKind::Handle(Handle::Own(id))
2093                        if dealias(resolve, *id) == resource_id =>
2094                    {
2095                        Some(ConstructorReturnType::Result { err: *err })
2096                    }
2097                    _ => None,
2098                }
2099            }
2100            _ => None,
2101        }
2102    }
2103
2104    classify(resolve, resource_id, result).expect("invalid constructor")
2105}