Skip to main content

wit_parser/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5#[cfg(feature = "std")]
6extern crate std;
7
8use crate::abi::AbiVariant;
9use alloc::format;
10use alloc::string::{String, ToString};
11use alloc::vec::Vec;
12#[cfg(feature = "std")]
13use anyhow::Context;
14use anyhow::{Result, bail};
15use id_arena::{Arena, Id};
16use semver::Version;
17
18#[cfg(feature = "std")]
19pub type IndexMap<K, V> = indexmap::IndexMap<K, V, std::hash::RandomState>;
20#[cfg(feature = "std")]
21pub type IndexSet<T> = indexmap::IndexSet<T, std::hash::RandomState>;
22#[cfg(not(feature = "std"))]
23pub type IndexMap<K, V> = indexmap::IndexMap<K, V, hashbrown::DefaultHashBuilder>;
24#[cfg(not(feature = "std"))]
25pub type IndexSet<T> = indexmap::IndexSet<T, hashbrown::DefaultHashBuilder>;
26
27#[cfg(feature = "std")]
28pub(crate) use std::collections::{HashMap, HashSet};
29
30#[cfg(not(feature = "std"))]
31pub(crate) use hashbrown::{HashMap, HashSet};
32
33use alloc::borrow::Cow;
34use core::fmt;
35use core::hash::{Hash, Hasher};
36#[cfg(feature = "std")]
37use std::path::Path;
38
39#[cfg(feature = "decoding")]
40pub mod decoding;
41#[cfg(feature = "decoding")]
42mod metadata;
43#[cfg(feature = "decoding")]
44pub use metadata::PackageMetadata;
45
46pub mod abi;
47mod ast;
48pub use ast::SourceMap;
49pub use ast::lex::Span;
50pub use ast::{ParsedUsePath, parse_use_path};
51mod sizealign;
52pub use sizealign::*;
53mod resolve;
54pub use resolve::*;
55mod live;
56pub use live::{LiveTypes, TypeIdVisitor};
57
58#[cfg(feature = "serde")]
59use serde_derive::Serialize;
60#[cfg(feature = "serde")]
61mod serde_;
62#[cfg(feature = "serde")]
63use serde_::*;
64
65/// Checks if the given string is a legal identifier in wit.
66pub fn validate_id(s: &str) -> Result<()> {
67    ast::validate_id(0, s)?;
68    Ok(())
69}
70
71pub type WorldId = Id<World>;
72pub type InterfaceId = Id<Interface>;
73pub type TypeId = Id<TypeDef>;
74
75/// Representation of a parsed WIT package which has not resolved external
76/// dependencies yet.
77///
78/// This representation has performed internal resolution of the WIT package
79/// itself, ensuring that all references internally are valid and the WIT was
80/// syntactically valid and such.
81///
82/// The fields of this structure represent a flat list of arrays unioned from
83/// all documents within the WIT package. This means, for example, that all
84/// types from all documents are located in `self.types`. The fields of each
85/// item can help splitting back out into packages/interfaces/etc as necessary.
86///
87/// Note that an `UnresolvedPackage` cannot be queried in general about
88/// information such as size or alignment as that would require resolution of
89/// foreign dependencies. Translations such as to-binary additionally are not
90/// supported on an `UnresolvedPackage` due to the lack of knowledge about the
91/// foreign types. This is intended to be an intermediate state which can be
92/// inspected by embedders, if necessary, before quickly transforming to a
93/// [`Resolve`] to fully work with a WIT package.
94///
95/// After an [`UnresolvedPackage`] is parsed it can be fully resolved with
96/// [`Resolve::push`]. During this operation a dependency map is specified which
97/// will connect the `foreign_deps` field of this structure to packages
98/// previously inserted within the [`Resolve`]. Embedders are responsible for
99/// performing this resolution themselves.
100#[derive(Clone)]
101pub struct UnresolvedPackage {
102    /// The namespace, name, and version information for this package.
103    pub name: PackageName,
104
105    /// All worlds from all documents within this package.
106    ///
107    /// Each world lists the document that it is from.
108    pub worlds: Arena<World>,
109
110    /// All interfaces from all documents within this package.
111    ///
112    /// Each interface lists the document that it is from. Interfaces are listed
113    /// in topological order as well so iteration through this arena will only
114    /// reference prior elements already visited when working with recursive
115    /// references.
116    pub interfaces: Arena<Interface>,
117
118    /// All types from all documents within this package.
119    ///
120    /// Each type lists the interface or world that defined it, or nothing if
121    /// it's an anonymous type. Types are listed in this arena in topological
122    /// order to ensure that iteration through this arena will only reference
123    /// other types transitively that are already iterated over.
124    pub types: Arena<TypeDef>,
125
126    /// All foreign dependencies that this package depends on.
127    ///
128    /// These foreign dependencies must be resolved to convert this unresolved
129    /// package into a `Resolve`. The map here is keyed by the name of the
130    /// foreign package that this depends on, and the sub-map is keyed by an
131    /// interface name followed by the identifier within `self.interfaces`. The
132    /// fields of `self.interfaces` describes the required types that are from
133    /// each foreign interface.
134    pub foreign_deps: IndexMap<PackageName, IndexMap<String, (AstItem, Vec<Stability>)>>,
135
136    /// Doc comments for this package.
137    pub docs: Docs,
138
139    #[cfg_attr(not(feature = "std"), allow(dead_code))]
140    package_name_span: Span,
141    unknown_type_spans: Vec<Span>,
142    foreign_dep_spans: Vec<Span>,
143    required_resource_types: Vec<(TypeId, Span)>,
144}
145
146impl UnresolvedPackage {
147    /// Adjusts all spans in this package by adding the given byte offset.
148    ///
149    /// This is used when merging source maps to update spans to point to the
150    /// correct location in the combined source map.
151    pub(crate) fn adjust_spans(&mut self, offset: u32) {
152        // Adjust parallel vec spans
153        self.package_name_span.adjust(offset);
154        for span in &mut self.unknown_type_spans {
155            span.adjust(offset);
156        }
157        for span in &mut self.foreign_dep_spans {
158            span.adjust(offset);
159        }
160        for (_, span) in &mut self.required_resource_types {
161            span.adjust(offset);
162        }
163
164        // Adjust spans on arena items
165        for (_, world) in self.worlds.iter_mut() {
166            world.adjust_spans(offset);
167        }
168        for (_, iface) in self.interfaces.iter_mut() {
169            iface.adjust_spans(offset);
170        }
171        for (_, ty) in self.types.iter_mut() {
172            ty.adjust_spans(offset);
173        }
174    }
175}
176
177/// Tracks a set of packages, all pulled from the same group of WIT source files.
178#[derive(Clone)]
179pub struct UnresolvedPackageGroup {
180    /// The "main" package in this package group which was found at the root of
181    /// the WIT files.
182    ///
183    /// Note that this is required to be present in all WIT files.
184    pub main: UnresolvedPackage,
185
186    /// Nested packages found while parsing `main`, if any.
187    pub nested: Vec<UnresolvedPackage>,
188
189    /// A set of processed source files from which these packages have been parsed.
190    pub source_map: SourceMap,
191}
192
193#[derive(Debug, Copy, Clone)]
194#[cfg_attr(feature = "serde", derive(Serialize))]
195#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
196pub enum AstItem {
197    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
198    Interface(InterfaceId),
199    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
200    World(WorldId),
201}
202
203/// A structure used to keep track of the name of a package, containing optional
204/// information such as a namespace and version information.
205///
206/// This is directly encoded as an "ID" in the binary component representation
207/// with an interfaced tacked on as well.
208#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
209#[cfg_attr(feature = "serde", derive(Serialize))]
210#[cfg_attr(feature = "serde", serde(into = "String"))]
211pub struct PackageName {
212    /// A namespace such as `wasi` in `wasi:foo/bar`
213    pub namespace: String,
214    /// The kebab-name of this package, which is always specified.
215    pub name: String,
216    /// Optional major/minor version information.
217    pub version: Option<Version>,
218}
219
220impl From<PackageName> for String {
221    fn from(name: PackageName) -> String {
222        name.to_string()
223    }
224}
225
226impl PackageName {
227    /// Returns the ID that this package name would assign the `interface` name
228    /// specified.
229    pub fn interface_id(&self, interface: &str) -> String {
230        let mut s = String::new();
231        s.push_str(&format!("{}:{}/{interface}", self.namespace, self.name));
232        if let Some(version) = &self.version {
233            s.push_str(&format!("@{version}"));
234        }
235        s
236    }
237
238    /// Determines the "semver compatible track" for the given version.
239    ///
240    /// This method implements the logic from the component model where semver
241    /// versions can be compatible with one another. For example versions 1.2.0
242    /// and 1.2.1 would be considered both compatible with one another because
243    /// they're on the same semver compatible track.
244    ///
245    /// This predicate is used during
246    /// [`Resolve::merge_world_imports_based_on_semver`] for example to
247    /// determine whether two imports can be merged together. This is
248    /// additionally used when creating components to match up imports in
249    /// core wasm to imports in worlds.
250    pub fn version_compat_track(version: &Version) -> Version {
251        let mut version = version.clone();
252        version.build = semver::BuildMetadata::EMPTY;
253        if !version.pre.is_empty() {
254            return version;
255        }
256        if version.major != 0 {
257            version.minor = 0;
258            version.patch = 0;
259            return version;
260        }
261        if version.minor != 0 {
262            version.patch = 0;
263            return version;
264        }
265        version
266    }
267
268    /// Returns the string corresponding to
269    /// [`PackageName::version_compat_track`]. This is done to match the
270    /// component model's expected naming scheme of imports and exports.
271    pub fn version_compat_track_string(version: &Version) -> String {
272        let version = Self::version_compat_track(version);
273        if !version.pre.is_empty() {
274            return version.to_string();
275        }
276        if version.major != 0 {
277            return format!("{}", version.major);
278        }
279        if version.minor != 0 {
280            return format!("{}.{}", version.major, version.minor);
281        }
282        version.to_string()
283    }
284}
285
286impl fmt::Display for PackageName {
287    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288        write!(f, "{}:{}", self.namespace, self.name)?;
289        if let Some(version) = &self.version {
290            write!(f, "@{version}")?;
291        }
292        Ok(())
293    }
294}
295
296#[derive(Debug)]
297struct Error {
298    span: Span,
299    msg: String,
300    highlighted: Option<String>,
301}
302
303impl Error {
304    fn new(span: Span, msg: impl Into<String>) -> Error {
305        Error {
306            span,
307            msg: msg.into(),
308            highlighted: None,
309        }
310    }
311
312    /// Highlights this error using the given source map, if the span is known.
313    fn highlight(&mut self, source_map: &ast::SourceMap) {
314        if self.highlighted.is_none() {
315            self.highlighted = source_map.highlight_span(self.span, &self.msg);
316        }
317    }
318}
319
320impl fmt::Display for Error {
321    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322        self.highlighted.as_ref().unwrap_or(&self.msg).fmt(f)
323    }
324}
325
326impl core::error::Error for Error {}
327
328#[derive(Debug)]
329struct PackageNotFoundError {
330    span: Span,
331    requested: PackageName,
332    known: Vec<PackageName>,
333    highlighted: Option<String>,
334}
335
336impl PackageNotFoundError {
337    pub fn new(span: Span, requested: PackageName, known: Vec<PackageName>) -> Self {
338        Self {
339            span,
340            requested,
341            known,
342            highlighted: None,
343        }
344    }
345
346    /// Highlights this error using the given source map, if the span is known.
347    fn highlight(&mut self, source_map: &ast::SourceMap) {
348        if self.highlighted.is_none() {
349            self.highlighted = source_map.highlight_span(self.span, &format!("{self}"));
350        }
351    }
352}
353
354impl fmt::Display for PackageNotFoundError {
355    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356        if let Some(highlighted) = &self.highlighted {
357            return highlighted.fmt(f);
358        }
359        if self.known.is_empty() {
360            write!(
361                f,
362                "package '{}' not found. no known packages.",
363                self.requested
364            )?;
365        } else {
366            write!(
367                f,
368                "package '{}' not found. known packages:\n",
369                self.requested
370            )?;
371            for known in self.known.iter() {
372                write!(f, "    {known}\n")?;
373            }
374        }
375        Ok(())
376    }
377}
378
379impl core::error::Error for PackageNotFoundError {}
380
381impl UnresolvedPackageGroup {
382    /// Parses the given string as a wit document.
383    ///
384    /// The `path` argument is used for error reporting. The `contents` provided
385    /// are considered to be the contents of `path`. This function does not read
386    /// the filesystem.
387    #[cfg(feature = "std")]
388    pub fn parse(path: impl AsRef<Path>, contents: &str) -> Result<UnresolvedPackageGroup> {
389        let path = path
390            .as_ref()
391            .to_str()
392            .ok_or_else(|| anyhow::anyhow!("path is not valid utf-8: {:?}", path.as_ref()))?;
393        Self::parse_str(path, contents)
394    }
395
396    /// Parses the given string as a wit document.
397    ///
398    /// The `path` argument is used for error reporting. The `contents` provided
399    /// are considered to be the contents of `path`. This function does not read
400    /// the filesystem.
401    pub fn parse_str(path: &str, contents: &str) -> Result<UnresolvedPackageGroup> {
402        let mut map = SourceMap::default();
403        map.push_str(path, contents);
404        map.parse()
405    }
406
407    /// Parse a WIT package at the provided path.
408    ///
409    /// The path provided is inferred whether it's a file or a directory. A file
410    /// is parsed with [`UnresolvedPackageGroup::parse_file`] and a directory is
411    /// parsed with [`UnresolvedPackageGroup::parse_dir`].
412    #[cfg(feature = "std")]
413    pub fn parse_path(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
414        let path = path.as_ref();
415        if path.is_dir() {
416            UnresolvedPackageGroup::parse_dir(path)
417        } else {
418            UnresolvedPackageGroup::parse_file(path)
419        }
420    }
421
422    /// Parses a WIT package from the file provided.
423    ///
424    /// The return value represents all packages found in the WIT file which
425    /// might be either one or multiple depending on the syntax used.
426    #[cfg(feature = "std")]
427    pub fn parse_file(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
428        let path = path.as_ref();
429        let contents = std::fs::read_to_string(path)
430            .with_context(|| format!("failed to read file {path:?}"))?;
431        Self::parse(path, &contents)
432    }
433
434    /// Parses a WIT package from the directory provided.
435    ///
436    /// This method will look at all files under the `path` specified. All
437    /// `*.wit` files are parsed and assumed to be part of the same package
438    /// grouping. This is useful when a WIT package is split across multiple
439    /// files.
440    #[cfg(feature = "std")]
441    pub fn parse_dir(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
442        let path = path.as_ref();
443        let mut map = SourceMap::default();
444        let cx = || format!("failed to read directory {path:?}");
445        for entry in path.read_dir().with_context(&cx)? {
446            let entry = entry.with_context(&cx)?;
447            let path = entry.path();
448            let ty = entry.file_type().with_context(&cx)?;
449            if ty.is_dir() {
450                continue;
451            }
452            if ty.is_symlink() {
453                if path.is_dir() {
454                    continue;
455                }
456            }
457            let filename = match path.file_name().and_then(|s| s.to_str()) {
458                Some(name) => name,
459                None => continue,
460            };
461            if !filename.ends_with(".wit") {
462                continue;
463            }
464            map.push_file(&path)?;
465        }
466        map.parse()
467    }
468}
469
470#[derive(Debug, Clone)]
471#[cfg_attr(feature = "serde", derive(Serialize))]
472pub struct World {
473    /// The WIT identifier name of this world.
474    pub name: String,
475
476    /// All imported items into this interface, both worlds and functions.
477    pub imports: IndexMap<WorldKey, WorldItem>,
478
479    /// All exported items from this interface, both worlds and functions.
480    pub exports: IndexMap<WorldKey, WorldItem>,
481
482    /// The package that owns this world.
483    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
484    pub package: Option<PackageId>,
485
486    /// Documentation associated with this world declaration.
487    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
488    pub docs: Docs,
489
490    /// Stability annotation for this world itself.
491    #[cfg_attr(
492        feature = "serde",
493        serde(skip_serializing_if = "Stability::is_unknown")
494    )]
495    pub stability: Stability,
496
497    /// All the included worlds from this world. Empty if this is fully resolved.
498    #[cfg_attr(feature = "serde", serde(skip))]
499    pub includes: Vec<WorldInclude>,
500
501    /// Source span for this world.
502    #[cfg_attr(feature = "serde", serde(skip))]
503    pub span: Span,
504}
505
506impl World {
507    /// Adjusts all spans in this world by adding the given byte offset.
508    pub(crate) fn adjust_spans(&mut self, offset: u32) {
509        self.span.adjust(offset);
510        for item in self.imports.values_mut().chain(self.exports.values_mut()) {
511            item.adjust_spans(offset);
512        }
513        for include in &mut self.includes {
514            include.span.adjust(offset);
515        }
516    }
517}
518
519#[derive(Debug, Clone)]
520pub struct IncludeName {
521    /// The name of the item
522    pub name: String,
523
524    /// The name to be replaced with
525    pub as_: String,
526}
527
528/// An entry in the `includes` list of a world, representing an `include`
529/// statement in WIT.
530#[derive(Debug, Clone)]
531pub struct WorldInclude {
532    /// The stability annotation on this include.
533    pub stability: Stability,
534
535    /// The world being included.
536    pub id: WorldId,
537
538    /// Names being renamed as part of this include.
539    pub names: Vec<IncludeName>,
540
541    /// Source span for this include statement.
542    pub span: Span,
543}
544
545/// The key to the import/export maps of a world. Either a kebab-name or a
546/// unique interface.
547#[derive(Debug, Clone, Eq)]
548#[cfg_attr(feature = "serde", derive(Serialize))]
549#[cfg_attr(feature = "serde", serde(into = "String"))]
550pub enum WorldKey {
551    /// A kebab-name.
552    Name(String),
553    /// An interface which is assigned no kebab-name.
554    Interface(InterfaceId),
555}
556
557impl Hash for WorldKey {
558    fn hash<H: Hasher>(&self, hasher: &mut H) {
559        match self {
560            WorldKey::Name(s) => {
561                0u8.hash(hasher);
562                s.as_str().hash(hasher);
563            }
564            WorldKey::Interface(i) => {
565                1u8.hash(hasher);
566                i.hash(hasher);
567            }
568        }
569    }
570}
571
572impl PartialEq for WorldKey {
573    fn eq(&self, other: &WorldKey) -> bool {
574        match (self, other) {
575            (WorldKey::Name(a), WorldKey::Name(b)) => a.as_str() == b.as_str(),
576            (WorldKey::Name(_), _) => false,
577            (WorldKey::Interface(a), WorldKey::Interface(b)) => a == b,
578            (WorldKey::Interface(_), _) => false,
579        }
580    }
581}
582
583impl From<WorldKey> for String {
584    fn from(key: WorldKey) -> String {
585        match key {
586            WorldKey::Name(name) => name,
587            WorldKey::Interface(id) => format!("interface-{}", id.index()),
588        }
589    }
590}
591
592impl WorldKey {
593    /// Asserts that this is `WorldKey::Name` and returns the name.
594    #[track_caller]
595    pub fn unwrap_name(self) -> String {
596        match self {
597            WorldKey::Name(name) => name,
598            WorldKey::Interface(_) => panic!("expected a name, found interface"),
599        }
600    }
601}
602
603#[derive(Debug, Clone, PartialEq)]
604#[cfg_attr(feature = "serde", derive(Serialize))]
605#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
606pub enum WorldItem {
607    /// An interface is being imported or exported from a world, indicating that
608    /// it's a namespace of functions.
609    Interface {
610        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
611        id: InterfaceId,
612        #[cfg_attr(
613            feature = "serde",
614            serde(skip_serializing_if = "Stability::is_unknown")
615        )]
616        stability: Stability,
617        #[cfg_attr(feature = "serde", serde(skip))]
618        span: Span,
619    },
620
621    /// A function is being directly imported or exported from this world.
622    Function(Function),
623
624    /// A type is being exported from this world.
625    ///
626    /// Note that types are never imported into worlds at this time.
627    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_ignore_span"))]
628    Type { id: TypeId, span: Span },
629}
630
631impl WorldItem {
632    pub fn stability<'a>(&'a self, resolve: &'a Resolve) -> &'a Stability {
633        match self {
634            WorldItem::Interface { stability, .. } => stability,
635            WorldItem::Function(f) => &f.stability,
636            WorldItem::Type { id, .. } => &resolve.types[*id].stability,
637        }
638    }
639
640    pub fn span(&self) -> Span {
641        match self {
642            WorldItem::Interface { span, .. } => *span,
643            WorldItem::Function(f) => f.span,
644            WorldItem::Type { span, .. } => *span,
645        }
646    }
647
648    pub(crate) fn adjust_spans(&mut self, offset: u32) {
649        match self {
650            WorldItem::Function(f) => f.adjust_spans(offset),
651            WorldItem::Interface { span, .. } => span.adjust(offset),
652            WorldItem::Type { span, .. } => span.adjust(offset),
653        }
654    }
655}
656
657#[derive(Debug, Clone)]
658#[cfg_attr(feature = "serde", derive(Serialize))]
659pub struct Interface {
660    /// Optionally listed name of this interface.
661    ///
662    /// This is `None` for inline interfaces in worlds.
663    pub name: Option<String>,
664
665    /// Exported types from this interface.
666    ///
667    /// Export names are listed within the types themselves. Note that the
668    /// export name here matches the name listed in the `TypeDef`.
669    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
670    pub types: IndexMap<String, TypeId>,
671
672    /// Exported functions from this interface.
673    pub functions: IndexMap<String, Function>,
674
675    /// Documentation associated with this interface.
676    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
677    pub docs: Docs,
678
679    /// Stability attribute for this interface.
680    #[cfg_attr(
681        feature = "serde",
682        serde(skip_serializing_if = "Stability::is_unknown")
683    )]
684    pub stability: Stability,
685
686    /// The package that owns this interface.
687    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
688    pub package: Option<PackageId>,
689
690    /// Source span for this interface.
691    #[cfg_attr(feature = "serde", serde(skip))]
692    pub span: Span,
693
694    /// The interface that this one was cloned from, if any.
695    ///
696    /// Applicable for [`Resolve::generate_nominal_type_ids`].
697    #[cfg_attr(
698        feature = "serde",
699        serde(
700            skip_serializing_if = "Option::is_none",
701            serialize_with = "serialize_optional_id",
702        )
703    )]
704    pub clone_of: Option<InterfaceId>,
705}
706
707impl Interface {
708    /// Adjusts all spans in this interface by adding the given byte offset.
709    pub(crate) fn adjust_spans(&mut self, offset: u32) {
710        self.span.adjust(offset);
711        for func in self.functions.values_mut() {
712            func.adjust_spans(offset);
713        }
714    }
715}
716
717#[derive(Debug, Clone, PartialEq)]
718#[cfg_attr(feature = "serde", derive(Serialize))]
719pub struct TypeDef {
720    pub name: Option<String>,
721    pub kind: TypeDefKind,
722    pub owner: TypeOwner,
723    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
724    pub docs: Docs,
725    /// Stability attribute for this type.
726    #[cfg_attr(
727        feature = "serde",
728        serde(skip_serializing_if = "Stability::is_unknown")
729    )]
730    pub stability: Stability,
731    /// Source span for this type.
732    #[cfg_attr(feature = "serde", serde(skip))]
733    pub span: Span,
734}
735
736impl TypeDef {
737    /// Adjusts all spans in this type definition by adding the given byte offset.
738    ///
739    /// This is used when merging source maps to update spans to point to the
740    /// correct location in the combined source map.
741    pub(crate) fn adjust_spans(&mut self, offset: u32) {
742        self.span.adjust(offset);
743        match &mut self.kind {
744            TypeDefKind::Record(r) => {
745                for field in &mut r.fields {
746                    field.span.adjust(offset);
747                }
748            }
749            TypeDefKind::Variant(v) => {
750                for case in &mut v.cases {
751                    case.span.adjust(offset);
752                }
753            }
754            TypeDefKind::Enum(e) => {
755                for case in &mut e.cases {
756                    case.span.adjust(offset);
757                }
758            }
759            TypeDefKind::Flags(f) => {
760                for flag in &mut f.flags {
761                    flag.span.adjust(offset);
762                }
763            }
764            _ => {}
765        }
766    }
767}
768
769#[derive(Debug, Clone, PartialEq, Hash, Eq)]
770#[cfg_attr(feature = "serde", derive(Serialize))]
771#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
772pub enum TypeDefKind {
773    Record(Record),
774    Resource,
775    Handle(Handle),
776    Flags(Flags),
777    Tuple(Tuple),
778    Variant(Variant),
779    Enum(Enum),
780    Option(Type),
781    Result(Result_),
782    List(Type),
783    Map(Type, Type),
784    FixedLengthList(Type, u32),
785    Future(Option<Type>),
786    Stream(Option<Type>),
787    Type(Type),
788
789    /// This represents a type of unknown structure imported from a foreign
790    /// interface.
791    ///
792    /// This variant is only used during the creation of `UnresolvedPackage` but
793    /// by the time a `Resolve` is created then this will not exist.
794    Unknown,
795}
796
797impl TypeDefKind {
798    pub fn as_str(&self) -> &'static str {
799        match self {
800            TypeDefKind::Record(_) => "record",
801            TypeDefKind::Resource => "resource",
802            TypeDefKind::Handle(handle) => match handle {
803                Handle::Own(_) => "own",
804                Handle::Borrow(_) => "borrow",
805            },
806            TypeDefKind::Flags(_) => "flags",
807            TypeDefKind::Tuple(_) => "tuple",
808            TypeDefKind::Variant(_) => "variant",
809            TypeDefKind::Enum(_) => "enum",
810            TypeDefKind::Option(_) => "option",
811            TypeDefKind::Result(_) => "result",
812            TypeDefKind::List(_) => "list",
813            TypeDefKind::Map(_, _) => "map",
814            TypeDefKind::FixedLengthList(..) => "fixed-length list",
815            TypeDefKind::Future(_) => "future",
816            TypeDefKind::Stream(_) => "stream",
817            TypeDefKind::Type(_) => "type",
818            TypeDefKind::Unknown => "unknown",
819        }
820    }
821}
822
823#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
824#[cfg_attr(feature = "serde", derive(Serialize))]
825#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
826pub enum TypeOwner {
827    /// This type was defined within a `world` block.
828    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
829    World(WorldId),
830    /// This type was defined within an `interface` block.
831    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
832    Interface(InterfaceId),
833    /// This type wasn't inherently defined anywhere, such as a `list<T>`, which
834    /// doesn't need an owner.
835    #[cfg_attr(feature = "serde", serde(untagged, serialize_with = "serialize_none"))]
836    None,
837}
838
839#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
840#[cfg_attr(feature = "serde", derive(Serialize))]
841#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
842pub enum Handle {
843    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
844    Own(TypeId),
845    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
846    Borrow(TypeId),
847}
848
849#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
850pub enum Type {
851    Bool,
852    U8,
853    U16,
854    U32,
855    U64,
856    S8,
857    S16,
858    S32,
859    S64,
860    F32,
861    F64,
862    Char,
863    String,
864    ErrorContext,
865    Id(TypeId),
866}
867
868#[derive(Debug, Copy, Clone, Eq, PartialEq)]
869pub enum Int {
870    U8,
871    U16,
872    U32,
873    U64,
874}
875
876#[derive(Debug, Clone, PartialEq, Hash, Eq)]
877#[cfg_attr(feature = "serde", derive(Serialize))]
878pub struct Record {
879    pub fields: Vec<Field>,
880}
881
882#[derive(Debug, Clone, PartialEq, Hash, Eq)]
883#[cfg_attr(feature = "serde", derive(Serialize))]
884pub struct Field {
885    pub name: String,
886    #[cfg_attr(feature = "serde", serde(rename = "type"))]
887    pub ty: Type,
888    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
889    pub docs: Docs,
890    /// Source span for this field.
891    #[cfg_attr(feature = "serde", serde(skip))]
892    pub span: Span,
893}
894
895#[derive(Debug, Clone, PartialEq, Hash, Eq)]
896#[cfg_attr(feature = "serde", derive(Serialize))]
897pub struct Flags {
898    pub flags: Vec<Flag>,
899}
900
901#[derive(Debug, Clone, PartialEq, Hash, Eq)]
902#[cfg_attr(feature = "serde", derive(Serialize))]
903pub struct Flag {
904    pub name: String,
905    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
906    pub docs: Docs,
907    /// Source span for this flag.
908    #[cfg_attr(feature = "serde", serde(skip))]
909    pub span: Span,
910}
911
912#[derive(Debug, Clone, PartialEq)]
913pub enum FlagsRepr {
914    U8,
915    U16,
916    U32(usize),
917}
918
919impl Flags {
920    pub fn repr(&self) -> FlagsRepr {
921        match self.flags.len() {
922            0 => FlagsRepr::U32(0),
923            n if n <= 8 => FlagsRepr::U8,
924            n if n <= 16 => FlagsRepr::U16,
925            n => FlagsRepr::U32(sizealign::align_to(n, 32) / 32),
926        }
927    }
928}
929
930impl FlagsRepr {
931    pub fn count(&self) -> usize {
932        match self {
933            FlagsRepr::U8 => 1,
934            FlagsRepr::U16 => 1,
935            FlagsRepr::U32(n) => *n,
936        }
937    }
938}
939
940#[derive(Debug, Clone, PartialEq, Hash, Eq)]
941#[cfg_attr(feature = "serde", derive(Serialize))]
942pub struct Tuple {
943    pub types: Vec<Type>,
944}
945
946#[derive(Debug, Clone, PartialEq, Hash, Eq)]
947#[cfg_attr(feature = "serde", derive(Serialize))]
948pub struct Variant {
949    pub cases: Vec<Case>,
950}
951
952#[derive(Debug, Clone, PartialEq, Hash, Eq)]
953#[cfg_attr(feature = "serde", derive(Serialize))]
954pub struct Case {
955    pub name: String,
956    #[cfg_attr(feature = "serde", serde(rename = "type"))]
957    pub ty: Option<Type>,
958    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
959    pub docs: Docs,
960    /// Source span for this variant case.
961    #[cfg_attr(feature = "serde", serde(skip))]
962    pub span: Span,
963}
964
965impl Variant {
966    pub fn tag(&self) -> Int {
967        discriminant_type(self.cases.len())
968    }
969}
970
971#[derive(Debug, Clone, PartialEq, Hash, Eq)]
972#[cfg_attr(feature = "serde", derive(Serialize))]
973pub struct Enum {
974    pub cases: Vec<EnumCase>,
975}
976
977#[derive(Debug, Clone, PartialEq, Hash, Eq)]
978#[cfg_attr(feature = "serde", derive(Serialize))]
979pub struct EnumCase {
980    pub name: String,
981    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
982    pub docs: Docs,
983    /// Source span for this enum case.
984    #[cfg_attr(feature = "serde", serde(skip))]
985    pub span: Span,
986}
987
988impl Enum {
989    pub fn tag(&self) -> Int {
990        discriminant_type(self.cases.len())
991    }
992}
993
994/// This corresponds to the `discriminant_type` function in the Canonical ABI.
995fn discriminant_type(num_cases: usize) -> Int {
996    match num_cases.checked_sub(1) {
997        None => Int::U8,
998        Some(n) if n <= u8::max_value() as usize => Int::U8,
999        Some(n) if n <= u16::max_value() as usize => Int::U16,
1000        Some(n) if n <= u32::max_value() as usize => Int::U32,
1001        _ => panic!("too many cases to fit in a repr"),
1002    }
1003}
1004
1005#[derive(Debug, Clone, PartialEq, Hash, Eq)]
1006#[cfg_attr(feature = "serde", derive(Serialize))]
1007pub struct Result_ {
1008    pub ok: Option<Type>,
1009    pub err: Option<Type>,
1010}
1011
1012#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
1013#[cfg_attr(feature = "serde", derive(Serialize))]
1014pub struct Docs {
1015    pub contents: Option<String>,
1016}
1017
1018impl Docs {
1019    pub fn is_empty(&self) -> bool {
1020        self.contents.is_none()
1021    }
1022}
1023
1024#[derive(Debug, Clone, PartialEq, Eq)]
1025#[cfg_attr(feature = "serde", derive(Serialize))]
1026pub struct Param {
1027    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
1028    pub name: String,
1029    #[cfg_attr(feature = "serde", serde(rename = "type"))]
1030    pub ty: Type,
1031    #[cfg_attr(feature = "serde", serde(skip))]
1032    pub span: Span,
1033}
1034
1035#[derive(Debug, Clone, PartialEq, Eq)]
1036#[cfg_attr(feature = "serde", derive(Serialize))]
1037pub struct Function {
1038    pub name: String,
1039    pub kind: FunctionKind,
1040    pub params: Vec<Param>,
1041    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1042    pub result: Option<Type>,
1043    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
1044    pub docs: Docs,
1045    /// Stability attribute for this function.
1046    #[cfg_attr(
1047        feature = "serde",
1048        serde(skip_serializing_if = "Stability::is_unknown")
1049    )]
1050    pub stability: Stability,
1051
1052    /// Source span for this function.
1053    #[cfg_attr(feature = "serde", serde(skip))]
1054    pub span: Span,
1055}
1056
1057#[derive(Debug, Clone, PartialEq, Eq)]
1058#[cfg_attr(feature = "serde", derive(Serialize))]
1059#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1060pub enum FunctionKind {
1061    /// A freestanding function.
1062    ///
1063    /// ```wit
1064    /// interface foo {
1065    ///     the-func: func();
1066    /// }
1067    /// ```
1068    Freestanding,
1069
1070    /// An async freestanding function.
1071    ///
1072    /// ```wit
1073    /// interface foo {
1074    ///     the-func: async func();
1075    /// }
1076    /// ```
1077    AsyncFreestanding,
1078
1079    /// A resource method where the first parameter is implicitly
1080    /// `borrow<T>`.
1081    ///
1082    /// ```wit
1083    /// interface foo {
1084    ///     resource r {
1085    ///         the-func: func();
1086    ///     }
1087    /// }
1088    /// ```
1089    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1090    Method(TypeId),
1091
1092    /// An async resource method where the first parameter is implicitly
1093    /// `borrow<T>`.
1094    ///
1095    /// ```wit
1096    /// interface foo {
1097    ///     resource r {
1098    ///         the-func: async func();
1099    ///     }
1100    /// }
1101    /// ```
1102    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1103    AsyncMethod(TypeId),
1104
1105    /// A static resource method.
1106    ///
1107    /// ```wit
1108    /// interface foo {
1109    ///     resource r {
1110    ///         the-func: static func();
1111    ///     }
1112    /// }
1113    /// ```
1114    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1115    Static(TypeId),
1116
1117    /// An async static resource method.
1118    ///
1119    /// ```wit
1120    /// interface foo {
1121    ///     resource r {
1122    ///         the-func: static async func();
1123    ///     }
1124    /// }
1125    /// ```
1126    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1127    AsyncStatic(TypeId),
1128
1129    /// A resource constructor where the return value is implicitly `own<T>`.
1130    ///
1131    /// ```wit
1132    /// interface foo {
1133    ///     resource r {
1134    ///         constructor();
1135    ///     }
1136    /// }
1137    /// ```
1138    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1139    Constructor(TypeId),
1140}
1141
1142impl FunctionKind {
1143    /// Returns whether this is an async function or not.
1144    pub fn is_async(&self) -> bool {
1145        match self {
1146            FunctionKind::Freestanding
1147            | FunctionKind::Method(_)
1148            | FunctionKind::Static(_)
1149            | FunctionKind::Constructor(_) => false,
1150            FunctionKind::AsyncFreestanding
1151            | FunctionKind::AsyncMethod(_)
1152            | FunctionKind::AsyncStatic(_) => true,
1153        }
1154    }
1155
1156    /// Returns the resource, if present, that this function kind refers to.
1157    pub fn resource(&self) -> Option<TypeId> {
1158        match self {
1159            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
1160            FunctionKind::Method(id)
1161            | FunctionKind::Static(id)
1162            | FunctionKind::Constructor(id)
1163            | FunctionKind::AsyncMethod(id)
1164            | FunctionKind::AsyncStatic(id) => Some(*id),
1165        }
1166    }
1167
1168    /// Returns the resource, if present, that this function kind refers to.
1169    pub fn resource_mut(&mut self) -> Option<&mut TypeId> {
1170        match self {
1171            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
1172            FunctionKind::Method(id)
1173            | FunctionKind::Static(id)
1174            | FunctionKind::Constructor(id)
1175            | FunctionKind::AsyncMethod(id)
1176            | FunctionKind::AsyncStatic(id) => Some(id),
1177        }
1178    }
1179}
1180
1181/// Possible forms of name mangling that are supported by this crate.
1182#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1183pub enum Mangling {
1184    /// The "standard" component model mangling format for 32-bit linear
1185    /// memories. This is specified in WebAssembly/component-model#378
1186    Standard32,
1187
1188    /// The "legacy" name mangling supported in versions 218-and-prior for this
1189    /// crate. This is the original support for how components were created from
1190    /// core wasm modules and this does not correspond to any standard. This is
1191    /// preserved for now while tools transition to the new scheme.
1192    Legacy,
1193}
1194
1195impl core::str::FromStr for Mangling {
1196    type Err = anyhow::Error;
1197
1198    fn from_str(s: &str) -> Result<Mangling> {
1199        match s {
1200            "legacy" => Ok(Mangling::Legacy),
1201            "standard32" => Ok(Mangling::Standard32),
1202            _ => {
1203                bail!(
1204                    "unknown name mangling `{s}`, \
1205                     supported values are `legacy` or `standard32`"
1206                )
1207            }
1208        }
1209    }
1210}
1211
1212/// Possible lift/lower ABI choices supported when mangling names.
1213#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1214pub enum LiftLowerAbi {
1215    /// Both imports and exports will use the synchronous ABI.
1216    Sync,
1217
1218    /// Both imports and exports will use the async ABI (with a callback for
1219    /// each export).
1220    AsyncCallback,
1221
1222    /// Both imports and exports will use the async ABI (with no callbacks for
1223    /// exports).
1224    AsyncStackful,
1225}
1226
1227impl LiftLowerAbi {
1228    fn import_prefix(self) -> &'static str {
1229        match self {
1230            Self::Sync => "",
1231            Self::AsyncCallback | Self::AsyncStackful => "[async-lower]",
1232        }
1233    }
1234
1235    /// Get the import [`AbiVariant`] corresponding to this [`LiftLowerAbi`]
1236    pub fn import_variant(self) -> AbiVariant {
1237        match self {
1238            Self::Sync => AbiVariant::GuestImport,
1239            Self::AsyncCallback | Self::AsyncStackful => AbiVariant::GuestImportAsync,
1240        }
1241    }
1242
1243    fn export_prefix(self) -> &'static str {
1244        match self {
1245            Self::Sync => "",
1246            Self::AsyncCallback => "[async-lift]",
1247            Self::AsyncStackful => "[async-lift-stackful]",
1248        }
1249    }
1250
1251    /// Get the export [`AbiVariant`] corresponding to this [`LiftLowerAbi`]
1252    pub fn export_variant(self) -> AbiVariant {
1253        match self {
1254            Self::Sync => AbiVariant::GuestExport,
1255            Self::AsyncCallback => AbiVariant::GuestExportAsync,
1256            Self::AsyncStackful => AbiVariant::GuestExportAsyncStackful,
1257        }
1258    }
1259}
1260
1261/// Combination of [`Mangling`] and [`LiftLowerAbi`].
1262#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1263pub enum ManglingAndAbi {
1264    /// See [`Mangling::Standard32`].
1265    ///
1266    /// As of this writing, the standard name mangling only supports the
1267    /// synchronous ABI.
1268    Standard32,
1269
1270    /// See [`Mangling::Legacy`] and [`LiftLowerAbi`].
1271    Legacy(LiftLowerAbi),
1272}
1273
1274impl ManglingAndAbi {
1275    /// Get the import [`AbiVariant`] corresponding to this [`ManglingAndAbi`]
1276    pub fn import_variant(self) -> AbiVariant {
1277        match self {
1278            Self::Standard32 => AbiVariant::GuestImport,
1279            Self::Legacy(abi) => abi.import_variant(),
1280        }
1281    }
1282
1283    /// Get the export [`AbiVariant`] corresponding to this [`ManglingAndAbi`]
1284    pub fn export_variant(self) -> AbiVariant {
1285        match self {
1286            Self::Standard32 => AbiVariant::GuestExport,
1287            Self::Legacy(abi) => abi.export_variant(),
1288        }
1289    }
1290
1291    /// Switch the ABI to be sync if it's async.
1292    pub fn sync(self) -> Self {
1293        match self {
1294            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => self,
1295            Self::Legacy(LiftLowerAbi::AsyncCallback)
1296            | Self::Legacy(LiftLowerAbi::AsyncStackful) => Self::Legacy(LiftLowerAbi::Sync),
1297        }
1298    }
1299
1300    /// Returns whether this is an async ABI
1301    pub fn is_async(&self) -> bool {
1302        match self {
1303            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => false,
1304            Self::Legacy(LiftLowerAbi::AsyncCallback)
1305            | Self::Legacy(LiftLowerAbi::AsyncStackful) => true,
1306        }
1307    }
1308
1309    pub fn mangling(&self) -> Mangling {
1310        match self {
1311            Self::Standard32 => Mangling::Standard32,
1312            Self::Legacy(_) => Mangling::Legacy,
1313        }
1314    }
1315}
1316
1317impl Function {
1318    /// Adjusts all spans in this function by adding the given byte offset.
1319    pub(crate) fn adjust_spans(&mut self, offset: u32) {
1320        self.span.adjust(offset);
1321        for param in &mut self.params {
1322            param.span.adjust(offset);
1323        }
1324    }
1325
1326    pub fn item_name(&self) -> &str {
1327        match &self.kind {
1328            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => &self.name,
1329            FunctionKind::Method(_)
1330            | FunctionKind::Static(_)
1331            | FunctionKind::AsyncMethod(_)
1332            | FunctionKind::AsyncStatic(_) => &self.name[self.name.find('.').unwrap() + 1..],
1333            FunctionKind::Constructor(_) => "constructor",
1334        }
1335    }
1336
1337    /// Returns an iterator over the types used in parameters and results.
1338    ///
1339    /// Note that this iterator is not transitive, it only iterates over the
1340    /// direct references to types that this function has.
1341    pub fn parameter_and_result_types(&self) -> impl Iterator<Item = Type> + '_ {
1342        self.params.iter().map(|p| p.ty).chain(self.result)
1343    }
1344
1345    /// Gets the core export name for this function.
1346    pub fn standard32_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1347        self.core_export_name(interface, Mangling::Standard32)
1348    }
1349
1350    pub fn legacy_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1351        self.core_export_name(interface, Mangling::Legacy)
1352    }
1353    /// Gets the core export name for this function.
1354    pub fn core_export_name<'a>(
1355        &'a self,
1356        interface: Option<&str>,
1357        mangling: Mangling,
1358    ) -> Cow<'a, str> {
1359        match interface {
1360            Some(interface) => match mangling {
1361                Mangling::Standard32 => Cow::Owned(format!("cm32p2|{interface}|{}", self.name)),
1362                Mangling::Legacy => Cow::Owned(format!("{interface}#{}", self.name)),
1363            },
1364            None => match mangling {
1365                Mangling::Standard32 => Cow::Owned(format!("cm32p2||{}", self.name)),
1366                Mangling::Legacy => Cow::Borrowed(&self.name),
1367            },
1368        }
1369    }
1370    /// Collect any future and stream types appearing in the signature of this
1371    /// function by doing a depth-first search over the parameter types and then
1372    /// the result types.
1373    ///
1374    /// For example, given the WIT function `foo: func(x: future<future<u32>>,
1375    /// y: u32) -> stream<u8>`, we would return `[future<u32>,
1376    /// future<future<u32>>, stream<u8>]`.
1377    ///
1378    /// This may be used by binding generators to refer to specific `future` and
1379    /// `stream` types when importing canonical built-ins such as `stream.new`,
1380    /// `future.read`, etc.  Using the example above, the import
1381    /// `[future-new-0]foo` would indicate a call to `future.new` for the type
1382    /// `future<u32>`.  Likewise, `[future-new-1]foo` would indicate a call to
1383    /// `future.new` for `future<future<u32>>`, and `[stream-new-2]foo` would
1384    /// indicate a call to `stream.new` for `stream<u8>`.
1385    pub fn find_futures_and_streams(&self, resolve: &Resolve) -> Vec<TypeId> {
1386        let mut results = Vec::new();
1387        for param in self.params.iter() {
1388            find_futures_and_streams(resolve, param.ty, &mut results);
1389        }
1390        if let Some(ty) = self.result {
1391            find_futures_and_streams(resolve, ty, &mut results);
1392        }
1393        results
1394    }
1395
1396    /// Check if this function is a resource constructor in shorthand form.
1397    /// I.e. without an explicit return type annotation.
1398    pub fn is_constructor_shorthand(&self, resolve: &Resolve) -> bool {
1399        let FunctionKind::Constructor(containing_resource_id) = self.kind else {
1400            return false;
1401        };
1402
1403        let Some(Type::Id(id)) = &self.result else {
1404            return false;
1405        };
1406
1407        let TypeDefKind::Handle(Handle::Own(returned_resource_id)) = resolve.types[*id].kind else {
1408            return false;
1409        };
1410
1411        return containing_resource_id == returned_resource_id;
1412    }
1413
1414    /// Returns the `module`, `name`, and signature to use when importing this
1415    /// function's `task.return` intrinsic using the `mangling` specified.
1416    pub fn task_return_import(
1417        &self,
1418        resolve: &Resolve,
1419        interface: Option<&WorldKey>,
1420        mangling: Mangling,
1421    ) -> (String, String, abi::WasmSignature) {
1422        match mangling {
1423            Mangling::Standard32 => todo!(),
1424            Mangling::Legacy => {}
1425        }
1426        // For exported async functions, generate a `task.return` intrinsic.
1427        let module = match interface {
1428            Some(key) => format!("[export]{}", resolve.name_world_key(key)),
1429            None => "[export]$root".to_string(),
1430        };
1431        let name = format!("[task-return]{}", self.name);
1432
1433        let mut func_tmp = self.clone();
1434        func_tmp.params = Vec::new();
1435        func_tmp.result = None;
1436        if let Some(ty) = self.result {
1437            func_tmp.params.push(Param {
1438                name: "x".to_string(),
1439                ty,
1440                span: Default::default(),
1441            });
1442        }
1443        let sig = resolve.wasm_signature(AbiVariant::GuestImport, &func_tmp);
1444        (module, name, sig)
1445    }
1446
1447    // push_imported_future_and_stream_intrinsics(wat, resolve, "[export]", interface, func);
1448}
1449
1450fn find_futures_and_streams(resolve: &Resolve, ty: Type, results: &mut Vec<TypeId>) {
1451    let Type::Id(id) = ty else {
1452        return;
1453    };
1454
1455    match &resolve.types[id].kind {
1456        TypeDefKind::Resource
1457        | TypeDefKind::Handle(_)
1458        | TypeDefKind::Flags(_)
1459        | TypeDefKind::Enum(_) => {}
1460        TypeDefKind::Record(r) => {
1461            for Field { ty, .. } in &r.fields {
1462                find_futures_and_streams(resolve, *ty, results);
1463            }
1464        }
1465        TypeDefKind::Tuple(t) => {
1466            for ty in &t.types {
1467                find_futures_and_streams(resolve, *ty, results);
1468            }
1469        }
1470        TypeDefKind::Variant(v) => {
1471            for Case { ty, .. } in &v.cases {
1472                if let Some(ty) = ty {
1473                    find_futures_and_streams(resolve, *ty, results);
1474                }
1475            }
1476        }
1477        TypeDefKind::Option(ty)
1478        | TypeDefKind::List(ty)
1479        | TypeDefKind::FixedLengthList(ty, ..)
1480        | TypeDefKind::Type(ty) => {
1481            find_futures_and_streams(resolve, *ty, results);
1482        }
1483        TypeDefKind::Map(k, v) => {
1484            find_futures_and_streams(resolve, *k, results);
1485            find_futures_and_streams(resolve, *v, results);
1486        }
1487        TypeDefKind::Result(r) => {
1488            if let Some(ty) = r.ok {
1489                find_futures_and_streams(resolve, ty, results);
1490            }
1491            if let Some(ty) = r.err {
1492                find_futures_and_streams(resolve, ty, results);
1493            }
1494        }
1495        TypeDefKind::Future(ty) => {
1496            if let Some(ty) = ty {
1497                find_futures_and_streams(resolve, *ty, results);
1498            }
1499            results.push(id);
1500        }
1501        TypeDefKind::Stream(ty) => {
1502            if let Some(ty) = ty {
1503                find_futures_and_streams(resolve, *ty, results);
1504            }
1505            results.push(id);
1506        }
1507        TypeDefKind::Unknown => unreachable!(),
1508    }
1509}
1510
1511/// Representation of the stability attributes associated with a world,
1512/// interface, function, or type.
1513///
1514/// This is added for WebAssembly/component-model#332 where @since and @unstable
1515/// annotations were added to WIT.
1516///
1517/// The order of the of enum values is significant since it is used with Ord and PartialOrd
1518#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1519#[cfg_attr(feature = "serde", derive(serde_derive::Deserialize, Serialize))]
1520#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1521pub enum Stability {
1522    /// This item does not have either `@since` or `@unstable`.
1523    Unknown,
1524
1525    /// `@unstable(feature = foo)`
1526    ///
1527    /// This item is explicitly tagged `@unstable`. A feature name is listed and
1528    /// this item is excluded by default in `Resolve` unless explicitly enabled.
1529    Unstable {
1530        feature: String,
1531        #[cfg_attr(
1532            feature = "serde",
1533            serde(
1534                skip_serializing_if = "Option::is_none",
1535                default,
1536                serialize_with = "serialize_optional_version",
1537                deserialize_with = "deserialize_optional_version"
1538            )
1539        )]
1540        deprecated: Option<Version>,
1541    },
1542
1543    /// `@since(version = 1.2.3)`
1544    ///
1545    /// This item is explicitly tagged with `@since` as stable since the
1546    /// specified version.  This may optionally have a feature listed as well.
1547    Stable {
1548        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_version"))]
1549        #[cfg_attr(feature = "serde", serde(deserialize_with = "deserialize_version"))]
1550        since: Version,
1551        #[cfg_attr(
1552            feature = "serde",
1553            serde(
1554                skip_serializing_if = "Option::is_none",
1555                default,
1556                serialize_with = "serialize_optional_version",
1557                deserialize_with = "deserialize_optional_version"
1558            )
1559        )]
1560        deprecated: Option<Version>,
1561    },
1562}
1563
1564impl Stability {
1565    /// Returns whether this is `Stability::Unknown`.
1566    pub fn is_unknown(&self) -> bool {
1567        matches!(self, Stability::Unknown)
1568    }
1569
1570    pub fn is_stable(&self) -> bool {
1571        matches!(self, Stability::Stable { .. })
1572    }
1573}
1574
1575impl Default for Stability {
1576    fn default() -> Stability {
1577        Stability::Unknown
1578    }
1579}
1580
1581#[cfg(test)]
1582mod test {
1583    use super::*;
1584    use alloc::vec;
1585
1586    #[test]
1587    fn test_discriminant_type() {
1588        assert_eq!(discriminant_type(1), Int::U8);
1589        assert_eq!(discriminant_type(0x100), Int::U8);
1590        assert_eq!(discriminant_type(0x101), Int::U16);
1591        assert_eq!(discriminant_type(0x10000), Int::U16);
1592        assert_eq!(discriminant_type(0x10001), Int::U32);
1593        if let Ok(num_cases) = usize::try_from(0x100000000_u64) {
1594            assert_eq!(discriminant_type(num_cases), Int::U32);
1595        }
1596    }
1597
1598    #[test]
1599    fn test_find_futures_and_streams() {
1600        let mut resolve = Resolve::default();
1601        let t0 = resolve.types.alloc(TypeDef {
1602            name: None,
1603            kind: TypeDefKind::Future(Some(Type::U32)),
1604            owner: TypeOwner::None,
1605            docs: Docs::default(),
1606            stability: Stability::Unknown,
1607            span: Default::default(),
1608        });
1609        let t1 = resolve.types.alloc(TypeDef {
1610            name: None,
1611            kind: TypeDefKind::Future(Some(Type::Id(t0))),
1612            owner: TypeOwner::None,
1613            docs: Docs::default(),
1614            stability: Stability::Unknown,
1615            span: Default::default(),
1616        });
1617        let t2 = resolve.types.alloc(TypeDef {
1618            name: None,
1619            kind: TypeDefKind::Stream(Some(Type::U32)),
1620            owner: TypeOwner::None,
1621            docs: Docs::default(),
1622            stability: Stability::Unknown,
1623            span: Default::default(),
1624        });
1625        let found = Function {
1626            name: "foo".into(),
1627            kind: FunctionKind::Freestanding,
1628            params: vec![
1629                Param {
1630                    name: "p1".into(),
1631                    ty: Type::Id(t1),
1632                    span: Default::default(),
1633                },
1634                Param {
1635                    name: "p2".into(),
1636                    ty: Type::U32,
1637                    span: Default::default(),
1638                },
1639            ],
1640            result: Some(Type::Id(t2)),
1641            docs: Docs::default(),
1642            stability: Stability::Unknown,
1643            span: Default::default(),
1644        }
1645        .find_futures_and_streams(&resolve);
1646        assert_eq!(3, found.len());
1647        assert_eq!(t0, found[0]);
1648        assert_eq!(t1, found[1]);
1649        assert_eq!(t2, found[2]);
1650    }
1651}