wit_parser/
lib.rs

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