Coverage Report

Created: 2026-08-08 08:01

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