Coverage Report

Created: 2026-04-09 08:09

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