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, Vec<Stability>)>>,
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
453impl Hash for WorldKey {
454    fn hash<H: Hasher>(&self, hasher: &mut H) {
455        match self {
456            WorldKey::Name(s) => {
457                0u8.hash(hasher);
458                s.as_str().hash(hasher);
459            }
460            WorldKey::Interface(i) => {
461                1u8.hash(hasher);
462                i.hash(hasher);
463            }
464        }
465    }
466}
467
468impl PartialEq for WorldKey {
469    fn eq(&self, other: &WorldKey) -> bool {
470        match (self, other) {
471            (WorldKey::Name(a), WorldKey::Name(b)) => a.as_str() == b.as_str(),
472            (WorldKey::Name(_), _) => false,
473            (WorldKey::Interface(a), WorldKey::Interface(b)) => a == b,
474            (WorldKey::Interface(_), _) => false,
475        }
476    }
477}
478
479impl From<WorldKey> for String {
480    fn from(key: WorldKey) -> String {
481        match key {
482            WorldKey::Name(name) => name,
483            WorldKey::Interface(id) => format!("interface-{}", id.index()),
484        }
485    }
486}
487
488impl WorldKey {
489    /// Asserts that this is `WorldKey::Name` and returns the name.
490    #[track_caller]
491    pub fn unwrap_name(self) -> String {
492        match self {
493            WorldKey::Name(name) => name,
494            WorldKey::Interface(_) => panic!("expected a name, found interface"),
495        }
496    }
497}
498
499#[derive(Debug, Clone, PartialEq)]
500#[cfg_attr(feature = "serde", derive(Serialize))]
501#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
502pub enum WorldItem {
503    /// An interface is being imported or exported from a world, indicating that
504    /// it's a namespace of functions.
505    Interface {
506        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
507        id: InterfaceId,
508        #[cfg_attr(
509            feature = "serde",
510            serde(skip_serializing_if = "Stability::is_unknown")
511        )]
512        stability: Stability,
513    },
514
515    /// A function is being directly imported or exported from this world.
516    Function(Function),
517
518    /// A type is being exported from this world.
519    ///
520    /// Note that types are never imported into worlds at this time.
521    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
522    Type(TypeId),
523}
524
525impl WorldItem {
526    pub fn stability<'a>(&'a self, resolve: &'a Resolve) -> &'a Stability {
527        match self {
528            WorldItem::Interface { stability, .. } => stability,
529            WorldItem::Function(f) => &f.stability,
530            WorldItem::Type(id) => &resolve.types[*id].stability,
531        }
532    }
533}
534
535#[derive(Debug, Clone)]
536#[cfg_attr(feature = "serde", derive(Serialize))]
537pub struct Interface {
538    /// Optionally listed name of this interface.
539    ///
540    /// This is `None` for inline interfaces in worlds.
541    pub name: Option<String>,
542
543    /// Exported types from this interface.
544    ///
545    /// Export names are listed within the types themselves. Note that the
546    /// export name here matches the name listed in the `TypeDef`.
547    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
548    pub types: IndexMap<String, TypeId>,
549
550    /// Exported functions from this interface.
551    pub functions: IndexMap<String, Function>,
552
553    /// Documentation associated with this interface.
554    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
555    pub docs: Docs,
556
557    /// Stability attribute for this interface.
558    #[cfg_attr(
559        feature = "serde",
560        serde(skip_serializing_if = "Stability::is_unknown")
561    )]
562    pub stability: Stability,
563
564    /// The package that owns this interface.
565    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
566    pub package: Option<PackageId>,
567}
568
569#[derive(Debug, Clone, PartialEq)]
570#[cfg_attr(feature = "serde", derive(Serialize))]
571pub struct TypeDef {
572    pub name: Option<String>,
573    pub kind: TypeDefKind,
574    pub owner: TypeOwner,
575    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
576    pub docs: Docs,
577    /// Stability attribute for this type.
578    #[cfg_attr(
579        feature = "serde",
580        serde(skip_serializing_if = "Stability::is_unknown")
581    )]
582    pub stability: Stability,
583}
584
585#[derive(Debug, Clone, PartialEq, Hash, Eq)]
586#[cfg_attr(feature = "serde", derive(Serialize))]
587#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
588pub enum TypeDefKind {
589    Record(Record),
590    Resource,
591    Handle(Handle),
592    Flags(Flags),
593    Tuple(Tuple),
594    Variant(Variant),
595    Enum(Enum),
596    Option(Type),
597    Result(Result_),
598    List(Type),
599    Map(Type, Type),
600    FixedSizeList(Type, u32),
601    Future(Option<Type>),
602    Stream(Option<Type>),
603    Type(Type),
604
605    /// This represents a type of unknown structure imported from a foreign
606    /// interface.
607    ///
608    /// This variant is only used during the creation of `UnresolvedPackage` but
609    /// by the time a `Resolve` is created then this will not exist.
610    Unknown,
611}
612
613impl TypeDefKind {
614    pub fn as_str(&self) -> &'static str {
615        match self {
616            TypeDefKind::Record(_) => "record",
617            TypeDefKind::Resource => "resource",
618            TypeDefKind::Handle(handle) => match handle {
619                Handle::Own(_) => "own",
620                Handle::Borrow(_) => "borrow",
621            },
622            TypeDefKind::Flags(_) => "flags",
623            TypeDefKind::Tuple(_) => "tuple",
624            TypeDefKind::Variant(_) => "variant",
625            TypeDefKind::Enum(_) => "enum",
626            TypeDefKind::Option(_) => "option",
627            TypeDefKind::Result(_) => "result",
628            TypeDefKind::List(_) => "list",
629            TypeDefKind::Map(_, _) => "map",
630            TypeDefKind::FixedSizeList(..) => "fixed size list",
631            TypeDefKind::Future(_) => "future",
632            TypeDefKind::Stream(_) => "stream",
633            TypeDefKind::Type(_) => "type",
634            TypeDefKind::Unknown => "unknown",
635        }
636    }
637}
638
639#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
640#[cfg_attr(feature = "serde", derive(Serialize))]
641#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
642pub enum TypeOwner {
643    /// This type was defined within a `world` block.
644    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
645    World(WorldId),
646    /// This type was defined within an `interface` block.
647    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
648    Interface(InterfaceId),
649    /// This type wasn't inherently defined anywhere, such as a `list<T>`, which
650    /// doesn't need an owner.
651    #[cfg_attr(feature = "serde", serde(untagged, serialize_with = "serialize_none"))]
652    None,
653}
654
655#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
656#[cfg_attr(feature = "serde", derive(Serialize))]
657#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
658pub enum Handle {
659    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
660    Own(TypeId),
661    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
662    Borrow(TypeId),
663}
664
665#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
666pub enum Type {
667    Bool,
668    U8,
669    U16,
670    U32,
671    U64,
672    S8,
673    S16,
674    S32,
675    S64,
676    F32,
677    F64,
678    Char,
679    String,
680    ErrorContext,
681    Id(TypeId),
682}
683
684#[derive(Debug, Copy, Clone, Eq, PartialEq)]
685pub enum Int {
686    U8,
687    U16,
688    U32,
689    U64,
690}
691
692#[derive(Debug, Clone, PartialEq, Hash, Eq)]
693#[cfg_attr(feature = "serde", derive(Serialize))]
694pub struct Record {
695    pub fields: Vec<Field>,
696}
697
698#[derive(Debug, Clone, PartialEq, Hash, Eq)]
699#[cfg_attr(feature = "serde", derive(Serialize))]
700pub struct Field {
701    pub name: String,
702    #[cfg_attr(feature = "serde", serde(rename = "type"))]
703    pub ty: Type,
704    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
705    pub docs: Docs,
706}
707
708#[derive(Debug, Clone, PartialEq, Hash, Eq)]
709#[cfg_attr(feature = "serde", derive(Serialize))]
710pub struct Flags {
711    pub flags: Vec<Flag>,
712}
713
714#[derive(Debug, Clone, PartialEq, Hash, Eq)]
715#[cfg_attr(feature = "serde", derive(Serialize))]
716pub struct Flag {
717    pub name: String,
718    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
719    pub docs: Docs,
720}
721
722#[derive(Debug, Clone, PartialEq)]
723pub enum FlagsRepr {
724    U8,
725    U16,
726    U32(usize),
727}
728
729impl Flags {
730    pub fn repr(&self) -> FlagsRepr {
731        match self.flags.len() {
732            0 => FlagsRepr::U32(0),
733            n if n <= 8 => FlagsRepr::U8,
734            n if n <= 16 => FlagsRepr::U16,
735            n => FlagsRepr::U32(sizealign::align_to(n, 32) / 32),
736        }
737    }
738}
739
740impl FlagsRepr {
741    pub fn count(&self) -> usize {
742        match self {
743            FlagsRepr::U8 => 1,
744            FlagsRepr::U16 => 1,
745            FlagsRepr::U32(n) => *n,
746        }
747    }
748}
749
750#[derive(Debug, Clone, PartialEq, Hash, Eq)]
751#[cfg_attr(feature = "serde", derive(Serialize))]
752pub struct Tuple {
753    pub types: Vec<Type>,
754}
755
756#[derive(Debug, Clone, PartialEq, Hash, Eq)]
757#[cfg_attr(feature = "serde", derive(Serialize))]
758pub struct Variant {
759    pub cases: Vec<Case>,
760}
761
762#[derive(Debug, Clone, PartialEq, Hash, Eq)]
763#[cfg_attr(feature = "serde", derive(Serialize))]
764pub struct Case {
765    pub name: String,
766    #[cfg_attr(feature = "serde", serde(rename = "type"))]
767    pub ty: Option<Type>,
768    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
769    pub docs: Docs,
770}
771
772impl Variant {
773    pub fn tag(&self) -> Int {
774        discriminant_type(self.cases.len())
775    }
776}
777
778#[derive(Debug, Clone, PartialEq, Hash, Eq)]
779#[cfg_attr(feature = "serde", derive(Serialize))]
780pub struct Enum {
781    pub cases: Vec<EnumCase>,
782}
783
784#[derive(Debug, Clone, PartialEq, Hash, Eq)]
785#[cfg_attr(feature = "serde", derive(Serialize))]
786pub struct EnumCase {
787    pub name: String,
788    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
789    pub docs: Docs,
790}
791
792impl Enum {
793    pub fn tag(&self) -> Int {
794        discriminant_type(self.cases.len())
795    }
796}
797
798/// This corresponds to the `discriminant_type` function in the Canonical ABI.
799fn discriminant_type(num_cases: usize) -> Int {
800    match num_cases.checked_sub(1) {
801        None => Int::U8,
802        Some(n) if n <= u8::max_value() as usize => Int::U8,
803        Some(n) if n <= u16::max_value() as usize => Int::U16,
804        Some(n) if n <= u32::max_value() as usize => Int::U32,
805        _ => panic!("too many cases to fit in a repr"),
806    }
807}
808
809#[derive(Debug, Clone, PartialEq, Hash, Eq)]
810#[cfg_attr(feature = "serde", derive(Serialize))]
811pub struct Result_ {
812    pub ok: Option<Type>,
813    pub err: Option<Type>,
814}
815
816#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
817#[cfg_attr(feature = "serde", derive(Serialize))]
818pub struct Docs {
819    pub contents: Option<String>,
820}
821
822impl Docs {
823    pub fn is_empty(&self) -> bool {
824        self.contents.is_none()
825    }
826}
827
828#[derive(Debug, Clone, PartialEq, Eq)]
829#[cfg_attr(feature = "serde", derive(Serialize))]
830pub struct Function {
831    pub name: String,
832    pub kind: FunctionKind,
833    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_params"))]
834    pub params: Vec<(String, Type)>,
835    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
836    pub result: Option<Type>,
837    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
838    pub docs: Docs,
839    /// Stability attribute for this function.
840    #[cfg_attr(
841        feature = "serde",
842        serde(skip_serializing_if = "Stability::is_unknown")
843    )]
844    pub stability: Stability,
845}
846
847#[derive(Debug, Clone, PartialEq, Eq)]
848#[cfg_attr(feature = "serde", derive(Serialize))]
849#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
850pub enum FunctionKind {
851    /// A freestanding function.
852    ///
853    /// ```wit
854    /// interface foo {
855    ///     the-func: func();
856    /// }
857    /// ```
858    Freestanding,
859
860    /// An async freestanding function.
861    ///
862    /// ```wit
863    /// interface foo {
864    ///     the-func: async func();
865    /// }
866    /// ```
867    AsyncFreestanding,
868
869    /// A resource method where the first parameter is implicitly
870    /// `borrow<T>`.
871    ///
872    /// ```wit
873    /// interface foo {
874    ///     resource r {
875    ///         the-func: func();
876    ///     }
877    /// }
878    /// ```
879    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
880    Method(TypeId),
881
882    /// An async resource method where the first parameter is implicitly
883    /// `borrow<T>`.
884    ///
885    /// ```wit
886    /// interface foo {
887    ///     resource r {
888    ///         the-func: async func();
889    ///     }
890    /// }
891    /// ```
892    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
893    AsyncMethod(TypeId),
894
895    /// A static resource method.
896    ///
897    /// ```wit
898    /// interface foo {
899    ///     resource r {
900    ///         the-func: static func();
901    ///     }
902    /// }
903    /// ```
904    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
905    Static(TypeId),
906
907    /// An async static resource method.
908    ///
909    /// ```wit
910    /// interface foo {
911    ///     resource r {
912    ///         the-func: static async func();
913    ///     }
914    /// }
915    /// ```
916    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
917    AsyncStatic(TypeId),
918
919    /// A resource constructor where the return value is implicitly `own<T>`.
920    ///
921    /// ```wit
922    /// interface foo {
923    ///     resource r {
924    ///         constructor();
925    ///     }
926    /// }
927    /// ```
928    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
929    Constructor(TypeId),
930}
931
932impl FunctionKind {
933    /// Returns whether this is an async function or not.
934    pub fn is_async(&self) -> bool {
935        match self {
936            FunctionKind::Freestanding
937            | FunctionKind::Method(_)
938            | FunctionKind::Static(_)
939            | FunctionKind::Constructor(_) => false,
940            FunctionKind::AsyncFreestanding
941            | FunctionKind::AsyncMethod(_)
942            | FunctionKind::AsyncStatic(_) => true,
943        }
944    }
945
946    /// Returns the resource, if present, that this function kind refers to.
947    pub fn resource(&self) -> Option<TypeId> {
948        match self {
949            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
950            FunctionKind::Method(id)
951            | FunctionKind::Static(id)
952            | FunctionKind::Constructor(id)
953            | FunctionKind::AsyncMethod(id)
954            | FunctionKind::AsyncStatic(id) => Some(*id),
955        }
956    }
957
958    /// Returns the resource, if present, that this function kind refers to.
959    pub fn resource_mut(&mut self) -> Option<&mut TypeId> {
960        match self {
961            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
962            FunctionKind::Method(id)
963            | FunctionKind::Static(id)
964            | FunctionKind::Constructor(id)
965            | FunctionKind::AsyncMethod(id)
966            | FunctionKind::AsyncStatic(id) => Some(id),
967        }
968    }
969}
970
971/// Possible forms of name mangling that are supported by this crate.
972#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
973pub enum Mangling {
974    /// The "standard" component model mangling format for 32-bit linear
975    /// memories. This is specified in WebAssembly/component-model#378
976    Standard32,
977
978    /// The "legacy" name mangling supported in versions 218-and-prior for this
979    /// crate. This is the original support for how components were created from
980    /// core wasm modules and this does not correspond to any standard. This is
981    /// preserved for now while tools transition to the new scheme.
982    Legacy,
983}
984
985impl std::str::FromStr for Mangling {
986    type Err = anyhow::Error;
987
988    fn from_str(s: &str) -> Result<Mangling> {
989        match s {
990            "legacy" => Ok(Mangling::Legacy),
991            "standard32" => Ok(Mangling::Standard32),
992            _ => {
993                bail!(
994                    "unknown name mangling `{s}`, \
995                     supported values are `legacy` or `standard32`"
996                )
997            }
998        }
999    }
1000}
1001
1002/// Possible lift/lower ABI choices supported when mangling names.
1003#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1004pub enum LiftLowerAbi {
1005    /// Both imports and exports will use the synchronous ABI.
1006    Sync,
1007
1008    /// Both imports and exports will use the async ABI (with a callback for
1009    /// each export).
1010    AsyncCallback,
1011
1012    /// Both imports and exports will use the async ABI (with no callbacks for
1013    /// exports).
1014    AsyncStackful,
1015}
1016
1017impl LiftLowerAbi {
1018    fn import_prefix(self) -> &'static str {
1019        match self {
1020            Self::Sync => "",
1021            Self::AsyncCallback | Self::AsyncStackful => "[async-lower]",
1022        }
1023    }
1024
1025    /// Get the import [`AbiVariant`] corresponding to this [`LiftLowerAbi`]
1026    pub fn import_variant(self) -> AbiVariant {
1027        match self {
1028            Self::Sync => AbiVariant::GuestImport,
1029            Self::AsyncCallback | Self::AsyncStackful => AbiVariant::GuestImportAsync,
1030        }
1031    }
1032
1033    fn export_prefix(self) -> &'static str {
1034        match self {
1035            Self::Sync => "",
1036            Self::AsyncCallback => "[async-lift]",
1037            Self::AsyncStackful => "[async-lift-stackful]",
1038        }
1039    }
1040
1041    /// Get the export [`AbiVariant`] corresponding to this [`LiftLowerAbi`]
1042    pub fn export_variant(self) -> AbiVariant {
1043        match self {
1044            Self::Sync => AbiVariant::GuestExport,
1045            Self::AsyncCallback => AbiVariant::GuestExportAsync,
1046            Self::AsyncStackful => AbiVariant::GuestExportAsyncStackful,
1047        }
1048    }
1049}
1050
1051/// Combination of [`Mangling`] and [`LiftLowerAbi`].
1052#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1053pub enum ManglingAndAbi {
1054    /// See [`Mangling::Standard32`].
1055    ///
1056    /// As of this writing, the standard name mangling only supports the
1057    /// synchronous ABI.
1058    Standard32,
1059
1060    /// See [`Mangling::Legacy`] and [`LiftLowerAbi`].
1061    Legacy(LiftLowerAbi),
1062}
1063
1064impl ManglingAndAbi {
1065    /// Get the import [`AbiVariant`] corresponding to this [`ManglingAndAbi`]
1066    pub fn import_variant(self) -> AbiVariant {
1067        match self {
1068            Self::Standard32 => AbiVariant::GuestImport,
1069            Self::Legacy(abi) => abi.import_variant(),
1070        }
1071    }
1072
1073    /// Get the export [`AbiVariant`] corresponding to this [`ManglingAndAbi`]
1074    pub fn export_variant(self) -> AbiVariant {
1075        match self {
1076            Self::Standard32 => AbiVariant::GuestExport,
1077            Self::Legacy(abi) => abi.export_variant(),
1078        }
1079    }
1080
1081    /// Switch the ABI to be sync if it's async.
1082    pub fn sync(self) -> Self {
1083        match self {
1084            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => self,
1085            Self::Legacy(LiftLowerAbi::AsyncCallback)
1086            | Self::Legacy(LiftLowerAbi::AsyncStackful) => Self::Legacy(LiftLowerAbi::Sync),
1087        }
1088    }
1089
1090    /// Returns whether this is an async ABI
1091    pub fn is_async(&self) -> bool {
1092        match self {
1093            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => false,
1094            Self::Legacy(LiftLowerAbi::AsyncCallback)
1095            | Self::Legacy(LiftLowerAbi::AsyncStackful) => true,
1096        }
1097    }
1098
1099    pub fn mangling(&self) -> Mangling {
1100        match self {
1101            Self::Standard32 => Mangling::Standard32,
1102            Self::Legacy(_) => Mangling::Legacy,
1103        }
1104    }
1105}
1106
1107impl Function {
1108    pub fn item_name(&self) -> &str {
1109        match &self.kind {
1110            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => &self.name,
1111            FunctionKind::Method(_)
1112            | FunctionKind::Static(_)
1113            | FunctionKind::AsyncMethod(_)
1114            | FunctionKind::AsyncStatic(_) => &self.name[self.name.find('.').unwrap() + 1..],
1115            FunctionKind::Constructor(_) => "constructor",
1116        }
1117    }
1118
1119    /// Returns an iterator over the types used in parameters and results.
1120    ///
1121    /// Note that this iterator is not transitive, it only iterates over the
1122    /// direct references to types that this function has.
1123    pub fn parameter_and_result_types(&self) -> impl Iterator<Item = Type> + '_ {
1124        self.params.iter().map(|(_, t)| *t).chain(self.result)
1125    }
1126
1127    /// Gets the core export name for this function.
1128    pub fn standard32_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1129        self.core_export_name(interface, Mangling::Standard32)
1130    }
1131
1132    pub fn legacy_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1133        self.core_export_name(interface, Mangling::Legacy)
1134    }
1135    /// Gets the core export name for this function.
1136    pub fn core_export_name<'a>(
1137        &'a self,
1138        interface: Option<&str>,
1139        mangling: Mangling,
1140    ) -> Cow<'a, str> {
1141        match interface {
1142            Some(interface) => match mangling {
1143                Mangling::Standard32 => Cow::Owned(format!("cm32p2|{interface}|{}", self.name)),
1144                Mangling::Legacy => Cow::Owned(format!("{interface}#{}", self.name)),
1145            },
1146            None => match mangling {
1147                Mangling::Standard32 => Cow::Owned(format!("cm32p2||{}", self.name)),
1148                Mangling::Legacy => Cow::Borrowed(&self.name),
1149            },
1150        }
1151    }
1152    /// Collect any future and stream types appearing in the signature of this
1153    /// function by doing a depth-first search over the parameter types and then
1154    /// the result types.
1155    ///
1156    /// For example, given the WIT function `foo: func(x: future<future<u32>>,
1157    /// y: u32) -> stream<u8>`, we would return `[future<u32>,
1158    /// future<future<u32>>, stream<u8>]`.
1159    ///
1160    /// This may be used by binding generators to refer to specific `future` and
1161    /// `stream` types when importing canonical built-ins such as `stream.new`,
1162    /// `future.read`, etc.  Using the example above, the import
1163    /// `[future-new-0]foo` would indicate a call to `future.new` for the type
1164    /// `future<u32>`.  Likewise, `[future-new-1]foo` would indicate a call to
1165    /// `future.new` for `future<future<u32>>`, and `[stream-new-2]foo` would
1166    /// indicate a call to `stream.new` for `stream<u8>`.
1167    pub fn find_futures_and_streams(&self, resolve: &Resolve) -> Vec<TypeId> {
1168        let mut results = Vec::new();
1169        for (_, ty) in self.params.iter() {
1170            find_futures_and_streams(resolve, *ty, &mut results);
1171        }
1172        if let Some(ty) = self.result {
1173            find_futures_and_streams(resolve, ty, &mut results);
1174        }
1175        results
1176    }
1177
1178    /// Check if this function is a resource constructor in shorthand form.
1179    /// I.e. without an explicit return type annotation.
1180    pub fn is_constructor_shorthand(&self, resolve: &Resolve) -> bool {
1181        let FunctionKind::Constructor(containing_resource_id) = self.kind else {
1182            return false;
1183        };
1184
1185        let Some(Type::Id(id)) = &self.result else {
1186            return false;
1187        };
1188
1189        let TypeDefKind::Handle(Handle::Own(returned_resource_id)) = resolve.types[*id].kind else {
1190            return false;
1191        };
1192
1193        return containing_resource_id == returned_resource_id;
1194    }
1195
1196    /// Returns the `module`, `name`, and signature to use when importing this
1197    /// function's `task.return` intrinsic using the `mangling` specified.
1198    pub fn task_return_import(
1199        &self,
1200        resolve: &Resolve,
1201        interface: Option<&WorldKey>,
1202        mangling: Mangling,
1203    ) -> (String, String, abi::WasmSignature) {
1204        match mangling {
1205            Mangling::Standard32 => todo!(),
1206            Mangling::Legacy => {}
1207        }
1208        // For exported async functions, generate a `task.return` intrinsic.
1209        let module = match interface {
1210            Some(key) => format!("[export]{}", resolve.name_world_key(key)),
1211            None => "[export]$root".to_string(),
1212        };
1213        let name = format!("[task-return]{}", self.name);
1214
1215        let mut func_tmp = self.clone();
1216        func_tmp.params = Vec::new();
1217        func_tmp.result = None;
1218        if let Some(ty) = self.result {
1219            func_tmp.params.push(("x".to_string(), ty));
1220        }
1221        let sig = resolve.wasm_signature(AbiVariant::GuestImport, &func_tmp);
1222        (module, name, sig)
1223    }
1224
1225    // push_imported_future_and_stream_intrinsics(wat, resolve, "[export]", interface, func);
1226}
1227
1228fn find_futures_and_streams(resolve: &Resolve, ty: Type, results: &mut Vec<TypeId>) {
1229    let Type::Id(id) = ty else {
1230        return;
1231    };
1232
1233    match &resolve.types[id].kind {
1234        TypeDefKind::Resource
1235        | TypeDefKind::Handle(_)
1236        | TypeDefKind::Flags(_)
1237        | TypeDefKind::Enum(_) => {}
1238        TypeDefKind::Record(r) => {
1239            for Field { ty, .. } in &r.fields {
1240                find_futures_and_streams(resolve, *ty, results);
1241            }
1242        }
1243        TypeDefKind::Tuple(t) => {
1244            for ty in &t.types {
1245                find_futures_and_streams(resolve, *ty, results);
1246            }
1247        }
1248        TypeDefKind::Variant(v) => {
1249            for Case { ty, .. } in &v.cases {
1250                if let Some(ty) = ty {
1251                    find_futures_and_streams(resolve, *ty, results);
1252                }
1253            }
1254        }
1255        TypeDefKind::Option(ty)
1256        | TypeDefKind::List(ty)
1257        | TypeDefKind::FixedSizeList(ty, ..)
1258        | TypeDefKind::Type(ty) => {
1259            find_futures_and_streams(resolve, *ty, results);
1260        }
1261        TypeDefKind::Map(k, v) => {
1262            find_futures_and_streams(resolve, *k, results);
1263            find_futures_and_streams(resolve, *v, results);
1264        }
1265        TypeDefKind::Result(r) => {
1266            if let Some(ty) = r.ok {
1267                find_futures_and_streams(resolve, ty, results);
1268            }
1269            if let Some(ty) = r.err {
1270                find_futures_and_streams(resolve, ty, results);
1271            }
1272        }
1273        TypeDefKind::Future(ty) => {
1274            if let Some(ty) = ty {
1275                find_futures_and_streams(resolve, *ty, results);
1276            }
1277            results.push(id);
1278        }
1279        TypeDefKind::Stream(ty) => {
1280            if let Some(ty) = ty {
1281                find_futures_and_streams(resolve, *ty, results);
1282            }
1283            results.push(id);
1284        }
1285        TypeDefKind::Unknown => unreachable!(),
1286    }
1287}
1288
1289/// Representation of the stability attributes associated with a world,
1290/// interface, function, or type.
1291///
1292/// This is added for WebAssembly/component-model#332 where @since and @unstable
1293/// annotations were added to WIT.
1294///
1295/// The order of the of enum values is significant since it is used with Ord and PartialOrd
1296#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1297#[cfg_attr(feature = "serde", derive(serde_derive::Deserialize, Serialize))]
1298#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1299pub enum Stability {
1300    /// This item does not have either `@since` or `@unstable`.
1301    Unknown,
1302
1303    /// `@unstable(feature = foo)`
1304    ///
1305    /// This item is explicitly tagged `@unstable`. A feature name is listed and
1306    /// this item is excluded by default in `Resolve` unless explicitly enabled.
1307    Unstable {
1308        feature: String,
1309        #[cfg_attr(
1310            feature = "serde",
1311            serde(
1312                skip_serializing_if = "Option::is_none",
1313                default,
1314                serialize_with = "serialize_optional_version",
1315                deserialize_with = "deserialize_optional_version"
1316            )
1317        )]
1318        deprecated: Option<Version>,
1319    },
1320
1321    /// `@since(version = 1.2.3)`
1322    ///
1323    /// This item is explicitly tagged with `@since` as stable since the
1324    /// specified version.  This may optionally have a feature listed as well.
1325    Stable {
1326        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_version"))]
1327        #[cfg_attr(feature = "serde", serde(deserialize_with = "deserialize_version"))]
1328        since: Version,
1329        #[cfg_attr(
1330            feature = "serde",
1331            serde(
1332                skip_serializing_if = "Option::is_none",
1333                default,
1334                serialize_with = "serialize_optional_version",
1335                deserialize_with = "deserialize_optional_version"
1336            )
1337        )]
1338        deprecated: Option<Version>,
1339    },
1340}
1341
1342impl Stability {
1343    /// Returns whether this is `Stability::Unknown`.
1344    pub fn is_unknown(&self) -> bool {
1345        matches!(self, Stability::Unknown)
1346    }
1347
1348    pub fn is_stable(&self) -> bool {
1349        matches!(self, Stability::Stable { .. })
1350    }
1351}
1352
1353impl Default for Stability {
1354    fn default() -> Stability {
1355        Stability::Unknown
1356    }
1357}
1358
1359#[cfg(test)]
1360mod test {
1361    use super::*;
1362
1363    #[test]
1364    fn test_discriminant_type() {
1365        assert_eq!(discriminant_type(1), Int::U8);
1366        assert_eq!(discriminant_type(0x100), Int::U8);
1367        assert_eq!(discriminant_type(0x101), Int::U16);
1368        assert_eq!(discriminant_type(0x10000), Int::U16);
1369        assert_eq!(discriminant_type(0x10001), Int::U32);
1370        if let Ok(num_cases) = usize::try_from(0x100000000_u64) {
1371            assert_eq!(discriminant_type(num_cases), Int::U32);
1372        }
1373    }
1374
1375    #[test]
1376    fn test_find_futures_and_streams() {
1377        let mut resolve = Resolve::default();
1378        let t0 = resolve.types.alloc(TypeDef {
1379            name: None,
1380            kind: TypeDefKind::Future(Some(Type::U32)),
1381            owner: TypeOwner::None,
1382            docs: Docs::default(),
1383            stability: Stability::Unknown,
1384        });
1385        let t1 = resolve.types.alloc(TypeDef {
1386            name: None,
1387            kind: TypeDefKind::Future(Some(Type::Id(t0))),
1388            owner: TypeOwner::None,
1389            docs: Docs::default(),
1390            stability: Stability::Unknown,
1391        });
1392        let t2 = resolve.types.alloc(TypeDef {
1393            name: None,
1394            kind: TypeDefKind::Stream(Some(Type::U32)),
1395            owner: TypeOwner::None,
1396            docs: Docs::default(),
1397            stability: Stability::Unknown,
1398        });
1399        let found = Function {
1400            name: "foo".into(),
1401            kind: FunctionKind::Freestanding,
1402            params: vec![("p1".into(), Type::Id(t1)), ("p2".into(), Type::U32)],
1403            result: Some(Type::Id(t2)),
1404            docs: Docs::default(),
1405            stability: Stability::Unknown,
1406        }
1407        .find_futures_and_streams(&resolve);
1408        assert_eq!(3, found.len());
1409        assert_eq!(t0, found[0]);
1410        assert_eq!(t1, found[1]);
1411        assert_eq!(t2, found[2]);
1412    }
1413}