Coverage Report

Created: 2025-12-04 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wit-parser/src/resolve.rs
Line
Count
Source
1
use std::cmp::Ordering;
2
use std::collections::hash_map;
3
use std::collections::{BTreeMap, HashMap, HashSet};
4
use std::fmt;
5
use std::mem;
6
use std::path::{Path, PathBuf};
7
8
use anyhow::{Context, Result, anyhow, bail};
9
use id_arena::{Arena, Id};
10
use indexmap::{IndexMap, IndexSet};
11
use semver::Version;
12
#[cfg(feature = "serde")]
13
use serde_derive::Serialize;
14
15
use crate::ast::lex::Span;
16
use crate::ast::{ParsedUsePath, parse_use_path};
17
#[cfg(feature = "serde")]
18
use crate::serde_::{serialize_arena, serialize_id_map};
19
use crate::{
20
    AstItem, Docs, Error, Function, FunctionKind, Handle, IncludeName, Interface, InterfaceId,
21
    InterfaceSpan, LiftLowerAbi, ManglingAndAbi, PackageName, PackageNotFoundError, SourceMap,
22
    Stability, Type, TypeDef, TypeDefKind, TypeId, TypeIdVisitor, TypeOwner, UnresolvedPackage,
23
    UnresolvedPackageGroup, World, WorldId, WorldItem, WorldKey, WorldSpan,
24
};
25
26
pub use clone::CloneMaps;
27
28
mod clone;
29
30
/// Representation of a fully resolved set of WIT packages.
31
///
32
/// This structure contains a graph of WIT packages and all of their contents
33
/// merged together into the contained arenas. All items are sorted
34
/// topologically and everything here is fully resolved, so with a `Resolve` no
35
/// name lookups are necessary and instead everything is index-based.
36
///
37
/// Working with a WIT package requires inserting it into a `Resolve` to ensure
38
/// that all of its dependencies are satisfied. This will give the full picture
39
/// of that package's types and such.
40
///
41
/// Each item in a `Resolve` has a parent link to trace it back to the original
42
/// package as necessary.
43
#[derive(Default, Clone, Debug)]
44
#[cfg_attr(feature = "serde", derive(Serialize))]
45
pub struct Resolve {
46
    /// All known worlds within this `Resolve`.
47
    ///
48
    /// Each world points at a `PackageId` which is stored below. No ordering is
49
    /// guaranteed between this list of worlds.
50
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
51
    pub worlds: Arena<World>,
52
53
    /// All known interfaces within this `Resolve`.
54
    ///
55
    /// Each interface points at a `PackageId` which is stored below. No
56
    /// ordering is guaranteed between this list of interfaces.
57
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
58
    pub interfaces: Arena<Interface>,
59
60
    /// All known types within this `Resolve`.
61
    ///
62
    /// Types are topologically sorted such that any type referenced from one
63
    /// type is guaranteed to be defined previously. Otherwise though these are
64
    /// not sorted by interface for example.
65
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
66
    pub types: Arena<TypeDef>,
67
68
    /// All known packages within this `Resolve`.
69
    ///
70
    /// This list of packages is not sorted. Sorted packages can be queried
71
    /// through [`Resolve::topological_packages`].
72
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
73
    pub packages: Arena<Package>,
74
75
    /// A map of package names to the ID of the package with that name.
76
    #[cfg_attr(feature = "serde", serde(skip))]
77
    pub package_names: IndexMap<PackageName, PackageId>,
78
79
    /// Activated features for this [`Resolve`].
80
    ///
81
    /// This set of features is empty by default. This is consulted for
82
    /// `@unstable` annotations in loaded WIT documents. Any items with
83
    /// `@unstable` are filtered out unless their feature is present within this
84
    /// set.
85
    #[cfg_attr(feature = "serde", serde(skip))]
86
    pub features: IndexSet<String>,
87
88
    /// Activate all features for this [`Resolve`].
89
    #[cfg_attr(feature = "serde", serde(skip))]
90
    pub all_features: bool,
91
}
92
93
/// A WIT package within a `Resolve`.
94
///
95
/// A package is a collection of interfaces and worlds. Packages additionally
96
/// have a unique identifier that affects generated components and uniquely
97
/// identifiers this particular package.
98
#[derive(Clone, Debug)]
99
#[cfg_attr(feature = "serde", derive(Serialize))]
100
pub struct Package {
101
    /// A unique name corresponding to this package.
102
    pub name: PackageName,
103
104
    /// Documentation associated with this package.
105
    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
106
    pub docs: Docs,
107
108
    /// All interfaces contained in this packaged, keyed by the interface's
109
    /// name.
110
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
111
    pub interfaces: IndexMap<String, InterfaceId>,
112
113
    /// All worlds contained in this package, keyed by the world's name.
114
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
115
    pub worlds: IndexMap<String, WorldId>,
116
}
117
118
pub type PackageId = Id<Package>;
119
120
/// All the sources used during resolving a directory or path.
121
#[derive(Clone, Debug)]
122
pub struct PackageSourceMap {
123
    sources: Vec<Vec<PathBuf>>,
124
    package_id_to_source_map_idx: BTreeMap<PackageId, usize>,
125
}
126
127
impl PackageSourceMap {
128
0
    fn from_single_source(package_id: PackageId, source: &Path) -> Self {
129
0
        Self {
130
0
            sources: vec![vec![source.to_path_buf()]],
131
0
            package_id_to_source_map_idx: BTreeMap::from([(package_id, 0)]),
132
0
        }
133
0
    }
134
135
12.6k
    fn from_source_maps(
136
12.6k
        source_maps: Vec<SourceMap>,
137
12.6k
        package_id_to_source_map_idx: BTreeMap<PackageId, usize>,
138
12.6k
    ) -> PackageSourceMap {
139
25.7k
        for (package_id, idx) in &package_id_to_source_map_idx {
140
13.1k
            if *idx >= source_maps.len() {
141
0
                panic!(
142
0
                    "Invalid source map index: {}, package id: {:?}, source maps size: {}",
143
                    idx,
144
                    package_id,
145
0
                    source_maps.len()
146
                )
147
13.1k
            }
148
        }
149
150
        Self {
151
12.6k
            sources: source_maps
152
12.6k
                .into_iter()
153
12.6k
                .map(|source_map| {
154
12.6k
                    source_map
155
12.6k
                        .source_files()
156
21.7k
                        .map(|path| path.to_path_buf())
157
12.6k
                        .collect()
158
12.6k
                })
159
12.6k
                .collect(),
160
12.6k
            package_id_to_source_map_idx,
161
        }
162
12.6k
    }
163
164
    /// All unique source paths.
165
0
    pub fn paths(&self) -> impl Iterator<Item = &Path> {
166
        // Usually any two source map should not have duplicated source paths,
167
        // but it can happen, e.g. with using [`Resolve::push_str`] directly.
168
        // To be sure we use a set for deduplication here.
169
0
        self.sources
170
0
            .iter()
171
0
            .flatten()
172
0
            .map(|path_buf| path_buf.as_ref())
173
0
            .collect::<IndexSet<&Path>>()
174
0
            .into_iter()
175
0
    }
176
177
    /// Source paths for package
178
0
    pub fn package_paths(&self, id: PackageId) -> Option<impl Iterator<Item = &Path>> {
179
0
        self.package_id_to_source_map_idx
180
0
            .get(&id)
181
0
            .map(|&idx| self.sources[idx].iter().map(|path_buf| path_buf.as_ref()))
182
0
    }
183
}
184
185
enum ParsedFile {
186
    #[cfg(feature = "decoding")]
187
    Package(PackageId),
188
    Unresolved(UnresolvedPackageGroup),
189
}
190
191
/// Visitor helper for performing topological sort on a group of packages.
192
13.6k
fn visit<'a>(
193
13.6k
    pkg: &'a UnresolvedPackage,
194
13.6k
    pkg_details_map: &'a BTreeMap<PackageName, (UnresolvedPackage, usize)>,
195
13.6k
    order: &mut IndexSet<PackageName>,
196
13.6k
    visiting: &mut HashSet<&'a PackageName>,
197
13.6k
    source_maps: &[SourceMap],
198
13.6k
) -> Result<()> {
199
13.6k
    if order.contains(&pkg.name) {
200
508
        return Ok(());
201
13.1k
    }
202
203
13.1k
    match pkg_details_map.get(&pkg.name) {
204
13.1k
        Some(pkg_details) => {
205
13.1k
            let (_, source_maps_index) = pkg_details;
206
13.1k
            source_maps[*source_maps_index].rewrite_error(|| {
207
13.1k
                for (i, (dep, _)) in pkg.foreign_deps.iter().enumerate() {
208
1.87k
                    let span = pkg.foreign_dep_spans[i];
209
1.87k
                    if !visiting.insert(dep) {
210
0
                        bail!(Error::new(span, "package depends on itself"));
211
1.87k
                    }
212
1.87k
                    if let Some(dep) = pkg_details_map.get(dep) {
213
508
                        let (dep_pkg, _) = dep;
214
508
                        visit(dep_pkg, pkg_details_map, order, visiting, source_maps)?;
215
1.36k
                    }
216
1.87k
                    assert!(visiting.remove(dep));
217
                }
218
13.1k
                assert!(order.insert(pkg.name.clone()));
219
13.1k
                Ok(())
220
13.1k
            })
221
        }
222
0
        None => panic!("No pkg_details found for package when doing topological sort"),
223
    }
224
13.6k
}
225
226
impl Resolve {
227
    /// Creates a new [`Resolve`] with no packages/items inside of it.
228
0
    pub fn new() -> Resolve {
229
0
        Resolve::default()
230
0
    }
231
232
    /// Parse WIT packages from the input `path`.
233
    ///
234
    /// The input `path` can be one of:
235
    ///
236
    /// * A directory containing a WIT package with an optional `deps` directory
237
    ///   for any dependent WIT packages it references.
238
    /// * A single standalone WIT file.
239
    /// * A wasm-encoded WIT package as a single file in the wasm binary format.
240
    /// * A wasm-encoded WIT package as a single file in the wasm text format.
241
    ///
242
    /// In all of these cases packages are allowed to depend on previously
243
    /// inserted packages into this `Resolve`. Resolution for packages is based
244
    /// on the name of each package and reference.
245
    ///
246
    /// This method returns a `PackageId` and additionally a `PackageSourceMap`.
247
    /// The `PackageId` represent the main package that was parsed. For example if a single WIT
248
    /// file was specified  this will be the main package found in the file. For a directory this
249
    /// will be all the main package in the directory itself. The `PackageId` value is useful
250
    /// to pass to [`Resolve::select_world`] to take a user-specified world in a
251
    /// conventional fashion and select which to use for bindings generation.
252
    ///
253
    /// The returned [`PackageSourceMap`] contains all the sources used during this operation.
254
    /// This can be useful for systems that want to rebuild or regenerate bindings based on files modified,
255
    /// or for ones which like to identify the used files for a package.
256
    ///
257
    /// More information can also be found at [`Resolve::push_dir`] and
258
    /// [`Resolve::push_file`].
259
    pub fn push_path(&mut self, path: impl AsRef<Path>) -> Result<(PackageId, PackageSourceMap)> {
260
        self._push_path(path.as_ref())
261
    }
262
263
0
    fn _push_path(&mut self, path: &Path) -> Result<(PackageId, PackageSourceMap)> {
264
0
        if path.is_dir() {
265
0
            self.push_dir(path).with_context(|| {
266
0
                format!(
267
0
                    "failed to resolve directory while parsing WIT for path [{}]",
268
0
                    path.display()
269
                )
270
0
            })
271
        } else {
272
0
            let id = self.push_file(path)?;
273
0
            Ok((id, PackageSourceMap::from_single_source(id, path)))
274
        }
275
0
    }
276
277
12.6k
    fn sort_unresolved_packages(
278
12.6k
        &mut self,
279
12.6k
        main: UnresolvedPackageGroup,
280
12.6k
        deps: Vec<UnresolvedPackageGroup>,
281
12.6k
    ) -> Result<(PackageId, PackageSourceMap)> {
282
12.6k
        let mut pkg_details_map = BTreeMap::new();
283
12.6k
        let mut source_maps = Vec::new();
284
285
12.6k
        let mut insert = |group: UnresolvedPackageGroup| {
286
            let UnresolvedPackageGroup {
287
12.6k
                main,
288
12.6k
                nested,
289
12.6k
                source_map,
290
12.6k
            } = group;
291
12.6k
            let i = source_maps.len();
292
12.6k
            source_maps.push(source_map);
293
294
13.1k
            for pkg in nested.into_iter().chain([main]) {
295
13.1k
                let name = pkg.name.clone();
296
13.1k
                let my_span = pkg.package_name_span;
297
13.1k
                let (prev_pkg, prev_i) = match pkg_details_map.insert(name.clone(), (pkg, i)) {
298
0
                    Some(pair) => pair,
299
13.1k
                    None => continue,
300
                };
301
0
                let loc1 = source_maps[i].render_location(my_span);
302
0
                let loc2 = source_maps[prev_i].render_location(prev_pkg.package_name_span);
303
0
                bail!(
304
0
                    "\
305
0
package {name} is defined in two different locations:\n\
306
0
  * {loc1}\n\
307
0
  * {loc2}\n\
308
0
                     "
309
                )
310
            }
311
12.6k
            Ok(())
312
12.6k
        };
313
314
12.6k
        let main_name = main.main.name.clone();
315
12.6k
        insert(main)?;
316
12.6k
        for dep in deps {
317
0
            insert(dep)?;
318
        }
319
320
        // Perform a simple topological sort which will bail out on cycles
321
        // and otherwise determine the order that packages must be added to
322
        // this `Resolve`.
323
12.6k
        let mut order = IndexSet::new();
324
12.6k
        let mut visiting = HashSet::new();
325
13.1k
        for pkg_details in pkg_details_map.values() {
326
13.1k
            let (pkg, _) = pkg_details;
327
13.1k
            visit(
328
13.1k
                pkg,
329
13.1k
                &pkg_details_map,
330
13.1k
                &mut order,
331
13.1k
                &mut visiting,
332
13.1k
                &source_maps,
333
0
            )?;
334
        }
335
336
        // Ensure that the final output is topologically sorted. Use a set to ensure that we render
337
        // the buffers for each `SourceMap` only once, even though multiple packages may reference
338
        // the same `SourceMap`.
339
12.6k
        let mut package_id_to_source_map_idx = BTreeMap::new();
340
12.6k
        let mut main_pkg_id = None;
341
25.7k
        for name in order {
342
13.1k
            let (pkg, source_map_index) = pkg_details_map.remove(&name).unwrap();
343
13.1k
            let source_map = &source_maps[source_map_index];
344
13.1k
            let is_main = pkg.name == main_name;
345
13.1k
            let id = self.push(pkg, source_map)?;
346
13.1k
            if is_main {
347
12.6k
                assert!(main_pkg_id.is_none());
348
12.6k
                main_pkg_id = Some(id);
349
490
            }
350
13.1k
            package_id_to_source_map_idx.insert(id, source_map_index);
351
        }
352
353
12.6k
        Ok((
354
12.6k
            main_pkg_id.unwrap(),
355
12.6k
            PackageSourceMap::from_source_maps(source_maps, package_id_to_source_map_idx),
356
12.6k
        ))
357
12.6k
    }
358
359
    /// Parses the filesystem directory at `path` as a WIT package and returns
360
    /// a fully resolved [`PackageId`] list as a result.
361
    ///
362
    /// The directory itself is parsed with [`UnresolvedPackageGroup::parse_dir`]
363
    /// and then all packages found are inserted into this `Resolve`. The `path`
364
    /// specified may have a `deps` subdirectory which is probed automatically
365
    /// for any other WIT dependencies.
366
    ///
367
    /// The `deps` folder may contain:
368
    ///
369
    /// * `$path/deps/my-package/*.wit` - a directory that may contain multiple
370
    ///   WIT files. This is parsed with [`UnresolvedPackageGroup::parse_dir`]
371
    ///   and then inserted into this [`Resolve`]. Note that cannot recursively
372
    ///   contain a `deps` directory.
373
    /// * `$path/deps/my-package.wit` - a single-file WIT package. This is
374
    ///   parsed with [`Resolve::push_file`] and then added to `self` for
375
    ///   name resolution.
376
    /// * `$path/deps/my-package.{wasm,wat}` - a wasm-encoded WIT package either
377
    ///   in the text for binary format.
378
    ///
379
    /// In all cases entries in the `deps` folder are added to `self` first
380
    /// before adding files found in `path` itself. All WIT packages found are
381
    /// candidates for name-based resolution that other packages may use.
382
    ///
383
    /// This function returns a tuple of two values. The first value is a
384
    /// [`PackageId`], which represents the main WIT package found within
385
    /// `path`. This argument is useful for passing to [`Resolve::select_world`]
386
    /// for choosing something to bindgen with.
387
    ///
388
    /// The second value returned is a [`PackageSourceMap`], which contains all the sources
389
    /// that were parsed during resolving. This can be useful for:
390
    /// * build systems that want to rebuild bindings whenever one of the files changed
391
    /// * or other tools, which want to identify the sources for the resolved packages
392
0
    pub fn push_dir(&mut self, path: impl AsRef<Path>) -> Result<(PackageId, PackageSourceMap)> {
393
0
        self._push_dir(path.as_ref())
394
0
    }
395
396
0
    fn _push_dir(&mut self, path: &Path) -> Result<(PackageId, PackageSourceMap)> {
397
0
        let top_pkg = UnresolvedPackageGroup::parse_dir(path)
398
0
            .with_context(|| format!("failed to parse package: {}", path.display()))?;
399
0
        let deps = path.join("deps");
400
0
        let deps = self
401
0
            .parse_deps_dir(&deps)
402
0
            .with_context(|| format!("failed to parse dependency directory: {}", deps.display()))?;
403
404
0
        self.sort_unresolved_packages(top_pkg, deps)
405
0
    }
406
407
0
    fn parse_deps_dir(&mut self, path: &Path) -> Result<Vec<UnresolvedPackageGroup>> {
408
0
        let mut ret = Vec::new();
409
0
        if !path.exists() {
410
0
            return Ok(ret);
411
0
        }
412
0
        let mut entries = path
413
0
            .read_dir()
414
0
            .and_then(|i| i.collect::<std::io::Result<Vec<_>>>())
415
0
            .context("failed to read directory")?;
416
0
        entries.sort_by_key(|e| e.file_name());
417
0
        for dep in entries {
418
0
            let path = dep.path();
419
0
            let pkg = if dep.file_type()?.is_dir() || path.metadata()?.is_dir() {
420
                // If this entry is a directory or a symlink point to a
421
                // directory then always parse it as an `UnresolvedPackage`
422
                // since it's intentional to not support recursive `deps`
423
                // directories.
424
0
                UnresolvedPackageGroup::parse_dir(&path)
425
0
                    .with_context(|| format!("failed to parse package: {}", path.display()))?
426
            } else {
427
                // If this entry is a file then we may want to ignore it but
428
                // this may also be a standalone WIT file or a `*.wasm` or
429
                // `*.wat` encoded package.
430
0
                let filename = dep.file_name();
431
0
                match Path::new(&filename).extension().and_then(|s| s.to_str()) {
432
0
                    Some("wit") | Some("wat") | Some("wasm") => match self._push_file(&path)? {
433
                        #[cfg(feature = "decoding")]
434
0
                        ParsedFile::Package(_) => continue,
435
0
                        ParsedFile::Unresolved(pkg) => pkg,
436
                    },
437
438
                    // Other files in deps dir are ignored for now to avoid
439
                    // accidentally including things like `.DS_Store` files in
440
                    // the call below to `parse_dir`.
441
0
                    _ => continue,
442
                }
443
            };
444
0
            ret.push(pkg);
445
        }
446
0
        Ok(ret)
447
0
    }
448
449
    /// Parses the contents of `path` from the filesystem and pushes the result
450
    /// into this `Resolve`.
451
    ///
452
    /// The `path` referenced here can be one of:
453
    ///
454
    /// * A WIT file. Note that in this case this single WIT file will be the
455
    ///   entire package and any dependencies it has must already be in `self`.
456
    /// * A WIT package encoded as WebAssembly, either in text or binary form.
457
    ///   In this the package and all of its dependencies are automatically
458
    ///   inserted into `self`.
459
    ///
460
    /// In both situations the `PackageId`s of the resulting resolved packages
461
    /// are returned from this method. The return value is mostly useful in
462
    /// conjunction with [`Resolve::select_world`].
463
0
    pub fn push_file(&mut self, path: impl AsRef<Path>) -> Result<PackageId> {
464
0
        match self._push_file(path.as_ref())? {
465
            #[cfg(feature = "decoding")]
466
0
            ParsedFile::Package(id) => Ok(id),
467
0
            ParsedFile::Unresolved(pkg) => self.push_group(pkg),
468
        }
469
0
    }
470
471
0
    fn _push_file(&mut self, path: &Path) -> Result<ParsedFile> {
472
0
        let contents = std::fs::read(path)
473
0
            .with_context(|| format!("failed to read path for WIT [{}]", path.display()))?;
474
475
        // If decoding is enabled at compile time then try to see if this is a
476
        // wasm file.
477
        #[cfg(feature = "decoding")]
478
        {
479
            use crate::decoding::{DecodedWasm, decode};
480
481
            #[cfg(feature = "wat")]
482
            let is_wasm = wat::Detect::from_bytes(&contents).is_wasm();
483
            #[cfg(not(feature = "wat"))]
484
0
            let is_wasm = wasmparser::Parser::is_component(&contents);
485
486
0
            if is_wasm {
487
                #[cfg(feature = "wat")]
488
                let contents = wat::parse_bytes(&contents).map_err(|mut e| {
489
                    e.set_path(path);
490
                    e
491
                })?;
492
493
0
                match decode(&contents)? {
494
                    DecodedWasm::Component(..) => {
495
0
                        bail!("found an actual component instead of an encoded WIT package in wasm")
496
                    }
497
0
                    DecodedWasm::WitPackage(resolve, pkg) => {
498
0
                        let remap = self.merge(resolve)?;
499
0
                        return Ok(ParsedFile::Package(remap.packages[pkg.index()]));
500
                    }
501
                }
502
0
            }
503
        }
504
505
        // If this wasn't a wasm file then assume it's a WIT file.
506
0
        let text = match std::str::from_utf8(&contents) {
507
0
            Ok(s) => s,
508
0
            Err(_) => bail!("input file is not valid utf-8 [{}]", path.display()),
509
        };
510
0
        let pkgs = UnresolvedPackageGroup::parse(path, text)?;
511
0
        Ok(ParsedFile::Unresolved(pkgs))
512
0
    }
513
514
    /// Appends a new [`UnresolvedPackage`] to this [`Resolve`], creating a
515
    /// fully resolved package with no dangling references.
516
    ///
517
    /// All the dependencies of `unresolved` must already have been loaded
518
    /// within this `Resolve` via previous calls to `push` or other methods such
519
    /// as [`Resolve::push_path`].
520
    ///
521
    /// Any dependency resolution error or otherwise world-elaboration error
522
    /// will be returned here, if successful a package identifier is returned
523
    /// which corresponds to the package that was just inserted.
524
13.1k
    pub fn push(
525
13.1k
        &mut self,
526
13.1k
        unresolved: UnresolvedPackage,
527
13.1k
        source_map: &SourceMap,
528
13.1k
    ) -> Result<PackageId> {
529
13.1k
        let ret = source_map.rewrite_error(|| Remap::default().append(self, unresolved));
530
13.1k
        if ret.is_ok() {
531
13.1k
            #[cfg(debug_assertions)]
532
13.1k
            self.assert_valid();
533
13.1k
        }
534
13.1k
        ret
535
13.1k
    }
536
537
    /// Appends new [`UnresolvedPackageGroup`] to this [`Resolve`], creating a
538
    /// fully resolved package with no dangling references.
539
    ///
540
    /// Any dependency resolution error or otherwise world-elaboration error
541
    /// will be returned here, if successful a package identifier is returned
542
    /// which corresponds to the package that was just inserted.
543
    ///
544
    /// The returned [`PackageId`]s are listed in topologically sorted order.
545
12.6k
    pub fn push_group(&mut self, unresolved_group: UnresolvedPackageGroup) -> Result<PackageId> {
546
12.6k
        let (pkg_id, _) = self.sort_unresolved_packages(unresolved_group, Vec::new())?;
547
12.6k
        Ok(pkg_id)
548
12.6k
    }
549
550
    /// Convenience method for combining [`UnresolvedPackageGroup::parse`] and
551
    /// [`Resolve::push_group`].
552
    ///
553
    /// The `path` provided is used for error messages but otherwise is not
554
    /// read. This method does not touch the filesystem. The `contents` provided
555
    /// are the contents of a WIT package.
556
5.46k
    pub fn push_str(&mut self, path: impl AsRef<Path>, contents: &str) -> Result<PackageId> {
557
5.46k
        self.push_group(UnresolvedPackageGroup::parse(path.as_ref(), contents)?)
558
5.46k
    }
559
560
0
    pub fn all_bits_valid(&self, ty: &Type) -> bool {
561
0
        match ty {
562
            Type::U8
563
            | Type::S8
564
            | Type::U16
565
            | Type::S16
566
            | Type::U32
567
            | Type::S32
568
            | Type::U64
569
            | Type::S64
570
            | Type::F32
571
0
            | Type::F64 => true,
572
573
0
            Type::Bool | Type::Char | Type::String | Type::ErrorContext => false,
574
575
0
            Type::Id(id) => match &self.types[*id].kind {
576
                TypeDefKind::List(_)
577
                | TypeDefKind::Variant(_)
578
                | TypeDefKind::Enum(_)
579
                | TypeDefKind::Option(_)
580
                | TypeDefKind::Result(_)
581
                | TypeDefKind::Future(_)
582
0
                | TypeDefKind::Stream(_) => false,
583
0
                TypeDefKind::Type(t) | TypeDefKind::FixedSizeList(t, ..) => self.all_bits_valid(t),
584
585
0
                TypeDefKind::Handle(h) => match h {
586
0
                    crate::Handle::Own(_) => true,
587
0
                    crate::Handle::Borrow(_) => true,
588
                },
589
590
0
                TypeDefKind::Resource => false,
591
0
                TypeDefKind::Record(r) => r.fields.iter().all(|f| self.all_bits_valid(&f.ty)),
592
0
                TypeDefKind::Tuple(t) => t.types.iter().all(|t| self.all_bits_valid(t)),
593
594
                // FIXME: this could perhaps be `true` for multiples-of-32 but
595
                // seems better to probably leave this as unconditionally
596
                // `false` for now, may want to reconsider later?
597
0
                TypeDefKind::Flags(_) => false,
598
599
0
                TypeDefKind::Unknown => unreachable!(),
600
            },
601
        }
602
0
    }
603
604
    /// Merges all the contents of a different `Resolve` into this one. The
605
    /// `Remap` structure returned provides a mapping from all old indices to
606
    /// new indices
607
    ///
608
    /// This operation can fail if `resolve` disagrees with `self` about the
609
    /// packages being inserted. Otherwise though this will additionally attempt
610
    /// to "union" packages found in `resolve` with those found in `self`.
611
    /// Unioning packages is keyed on the name/url of packages for those with
612
    /// URLs present. If found then it's assumed that both `Resolve` instances
613
    /// were originally created from the same contents and are two views
614
    /// of the same package.
615
12.3k
    pub fn merge(&mut self, resolve: Resolve) -> Result<Remap> {
616
12.3k
        log::trace!(
617
0
            "merging {} packages into {} packages",
618
0
            resolve.packages.len(),
619
0
            self.packages.len()
620
        );
621
622
12.3k
        let mut map = MergeMap::new(&resolve, &self);
623
12.3k
        map.build()?;
624
        let MergeMap {
625
12.3k
            package_map,
626
12.3k
            interface_map,
627
12.3k
            type_map,
628
12.3k
            world_map,
629
12.3k
            interfaces_to_add,
630
12.3k
            worlds_to_add,
631
            ..
632
12.3k
        } = map;
633
634
        // With a set of maps from ids in `resolve` to ids in `self` the next
635
        // operation is to start moving over items and building a `Remap` to
636
        // update ids.
637
        //
638
        // Each component field of `resolve` is moved into `self` so long as
639
        // its ID is not within one of the maps above. If it's present in a map
640
        // above then that means the item is already present in `self` so a new
641
        // one need not be added. If it's not present in a map that means it's
642
        // not present in `self` so it must be added to an arena.
643
        //
644
        // When adding an item to an arena one of the `remap.update_*` methods
645
        // is additionally called to update all identifiers from pointers within
646
        // `resolve` to becoming pointers within `self`.
647
        //
648
        // Altogether this should weave all the missing items in `self` from
649
        // `resolve` into one structure while updating all identifiers to
650
        // be local within `self`.
651
652
12.3k
        let mut remap = Remap::default();
653
        let Resolve {
654
12.3k
            types,
655
12.3k
            worlds,
656
12.3k
            interfaces,
657
12.3k
            packages,
658
12.3k
            package_names,
659
            features: _,
660
            ..
661
12.3k
        } = resolve;
662
663
12.3k
        let mut moved_types = Vec::new();
664
69.4k
        for (id, mut ty) in types {
665
57.1k
            let new_id = match type_map.get(&id).copied() {
666
10
                Some(id) => {
667
10
                    update_stability(&ty.stability, &mut self.types[id].stability)?;
668
10
                    id
669
                }
670
                None => {
671
57.0k
                    log::debug!("moving type {:?}", ty.name);
672
57.0k
                    moved_types.push(id);
673
57.0k
                    remap.update_typedef(self, &mut ty, None)?;
674
57.0k
                    self.types.alloc(ty)
675
                }
676
            };
677
57.1k
            assert_eq!(remap.types.len(), id.index());
678
57.1k
            remap.types.push(Some(new_id));
679
        }
680
681
12.3k
        let mut moved_interfaces = Vec::new();
682
16.3k
        for (id, mut iface) in interfaces {
683
4.04k
            let new_id = match interface_map.get(&id).copied() {
684
6
                Some(id) => {
685
6
                    update_stability(&iface.stability, &mut self.interfaces[id].stability)?;
686
6
                    id
687
                }
688
                None => {
689
4.03k
                    log::debug!("moving interface {:?}", iface.name);
690
4.03k
                    moved_interfaces.push(id);
691
4.03k
                    remap.update_interface(self, &mut iface, None)?;
692
4.03k
                    self.interfaces.alloc(iface)
693
                }
694
            };
695
4.04k
            assert_eq!(remap.interfaces.len(), id.index());
696
4.04k
            remap.interfaces.push(Some(new_id));
697
        }
698
699
12.3k
        let mut moved_worlds = Vec::new();
700
28.8k
        for (id, mut world) in worlds {
701
16.4k
            let new_id = match world_map.get(&id).copied() {
702
0
                Some(world_id) => {
703
0
                    update_stability(&world.stability, &mut self.worlds[world_id].stability)?;
704
0
                    for from_import in world.imports.iter() {
705
0
                        Resolve::update_world_imports_stability(
706
0
                            from_import,
707
0
                            &mut self.worlds[world_id].imports,
708
0
                            &interface_map,
709
0
                        )?;
710
                    }
711
0
                    for from_export in world.exports.iter() {
712
0
                        Resolve::update_world_imports_stability(
713
0
                            from_export,
714
0
                            &mut self.worlds[world_id].exports,
715
0
                            &interface_map,
716
0
                        )?;
717
                    }
718
0
                    world_id
719
                }
720
                None => {
721
16.4k
                    log::debug!("moving world {}", world.name);
722
16.4k
                    moved_worlds.push(id);
723
32.9k
                    let mut update = |map: &mut IndexMap<WorldKey, WorldItem>| -> Result<_> {
724
32.9k
                        for (mut name, mut item) in mem::take(map) {
725
24.6k
                            remap.update_world_key(&mut name, None)?;
726
24.6k
                            match &mut item {
727
5.00k
                                WorldItem::Function(f) => remap.update_function(self, f, None)?,
728
4.54k
                                WorldItem::Interface { id, .. } => {
729
4.54k
                                    *id = remap.map_interface(*id, None)?
730
                                }
731
15.1k
                                WorldItem::Type(i) => *i = remap.map_type(*i, None)?,
732
                            }
733
24.6k
                            map.insert(name, item);
734
                        }
735
32.9k
                        Ok(())
736
32.9k
                    };
737
16.4k
                    update(&mut world.imports)?;
738
16.4k
                    update(&mut world.exports)?;
739
16.4k
                    self.worlds.alloc(world)
740
                }
741
            };
742
16.4k
            assert_eq!(remap.worlds.len(), id.index());
743
16.4k
            remap.worlds.push(Some(new_id));
744
        }
745
746
29.1k
        for (id, mut pkg) in packages {
747
16.8k
            let new_id = match package_map.get(&id).copied() {
748
105
                Some(id) => id,
749
                None => {
750
16.7k
                    for (_, id) in pkg.interfaces.iter_mut() {
751
1.15k
                        *id = remap.map_interface(*id, None)?;
752
                    }
753
16.7k
                    for (_, id) in pkg.worlds.iter_mut() {
754
16.3k
                        *id = remap.map_world(*id, None)?;
755
                    }
756
16.7k
                    self.packages.alloc(pkg)
757
                }
758
            };
759
16.8k
            assert_eq!(remap.packages.len(), id.index());
760
16.8k
            remap.packages.push(new_id);
761
        }
762
763
25.0k
        for (name, id) in package_names {
764
12.6k
            let id = remap.packages[id.index()];
765
12.6k
            if let Some(prev) = self.package_names.insert(name, id) {
766
105
                assert_eq!(prev, id);
767
12.5k
            }
768
        }
769
770
        // Fixup all "parent" links now.
771
        //
772
        // Note that this is only done for items that are actually moved from
773
        // `resolve` into `self`, which is tracked by the various `moved_*`
774
        // lists built incrementally above. The ids in the `moved_*` lists
775
        // are ids within `resolve`, so they're translated through `remap` to
776
        // ids within `self`.
777
28.8k
        for id in moved_worlds {
778
16.4k
            let id = remap.map_world(id, None)?;
779
16.4k
            if let Some(pkg) = self.worlds[id].package.as_mut() {
780
16.4k
                *pkg = remap.packages[pkg.index()];
781
16.4k
            }
782
        }
783
16.3k
        for id in moved_interfaces {
784
4.03k
            let id = remap.map_interface(id, None)?;
785
4.03k
            if let Some(pkg) = self.interfaces[id].package.as_mut() {
786
4.03k
                *pkg = remap.packages[pkg.index()];
787
4.03k
            }
788
        }
789
69.4k
        for id in moved_types {
790
57.0k
            let id = remap.map_type(id, None)?;
791
57.0k
            match &mut self.types[id].owner {
792
6.49k
                TypeOwner::Interface(id) => *id = remap.map_interface(*id, None)?,
793
15.1k
                TypeOwner::World(id) => *id = remap.map_world(*id, None)?,
794
35.4k
                TypeOwner::None => {}
795
            }
796
        }
797
798
        // And finally process items that were present in `resolve` but were
799
        // not present in `self`. This is only done for merged packages as
800
        // documents may be added to `self.documents` but wouldn't otherwise be
801
        // present in the `documents` field of the corresponding package.
802
12.3k
        for (name, pkg, iface) in interfaces_to_add {
803
8
            let prev = self.packages[pkg]
804
8
                .interfaces
805
8
                .insert(name, remap.map_interface(iface, None)?);
806
8
            assert!(prev.is_none());
807
        }
808
12.4k
        for (name, pkg, world) in worlds_to_add {
809
103
            let prev = self.packages[pkg]
810
103
                .worlds
811
103
                .insert(name, remap.map_world(world, None)?);
812
103
            assert!(prev.is_none());
813
        }
814
815
12.3k
        log::trace!("now have {} packages", self.packages.len());
816
817
        #[cfg(debug_assertions)]
818
        self.assert_valid();
819
12.3k
        Ok(remap)
820
12.3k
    }
821
822
0
    fn update_world_imports_stability(
823
0
        from_item: (&WorldKey, &WorldItem),
824
0
        into_items: &mut IndexMap<WorldKey, WorldItem>,
825
0
        interface_map: &HashMap<Id<Interface>, Id<Interface>>,
826
0
    ) -> Result<()> {
827
0
        match from_item.0 {
828
            WorldKey::Name(_) => {
829
                // No stability info to update here, only updating import/include stability
830
0
                Ok(())
831
            }
832
0
            key @ WorldKey::Interface(_) => {
833
0
                let new_key = MergeMap::map_name(key, interface_map);
834
0
                if let Some(into) = into_items.get_mut(&new_key) {
835
0
                    match (from_item.1, into) {
836
                        (
837
                            WorldItem::Interface {
838
0
                                id: aid,
839
0
                                stability: astability,
840
                            },
841
                            WorldItem::Interface {
842
0
                                id: bid,
843
0
                                stability: bstability,
844
                            },
845
                        ) => {
846
0
                            let aid = interface_map.get(aid).copied().unwrap_or(*aid);
847
0
                            assert_eq!(aid, *bid);
848
0
                            update_stability(astability, bstability)?;
849
0
                            Ok(())
850
                        }
851
0
                        _ => unreachable!(),
852
                    }
853
                } else {
854
                    // we've already matched all the imports/exports by the time we are calling this
855
                    // so this is unreachable since we should always find the item
856
0
                    unreachable!()
857
                }
858
            }
859
        }
860
0
    }
861
862
    /// Merges the world `from` into the world `into`.
863
    ///
864
    /// This will attempt to merge one world into another, unioning all of its
865
    /// imports and exports together. This is an operation performed by
866
    /// `wit-component`, for example where two different worlds from two
867
    /// different libraries were linked into the same core wasm file and are
868
    /// producing a singular world that will be the final component's
869
    /// interface.
870
    ///
871
    /// During the merge operation, some of the types and/or interfaces in
872
    /// `from` might need to be cloned so that backreferences point to `into`
873
    /// instead of `from`.  Any such clones will be added to `clone_maps`.
874
    ///
875
    /// This operation can fail if the imports/exports overlap.
876
12.3k
    pub fn merge_worlds(
877
12.3k
        &mut self,
878
12.3k
        from: WorldId,
879
12.3k
        into: WorldId,
880
12.3k
        clone_maps: &mut CloneMaps,
881
12.3k
    ) -> Result<()> {
882
12.3k
        let mut new_imports = Vec::new();
883
12.3k
        let mut new_exports = Vec::new();
884
885
12.3k
        let from_world = &self.worlds[from];
886
12.3k
        let into_world = &self.worlds[into];
887
888
12.3k
        log::trace!("merging {} into {}", from_world.name, into_world.name);
889
890
        // First walk over all the imports of `from` world and figure out what
891
        // to do with them.
892
        //
893
        // If the same item exists in `from` and `into` then merge it together
894
        // below with `merge_world_item` which basically asserts they're the
895
        // same. Otherwise queue up a new import since if `from` has more
896
        // imports than `into` then it's fine to add new imports.
897
16.1k
        for (name, from_import) in from_world.imports.iter() {
898
16.1k
            let name_str = self.name_world_key(name);
899
16.1k
            match into_world.imports.get(name) {
900
62
                Some(into_import) => {
901
62
                    log::trace!("info/from shared import on `{name_str}`");
902
62
                    self.merge_world_item(from_import, into_import)
903
62
                        .with_context(|| format!("failed to merge world import {name_str}"))?;
904
                }
905
                None => {
906
16.0k
                    log::trace!("new import: `{name_str}`");
907
16.0k
                    new_imports.push((name.clone(), from_import.clone()));
908
                }
909
            }
910
        }
911
912
        // Build a set of interfaces which are required to be imported because
913
        // of `into`'s exports. This set is then used below during
914
        // `ensure_can_add_world_export`.
915
        //
916
        // This is the set of interfaces which exports depend on that are
917
        // themselves not exports.
918
12.3k
        let mut must_be_imported = HashMap::new();
919
12.3k
        for (key, export) in into_world.exports.iter() {
920
28
            for dep in self.world_item_direct_deps(export) {
921
2
                if into_world.exports.contains_key(&WorldKey::Interface(dep)) {
922
1
                    continue;
923
1
                }
924
1
                self.foreach_interface_dep(dep, &mut |id| {
925
1
                    must_be_imported.insert(id, key.clone());
926
1
                });
927
            }
928
        }
929
930
        // Next walk over exports of `from` and process these similarly to
931
        // imports.
932
12.3k
        for (name, from_export) in from_world.exports.iter() {
933
2.28k
            let name_str = self.name_world_key(name);
934
2.28k
            match into_world.exports.get(name) {
935
5
                Some(into_export) => {
936
5
                    log::trace!("info/from shared export on `{name_str}`");
937
5
                    self.merge_world_item(from_export, into_export)
938
5
                        .with_context(|| format!("failed to merge world export {name_str}"))?;
939
                }
940
                None => {
941
2.27k
                    log::trace!("new export `{name_str}`");
942
                    // See comments in `ensure_can_add_world_export` for why
943
                    // this is slightly different than imports.
944
2.27k
                    self.ensure_can_add_world_export(
945
2.27k
                        into_world,
946
2.27k
                        name,
947
2.27k
                        from_export,
948
2.27k
                        &must_be_imported,
949
                    )
950
2.27k
                    .with_context(|| {
951
0
                        format!("failed to add export `{}`", self.name_world_key(name))
952
0
                    })?;
953
2.27k
                    new_exports.push((name.clone(), from_export.clone()));
954
                }
955
            }
956
        }
957
958
        // For all the new imports and exports they may need to be "cloned" to
959
        // be able to belong to the new world. For example:
960
        //
961
        // * Anonymous interfaces have a `package` field which points to the
962
        //   package of the containing world, but `from` and `into` may not be
963
        //   in the same package.
964
        //
965
        // * Type imports have an `owner` field that point to `from`, but they
966
        //   now need to point to `into` instead.
967
        //
968
        // Cloning is no trivial task, however, so cloning is delegated to a
969
        // submodule to perform a "deep" clone and copy items into new arena
970
        // entries as necessary.
971
12.3k
        let mut cloner = clone::Cloner::new(self, TypeOwner::World(from), TypeOwner::World(into));
972
12.3k
        cloner.register_world_type_overlap(from, into);
973
18.3k
        for (name, item) in new_imports.iter_mut().chain(&mut new_exports) {
974
18.3k
            cloner.world_item(name, item, clone_maps);
975
18.3k
        }
976
977
12.3k
        clone_maps.types.extend(cloner.types);
978
979
        // Insert any new imports and new exports found first.
980
12.3k
        let into_world = &mut self.worlds[into];
981
28.3k
        for (name, import) in new_imports {
982
16.0k
            let prev = into_world.imports.insert(name, import);
983
16.0k
            assert!(prev.is_none());
984
        }
985
14.5k
        for (name, export) in new_exports {
986
2.27k
            let prev = into_world.exports.insert(name, export);
987
2.27k
            assert!(prev.is_none());
988
        }
989
990
        #[cfg(debug_assertions)]
991
        self.assert_valid();
992
12.3k
        Ok(())
993
12.3k
    }
994
995
67
    fn merge_world_item(&self, from: &WorldItem, into: &WorldItem) -> Result<()> {
996
67
        let mut map = MergeMap::new(self, self);
997
67
        match (from, into) {
998
8
            (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
999
                // If these imports are the same that can happen, for
1000
                // example, when both worlds to `import foo:bar/baz;`. That
1001
                // foreign interface will point to the same interface within
1002
                // `Resolve`.
1003
8
                if from == into {
1004
6
                    return Ok(());
1005
2
                }
1006
1007
                // .. otherwise this MUST be a case of
1008
                // `import foo: interface { ... }`. If `from != into` but
1009
                // both `from` and `into` have the same name then the
1010
                // `WorldKey::Interface` case is ruled out as otherwise
1011
                // they'd have different names.
1012
                //
1013
                // In the case of an anonymous interface all we can do is
1014
                // ensure that the interfaces both match, so use `MergeMap`
1015
                // for that.
1016
2
                map.build_interface(*from, *into)
1017
2
                    .context("failed to merge interfaces")?;
1018
            }
1019
1020
            // Like `WorldKey::Name` interfaces for functions and types the
1021
            // structure is asserted to be the same.
1022
2
            (WorldItem::Function(from), WorldItem::Function(into)) => {
1023
2
                map.build_function(from, into)
1024
2
                    .context("failed to merge functions")?;
1025
            }
1026
49
            (WorldItem::Type(from), WorldItem::Type(into)) => {
1027
49
                map.build_type_id(*from, *into)
1028
49
                    .context("failed to merge types")?;
1029
            }
1030
1031
            // Kind-level mismatches are caught here.
1032
            (WorldItem::Interface { .. }, _)
1033
            | (WorldItem::Function { .. }, _)
1034
            | (WorldItem::Type { .. }, _) => {
1035
8
                bail!("different kinds of items");
1036
            }
1037
        }
1038
52
        assert!(map.interfaces_to_add.is_empty());
1039
52
        assert!(map.worlds_to_add.is_empty());
1040
52
        Ok(())
1041
67
    }
1042
1043
    /// This method ensures that the world export of `name` and `item` can be
1044
    /// added to the world `into` without changing the meaning of `into`.
1045
    ///
1046
    /// All dependencies of world exports must either be:
1047
    ///
1048
    /// * An export themselves
1049
    /// * An import with all transitive dependencies of the import also imported
1050
    ///
1051
    /// It's not possible to depend on an import which then also depends on an
1052
    /// export at some point, for example. This method ensures that if `name`
1053
    /// and `item` are added that this property is upheld.
1054
2.27k
    fn ensure_can_add_world_export(
1055
2.27k
        &self,
1056
2.27k
        into: &World,
1057
2.27k
        name: &WorldKey,
1058
2.27k
        item: &WorldItem,
1059
2.27k
        must_be_imported: &HashMap<InterfaceId, WorldKey>,
1060
2.27k
    ) -> Result<()> {
1061
2.27k
        assert!(!into.exports.contains_key(name));
1062
2.27k
        let name = self.name_world_key(name);
1063
1064
        // First make sure that all of this item's dependencies are either
1065
        // exported or the entire chain of imports rooted at that dependency are
1066
        // all imported.
1067
2.27k
        for dep in self.world_item_direct_deps(item) {
1068
210
            if into.exports.contains_key(&WorldKey::Interface(dep)) {
1069
0
                continue;
1070
210
            }
1071
210
            self.ensure_not_exported(into, dep)
1072
210
                .with_context(|| format!("failed validating export of `{name}`"))?;
1073
        }
1074
1075
        // Second make sure that this item, if it's an interface, will not alter
1076
        // the meaning of the preexisting world by ensuring that it's not in the
1077
        // set of "must be imported" items.
1078
2.27k
        if let WorldItem::Interface { id, .. } = item {
1079
1.27k
            if let Some(export) = must_be_imported.get(&id) {
1080
0
                let export_name = self.name_world_key(export);
1081
0
                bail!(
1082
0
                    "export `{export_name}` depends on `{name}` \
1083
0
                     previously as an import which will change meaning \
1084
0
                     if `{name}` is added as an export"
1085
                );
1086
1.27k
            }
1087
1.00k
        }
1088
1089
2.27k
        Ok(())
1090
2.27k
    }
1091
1092
285
    fn ensure_not_exported(&self, world: &World, id: InterfaceId) -> Result<()> {
1093
285
        let key = WorldKey::Interface(id);
1094
285
        let name = self.name_world_key(&key);
1095
285
        if world.exports.contains_key(&key) {
1096
0
            bail!(
1097
0
                "world exports `{name}` but it's also transitively used by an \
1098
0
                     import \
1099
0
                   which means that this is not valid"
1100
            )
1101
285
        }
1102
285
        for dep in self.interface_direct_deps(id) {
1103
75
            self.ensure_not_exported(world, dep)
1104
75
                .with_context(|| format!("failed validating transitive import dep `{name}`"))?;
1105
        }
1106
285
        Ok(())
1107
285
    }
1108
1109
    /// Returns an iterator of all the direct interface dependencies of this
1110
    /// `item`.
1111
    ///
1112
    /// Note that this doesn't include transitive dependencies, that must be
1113
    /// followed manually.
1114
2.30k
    fn world_item_direct_deps(&self, item: &WorldItem) -> impl Iterator<Item = InterfaceId> + '_ {
1115
2.30k
        let mut interface = None;
1116
2.30k
        let mut ty = None;
1117
2.30k
        match item {
1118
1.01k
            WorldItem::Function(_) => {}
1119
0
            WorldItem::Type(id) => ty = Some(*id),
1120
1.28k
            WorldItem::Interface { id, .. } => interface = Some(*id),
1121
        }
1122
1123
2.30k
        interface
1124
2.30k
            .into_iter()
1125
2.30k
            .flat_map(move |id| self.interface_direct_deps(id))
1126
2.30k
            .chain(ty.and_then(|t| self.type_interface_dep(t)))
1127
2.30k
    }
1128
1129
    /// Invokes `f` with `id` and all transitive interface dependencies of `id`.
1130
    ///
1131
    /// Note that `f` may be called with the same id multiple times.
1132
133
    fn foreach_interface_dep(&self, id: InterfaceId, f: &mut dyn FnMut(InterfaceId)) {
1133
133
        self._foreach_interface_dep(id, f, &mut HashSet::new())
1134
133
    }
1135
1136
    // Internal detail of `foreach_interface_dep` which uses a hash map to prune
1137
    // the visit tree to ensure that this doesn't visit an exponential number of
1138
    // interfaces.
1139
183
    fn _foreach_interface_dep(
1140
183
        &self,
1141
183
        id: InterfaceId,
1142
183
        f: &mut dyn FnMut(InterfaceId),
1143
183
        visited: &mut HashSet<InterfaceId>,
1144
183
    ) {
1145
183
        if !visited.insert(id) {
1146
26
            return;
1147
157
        }
1148
157
        f(id);
1149
157
        for dep in self.interface_direct_deps(id) {
1150
50
            self._foreach_interface_dep(dep, f, visited);
1151
50
        }
1152
183
    }
1153
1154
    /// Returns the ID of the specified `interface`.
1155
    ///
1156
    /// Returns `None` for unnamed interfaces.
1157
68.5k
    pub fn id_of(&self, interface: InterfaceId) -> Option<String> {
1158
68.5k
        let interface = &self.interfaces[interface];
1159
68.5k
        Some(self.id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1160
68.5k
    }
1161
1162
    /// Returns the "canonicalized interface name" of `interface`.
1163
    ///
1164
    /// Returns `None` for unnamed interfaces. See `BuildTargets.md` in the
1165
    /// upstream component model repository for more information about this.
1166
187
    pub fn canonicalized_id_of(&self, interface: InterfaceId) -> Option<String> {
1167
187
        let interface = &self.interfaces[interface];
1168
187
        Some(self.canonicalized_id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1169
187
    }
1170
1171
    /// Convert a world to an "importized" version where the world is updated
1172
    /// in-place to reflect what it would look like to be imported.
1173
    ///
1174
    /// This is a transformation which is used as part of the process of
1175
    /// importing a component today. For example when a component depends on
1176
    /// another component this is useful for generating WIT which can be use to
1177
    /// represent the component being imported. The general idea is that this
1178
    /// function will update the `world_id` specified such it imports the
1179
    /// functionality that it previously exported. The world will be left with
1180
    /// no exports.
1181
    ///
1182
    /// This world is then suitable for merging into other worlds or generating
1183
    /// bindings in a context that is importing the original world. This
1184
    /// is intended to be used as part of language tooling when depending on
1185
    /// other components.
1186
4.07k
    pub fn importize(&mut self, world_id: WorldId, out_world_name: Option<String>) -> Result<()> {
1187
        // Rename the world to avoid having it get confused with the original
1188
        // name of the world. Add `-importized` to it for now. Precisely how
1189
        // this new world is created may want to be updated over time if this
1190
        // becomes problematic.
1191
4.07k
        let world = &mut self.worlds[world_id];
1192
4.07k
        let pkg = &mut self.packages[world.package.unwrap()];
1193
4.07k
        pkg.worlds.shift_remove(&world.name);
1194
4.07k
        if let Some(name) = out_world_name {
1195
0
            world.name = name.clone();
1196
0
            pkg.worlds.insert(name, world_id);
1197
4.07k
        } else {
1198
4.07k
            world.name.push_str("-importized");
1199
4.07k
            pkg.worlds.insert(world.name.clone(), world_id);
1200
4.07k
        }
1201
1202
        // Trim all non-type definitions from imports. Types can be used by
1203
        // exported functions, for example, so they're preserved.
1204
5.32k
        world.imports.retain(|_, item| match item {
1205
3.72k
            WorldItem::Type(_) => true,
1206
1.59k
            _ => false,
1207
5.32k
        });
1208
1209
4.07k
        for (name, export) in mem::take(&mut world.exports) {
1210
735
            match (name.clone(), world.imports.insert(name, export)) {
1211
                // no previous item? this insertion was ok
1212
603
                (_, None) => {}
1213
1214
                // cannot overwrite an import with an export
1215
132
                (WorldKey::Name(name), Some(_)) => {
1216
132
                    bail!("world export `{name}` conflicts with import of same name");
1217
                }
1218
1219
                // Exports already don't overlap each other and the only imports
1220
                // preserved above were types so this shouldn't be reachable.
1221
0
                (WorldKey::Interface(_), _) => unreachable!(),
1222
            }
1223
        }
1224
1225
        // Fill out any missing transitive interface imports by elaborating this
1226
        // world which does that for us.
1227
3.94k
        self.elaborate_world(world_id)?;
1228
1229
        #[cfg(debug_assertions)]
1230
        self.assert_valid();
1231
3.94k
        Ok(())
1232
4.07k
    }
1233
1234
    /// Returns the ID of the specified `name` within the `pkg`.
1235
72.6k
    pub fn id_of_name(&self, pkg: PackageId, name: &str) -> String {
1236
72.6k
        let package = &self.packages[pkg];
1237
72.6k
        let mut base = String::new();
1238
72.6k
        base.push_str(&package.name.namespace);
1239
72.6k
        base.push_str(":");
1240
72.6k
        base.push_str(&package.name.name);
1241
72.6k
        base.push_str("/");
1242
72.6k
        base.push_str(name);
1243
72.6k
        if let Some(version) = &package.name.version {
1244
51.8k
            base.push_str(&format!("@{version}"));
1245
51.8k
        }
1246
72.6k
        base
1247
72.6k
    }
1248
1249
    /// Returns the "canonicalized interface name" of the specified `name`
1250
    /// within the `pkg`.
1251
    ///
1252
    /// See `BuildTargets.md` in the upstream component model repository for
1253
    /// more information about this.
1254
187
    pub fn canonicalized_id_of_name(&self, pkg: PackageId, name: &str) -> String {
1255
187
        let package = &self.packages[pkg];
1256
187
        let mut base = String::new();
1257
187
        base.push_str(&package.name.namespace);
1258
187
        base.push_str(":");
1259
187
        base.push_str(&package.name.name);
1260
187
        base.push_str("/");
1261
187
        base.push_str(name);
1262
187
        if let Some(version) = &package.name.version {
1263
151
            base.push_str("@");
1264
151
            let string = PackageName::version_compat_track_string(version);
1265
151
            base.push_str(&string);
1266
151
        }
1267
187
        base
1268
187
    }
1269
1270
    /// Selects a world from among the packages in a `Resolve`.
1271
    ///
1272
    /// A `Resolve` may have many packages, each with many worlds. Many WIT
1273
    /// tools need a specific world to operate on. This function choses a
1274
    /// world, failing if the choice is ambiguous.
1275
    ///
1276
    /// `main_packages` provides the package IDs returned by
1277
    /// [`push_path`](Resolve::push_path), [`push_dir`](Resolve::push_dir),
1278
    /// [`push_file`](Resolve::push_file), [`push_group`](Resolve::push_group),
1279
    /// and [`push_str`](Resolve::push_str), which are the "main packages",
1280
    /// as distinguished from any packages nested inside them.
1281
    ///
1282
    /// `world` is a world name such as from a `--world` command-line option or
1283
    /// a `world:` macro parameter. `world` can be:
1284
    ///
1285
    /// * A kebab-name of a world, for example `"the-world"`. It is resolved
1286
    ///   within the "main package", if there is exactly one.
1287
    ///
1288
    /// * An ID-based form of a world, for example `"wasi:http/proxy"`. Note
1289
    ///   that a version does not need to be specified in this string if
1290
    ///   there's only one package of the same name and it has a version. In
1291
    ///   this situation the version can be omitted.
1292
    ///
1293
    /// * `None`. If there's exactly one "main package" and it contains exactly
1294
    ///   one world, that world is chosen.
1295
    ///
1296
    /// If successful, the chosen `WorldId` is returned.
1297
    ///
1298
    /// # Examples
1299
    ///
1300
    /// ```
1301
    /// use anyhow::Result;
1302
    /// use wit_parser::Resolve;
1303
    ///
1304
    /// fn main() -> Result<()> {
1305
    ///     let mut resolve = Resolve::default();
1306
    ///
1307
    ///     // If there's a single package and only one world, that world is
1308
    ///     // the obvious choice.
1309
    ///     let wit1 = resolve.push_str(
1310
    ///         "./my-test.wit",
1311
    ///         r#"
1312
    ///             package example:wit1;
1313
    ///
1314
    ///             world foo {
1315
    ///                 // ...
1316
    ///             }
1317
    ///         "#,
1318
    ///     )?;
1319
    ///     assert!(resolve.select_world(&[wit1], None).is_ok());
1320
    ///
1321
    ///     // If there are multiple packages, we need to be told which package
1322
    ///     // to use, either by a "main package" or by a fully-qualified name.
1323
    ///     let wit2 = resolve.push_str(
1324
    ///         "./my-test.wit",
1325
    ///         r#"
1326
    ///             package example:wit2;
1327
    ///
1328
    ///             world foo { /* ... */ }
1329
    ///         "#,
1330
    ///     )?;
1331
    ///     assert!(resolve.select_world(&[wit1, wit2], None).is_err());
1332
    ///     assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
1333
    ///     // Fix: use fully-qualified names.
1334
    ///     assert!(resolve.select_world(&[wit1, wit2], Some("example:wit1/foo")).is_ok());
1335
    ///     assert!(resolve.select_world(&[wit1, wit2], Some("example:wit2/foo")).is_ok());
1336
    ///
1337
    ///     // If a package has multiple worlds, then we can't guess the world
1338
    ///     // even if we know the package.
1339
    ///     let wit3 = resolve.push_str(
1340
    ///         "./my-test.wit",
1341
    ///         r#"
1342
    ///             package example:wit3;
1343
    ///
1344
    ///             world foo { /* ... */ }
1345
    ///
1346
    ///             world bar { /* ... */ }
1347
    ///         "#,
1348
    ///     )?;
1349
    ///     assert!(resolve.select_world(&[wit3], None).is_err());
1350
    ///     // Fix: pick between "foo" and "bar" here.
1351
    ///     assert!(resolve.select_world(&[wit3], Some("foo")).is_ok());
1352
    ///
1353
    ///     // When selecting with a version it's ok to drop the version when
1354
    ///     // there's only a single copy of that package in `Resolve`.
1355
    ///     let wit5_1 = resolve.push_str(
1356
    ///         "./my-test.wit",
1357
    ///         r#"
1358
    ///             package example:wit5@1.0.0;
1359
    ///
1360
    ///             world foo { /* ... */ }
1361
    ///         "#,
1362
    ///     )?;
1363
    ///     assert!(resolve.select_world(&[wit5_1], Some("foo")).is_ok());
1364
    ///     assert!(resolve.select_world(&[wit5_1], Some("example:wit5/foo")).is_ok());
1365
    ///
1366
    ///     // However when a single package has multiple versions in a resolve
1367
    ///     // it's required to specify the version to select which one.
1368
    ///     let wit5_2 = resolve.push_str(
1369
    ///         "./my-test.wit",
1370
    ///         r#"
1371
    ///             package example:wit5@2.0.0;
1372
    ///
1373
    ///             world foo { /* ... */ }
1374
    ///         "#,
1375
    ///     )?;
1376
    ///     assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo")).is_err());
1377
    ///     // Fix: Pass explicit versions.
1378
    ///     assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo@1.0.0")).is_ok());
1379
    ///     assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo@2.0.0")).is_ok());
1380
    ///
1381
    ///     Ok(())
1382
    /// }
1383
    /// ```
1384
0
    pub fn select_world(
1385
0
        &self,
1386
0
        main_packages: &[PackageId],
1387
0
        world: Option<&str>,
1388
0
    ) -> Result<WorldId> {
1389
        // Determine if `world` is a kebab-name or an ID.
1390
0
        let world_path = match world {
1391
0
            Some(world) => Some(
1392
0
                parse_use_path(world)
1393
0
                    .with_context(|| format!("failed to parse world specifier `{world}`"))?,
1394
            ),
1395
0
            None => None,
1396
        };
1397
1398
0
        match world_path {
1399
            // We have a world path. If needed, pick a package to resolve it in.
1400
0
            Some(world_path) => {
1401
0
                let (pkg, world_name) = match (main_packages, world_path) {
1402
                    // We have no main packages; fail.
1403
0
                    ([], _) => bail!("No main packages defined"),
1404
1405
                    // We have exactly one main package.
1406
0
                    ([main_package], ParsedUsePath::Name(name)) => (*main_package, name),
1407
1408
                    // We have more than one main package; fail.
1409
0
                    (_, ParsedUsePath::Name(_name)) => {
1410
0
                        bail!(
1411
0
                            "There are multiple main packages; a world must be explicitly chosen:{}",
1412
0
                            self.worlds
1413
0
                                .iter()
1414
0
                                .map(|world| format!(
1415
0
                                    "\n  {}",
1416
0
                                    self.id_of_name(world.1.package.unwrap(), &world.1.name)
1417
                                ))
1418
0
                                .collect::<String>()
1419
                        )
1420
                    }
1421
1422
                    // The world name is fully-qualified.
1423
0
                    (_, ParsedUsePath::Package(pkg, world_name)) => {
1424
0
                        let pkg = match self.package_names.get(&pkg) {
1425
0
                            Some(pkg) => *pkg,
1426
                            None => {
1427
0
                                let mut candidates =
1428
0
                                    self.package_names.iter().filter(|(name, _)| {
1429
0
                                        pkg.version.is_none()
1430
0
                                            && pkg.name == name.name
1431
0
                                            && pkg.namespace == name.namespace
1432
0
                                            && name.version.is_some()
1433
0
                                    });
1434
0
                                let candidate = candidates.next();
1435
0
                                if let Some((c2, _)) = candidates.next() {
1436
0
                                    let (c1, _) = candidate.unwrap();
1437
0
                                    bail!(
1438
0
                                        "package name `{pkg}` is available at both \
1439
0
                                    versions {} and {} but which is not specified",
1440
0
                                        c1.version.as_ref().unwrap(),
1441
0
                                        c2.version.as_ref().unwrap(),
1442
                                    );
1443
0
                                }
1444
0
                                match candidate {
1445
0
                                    Some((_, id)) => *id,
1446
0
                                    None => bail!("unknown package `{pkg}`"),
1447
                                }
1448
                            }
1449
                        };
1450
0
                        (pkg, world_name.to_string())
1451
                    }
1452
                };
1453
1454
                // Now that we've picked the package, resolve the world name.
1455
0
                let pkg = &self.packages[pkg];
1456
0
                pkg.worlds.get(&world_name).copied().ok_or_else(|| {
1457
0
                    anyhow!("World `{world_name}` not found in package `{}`", pkg.name)
1458
0
                })
1459
            }
1460
1461
            // With no specified `world`, try to find a single obvious world.
1462
0
            None => match main_packages {
1463
0
                [] => bail!("No main packages defined"),
1464
1465
                // Check for exactly one main package with exactly one world.
1466
0
                [main_package] => {
1467
0
                    let pkg = &self.packages[*main_package];
1468
0
                    match pkg.worlds.len() {
1469
0
                        0 => bail!("The main package `{}` contains no worlds", pkg.name),
1470
0
                        1 => Ok(pkg.worlds[0]),
1471
0
                        _ => bail!(
1472
0
                            "There are multiple worlds in `{}`; one must be explicitly chosen:{}",
1473
                            pkg.name,
1474
0
                            pkg.worlds
1475
0
                                .values()
1476
0
                                .map(|world| format!(
1477
0
                                    "\n  {}",
1478
0
                                    self.id_of_name(*main_package, &self.worlds[*world].name)
1479
                                ))
1480
0
                                .collect::<String>()
1481
                        ),
1482
                    }
1483
                }
1484
1485
                // Multiple main packages and no world name; fail.
1486
                _ => {
1487
0
                    bail!(
1488
0
                        "There are multiple main packages; a world must be explicitly chosen:{}",
1489
0
                        self.worlds
1490
0
                            .iter()
1491
0
                            .map(|world| format!(
1492
0
                                "\n  {}",
1493
0
                                self.id_of_name(world.1.package.unwrap(), &world.1.name)
1494
                            ))
1495
0
                            .collect::<String>()
1496
                    )
1497
                }
1498
            },
1499
        }
1500
0
    }
1501
1502
    /// Assigns a human readable name to the `WorldKey` specified.
1503
72.9k
    pub fn name_world_key(&self, key: &WorldKey) -> String {
1504
72.9k
        match key {
1505
65.0k
            WorldKey::Name(s) => s.to_string(),
1506
7.92k
            WorldKey::Interface(i) => self.id_of(*i).expect("unexpected anonymous interface"),
1507
        }
1508
72.9k
    }
1509
1510
    /// Same as [`Resolve::name_world_key`] except that `WorldKey::Interfaces`
1511
    /// uses [`Resolve::canonicalized_id_of`].
1512
318
    pub fn name_canonicalized_world_key(&self, key: &WorldKey) -> String {
1513
318
        match key {
1514
205
            WorldKey::Name(s) => s.to_string(),
1515
113
            WorldKey::Interface(i) => self
1516
113
                .canonicalized_id_of(*i)
1517
113
                .expect("unexpected anonymous interface"),
1518
        }
1519
318
    }
1520
1521
    /// Returns the interface that `id` uses a type from, if it uses a type from
1522
    /// a different interface than `id` is defined within.
1523
    ///
1524
    /// If `id` is not a use-of-a-type or it's using a type in the same
1525
    /// interface then `None` is returned.
1526
139k
    pub fn type_interface_dep(&self, id: TypeId) -> Option<InterfaceId> {
1527
139k
        let ty = &self.types[id];
1528
33.8k
        let dep = match ty.kind {
1529
28.9k
            TypeDefKind::Type(Type::Id(id)) => id,
1530
110k
            _ => return None,
1531
        };
1532
28.9k
        let other = &self.types[dep];
1533
28.9k
        if ty.owner == other.owner {
1534
135
            None
1535
        } else {
1536
28.8k
            match other.owner {
1537
28.8k
                TypeOwner::Interface(id) => Some(id),
1538
0
                _ => unreachable!(),
1539
            }
1540
        }
1541
139k
    }
1542
1543
    /// Returns an iterator of all interfaces that the interface `id` depends
1544
    /// on.
1545
    ///
1546
    /// Interfaces may depend on others for type information to resolve type
1547
    /// imports.
1548
    ///
1549
    /// Note that the returned iterator may yield the same interface as a
1550
    /// dependency multiple times. Additionally only direct dependencies of `id`
1551
    /// are yielded, not transitive dependencies.
1552
102k
    pub fn interface_direct_deps(&self, id: InterfaceId) -> impl Iterator<Item = InterfaceId> + '_ {
1553
102k
        self.interfaces[id]
1554
102k
            .types
1555
102k
            .iter()
1556
102k
            .filter_map(move |(_name, ty)| self.type_interface_dep(*ty))
1557
102k
    }
1558
1559
    /// Returns an iterator of all packages that the package `id` depends
1560
    /// on.
1561
    ///
1562
    /// Packages may depend on others for type information to resolve type
1563
    /// imports or interfaces to resolve worlds.
1564
    ///
1565
    /// Note that the returned iterator may yield the same package as a
1566
    /// dependency multiple times. Additionally only direct dependencies of `id`
1567
    /// are yielded, not transitive dependencies.
1568
22.8k
    pub fn package_direct_deps(&self, id: PackageId) -> impl Iterator<Item = PackageId> + '_ {
1569
22.8k
        let pkg = &self.packages[id];
1570
1571
22.8k
        pkg.interfaces
1572
22.8k
            .iter()
1573
25.8k
            .flat_map(move |(_name, id)| self.interface_direct_deps(*id))
1574
24.6k
            .chain(pkg.worlds.iter().flat_map(move |(_name, id)| {
1575
24.6k
                let world = &self.worlds[*id];
1576
24.6k
                world
1577
24.6k
                    .imports
1578
24.6k
                    .iter()
1579
24.6k
                    .chain(world.exports.iter())
1580
36.8k
                    .filter_map(move |(_name, item)| match item {
1581
6.78k
                        WorldItem::Interface { id, .. } => Some(*id),
1582
7.47k
                        WorldItem::Function(_) => None,
1583
22.5k
                        WorldItem::Type(t) => self.type_interface_dep(*t),
1584
36.8k
                    })
1585
24.6k
            }))
1586
22.8k
            .filter_map(move |iface_id| {
1587
12.7k
                let pkg = self.interfaces[iface_id].package?;
1588
12.7k
                if pkg == id { None } else { Some(pkg) }
1589
12.7k
            })
1590
22.8k
    }
1591
1592
    /// Returns a topological ordering of packages contained in this `Resolve`.
1593
    ///
1594
    /// This returns a list of `PackageId` such that when visited in order it's
1595
    /// guaranteed that all dependencies will have been defined by prior items
1596
    /// in the list.
1597
17.7k
    pub fn topological_packages(&self) -> Vec<PackageId> {
1598
17.7k
        let mut pushed = vec![false; self.packages.len()];
1599
17.7k
        let mut order = Vec::new();
1600
22.8k
        for (id, _) in self.packages.iter() {
1601
22.8k
            self.build_topological_package_ordering(id, &mut pushed, &mut order);
1602
22.8k
        }
1603
17.7k
        order
1604
17.7k
    }
1605
1606
26.6k
    fn build_topological_package_ordering(
1607
26.6k
        &self,
1608
26.6k
        id: PackageId,
1609
26.6k
        pushed: &mut Vec<bool>,
1610
26.6k
        order: &mut Vec<PackageId>,
1611
26.6k
    ) {
1612
26.6k
        if pushed[id.index()] {
1613
3.79k
            return;
1614
22.8k
        }
1615
22.8k
        for dep in self.package_direct_deps(id) {
1616
3.79k
            self.build_topological_package_ordering(dep, pushed, order);
1617
3.79k
        }
1618
22.8k
        order.push(id);
1619
22.8k
        pushed[id.index()] = true;
1620
26.6k
    }
1621
1622
    #[doc(hidden)]
1623
5.46k
    pub fn assert_valid(&self) {
1624
5.46k
        let mut package_interfaces = Vec::new();
1625
5.46k
        let mut package_worlds = Vec::new();
1626
5.95k
        for (id, pkg) in self.packages.iter() {
1627
5.95k
            let mut interfaces = HashSet::new();
1628
24.7k
            for (name, iface) in pkg.interfaces.iter() {
1629
24.7k
                assert!(interfaces.insert(*iface));
1630
24.7k
                let iface = &self.interfaces[*iface];
1631
24.7k
                assert_eq!(name, iface.name.as_ref().unwrap());
1632
24.7k
                assert_eq!(iface.package.unwrap(), id);
1633
            }
1634
5.95k
            package_interfaces.push(pkg.interfaces.values().copied().collect::<HashSet<_>>());
1635
5.95k
            let mut worlds = HashSet::new();
1636
8.14k
            for (name, world) in pkg.worlds.iter() {
1637
8.14k
                assert!(worlds.insert(*world));
1638
8.14k
                assert_eq!(
1639
8.14k
                    pkg.worlds.get_key_value(name),
1640
8.14k
                    Some((name, world)),
1641
0
                    "`MutableKeys` impl may have been used to change a key's hash or equality"
1642
                );
1643
8.14k
                let world = &self.worlds[*world];
1644
8.14k
                assert_eq!(*name, world.name);
1645
8.14k
                assert_eq!(world.package.unwrap(), id);
1646
            }
1647
5.95k
            package_worlds.push(pkg.worlds.values().copied().collect::<HashSet<_>>());
1648
        }
1649
1650
5.46k
        let mut interface_types = Vec::new();
1651
26.1k
        for (id, iface) in self.interfaces.iter() {
1652
26.1k
            assert!(self.packages.get(iface.package.unwrap()).is_some());
1653
26.1k
            if iface.name.is_some() {
1654
24.7k
                assert!(package_interfaces[iface.package.unwrap().index()].contains(&id));
1655
1.41k
            }
1656
1657
26.1k
            for (name, ty) in iface.types.iter() {
1658
11.1k
                let ty = &self.types[*ty];
1659
11.1k
                assert_eq!(ty.name.as_ref(), Some(name));
1660
11.1k
                assert_eq!(ty.owner, TypeOwner::Interface(id));
1661
            }
1662
26.1k
            interface_types.push(iface.types.values().copied().collect::<HashSet<_>>());
1663
26.1k
            for (name, f) in iface.functions.iter() {
1664
9.43k
                assert_eq!(*name, f.name);
1665
            }
1666
        }
1667
1668
5.46k
        let mut world_types = Vec::new();
1669
8.14k
        for (id, world) in self.worlds.iter() {
1670
8.14k
            log::debug!("validating world {}", &world.name);
1671
8.14k
            if let Some(package) = world.package {
1672
8.14k
                assert!(self.packages.get(package).is_some());
1673
8.14k
                assert!(package_worlds[package.index()].contains(&id));
1674
0
            }
1675
8.14k
            assert!(world.includes.is_empty());
1676
1677
8.14k
            let mut types = HashSet::new();
1678
12.1k
            for (name, item) in world.imports.iter().chain(world.exports.iter()) {
1679
12.1k
                log::debug!("validating world item: {}", self.name_world_key(name));
1680
12.1k
                match item {
1681
2.23k
                    WorldItem::Interface { id, .. } => {
1682
                        // anonymous interfaces must belong to the same package
1683
                        // as the world's package.
1684
2.23k
                        if matches!(name, WorldKey::Name(_)) {
1685
1.41k
                            assert_eq!(self.interfaces[*id].package, world.package);
1686
816
                        }
1687
                    }
1688
2.47k
                    WorldItem::Function(f) => {
1689
2.47k
                        assert!(!matches!(name, WorldKey::Interface(_)));
1690
2.47k
                        assert_eq!(f.name, name.clone().unwrap_name());
1691
                    }
1692
7.45k
                    WorldItem::Type(ty) => {
1693
7.45k
                        assert!(!matches!(name, WorldKey::Interface(_)));
1694
7.45k
                        assert!(types.insert(*ty));
1695
7.45k
                        let ty = &self.types[*ty];
1696
7.45k
                        assert_eq!(ty.name, Some(name.clone().unwrap_name()));
1697
7.45k
                        assert_eq!(ty.owner, TypeOwner::World(id));
1698
                    }
1699
                }
1700
            }
1701
8.14k
            self.assert_world_elaborated(world);
1702
8.14k
            world_types.push(types);
1703
        }
1704
1705
73.0k
        for (ty_id, ty) in self.types.iter() {
1706
73.0k
            match ty.owner {
1707
11.1k
                TypeOwner::Interface(id) => {
1708
11.1k
                    assert!(self.interfaces.get(id).is_some());
1709
11.1k
                    assert!(interface_types[id.index()].contains(&ty_id));
1710
                }
1711
7.45k
                TypeOwner::World(id) => {
1712
7.45k
                    assert!(self.worlds.get(id).is_some());
1713
7.45k
                    assert!(world_types[id.index()].contains(&ty_id));
1714
                }
1715
54.4k
                TypeOwner::None => {}
1716
            }
1717
        }
1718
1719
5.46k
        self.assert_topologically_sorted();
1720
5.46k
    }
1721
1722
5.46k
    fn assert_topologically_sorted(&self) {
1723
5.46k
        let mut positions = IndexMap::new();
1724
5.95k
        for id in self.topological_packages() {
1725
5.95k
            let pkg = &self.packages[id];
1726
5.95k
            log::debug!("pkg {}", pkg.name);
1727
5.95k
            let prev = positions.insert(Some(id), IndexSet::new());
1728
5.95k
            assert!(prev.is_none());
1729
        }
1730
5.46k
        positions.insert(None, IndexSet::new());
1731
1732
26.1k
        for (id, iface) in self.interfaces.iter() {
1733
26.1k
            log::debug!("iface {:?}", iface.name);
1734
26.1k
            let ok = positions.get_mut(&iface.package).unwrap().insert(id);
1735
26.1k
            assert!(ok);
1736
        }
1737
1738
8.14k
        for (_, world) in self.worlds.iter() {
1739
8.14k
            log::debug!("world {:?}", world.name);
1740
1741
8.14k
            let my_package = world.package;
1742
8.14k
            let my_package_pos = positions.get_index_of(&my_package).unwrap();
1743
1744
12.1k
            for (_, item) in world.imports.iter().chain(&world.exports) {
1745
12.1k
                let id = match item {
1746
2.23k
                    WorldItem::Interface { id, .. } => *id,
1747
9.92k
                    _ => continue,
1748
                };
1749
2.23k
                let other_package = self.interfaces[id].package;
1750
2.23k
                let other_package_pos = positions.get_index_of(&other_package).unwrap();
1751
1752
2.23k
                assert!(other_package_pos <= my_package_pos);
1753
            }
1754
        }
1755
1756
73.0k
        for (_id, ty) in self.types.iter() {
1757
73.0k
            log::debug!("type {:?} {:?}", ty.name, ty.owner);
1758
4.61k
            let other_id = match ty.kind {
1759
4.05k
                TypeDefKind::Type(Type::Id(ty)) => ty,
1760
68.9k
                _ => continue,
1761
            };
1762
4.05k
            let other = &self.types[other_id];
1763
4.05k
            if ty.kind == other.kind {
1764
0
                continue;
1765
4.05k
            }
1766
4.05k
            let my_interface = match ty.owner {
1767
3.09k
                TypeOwner::Interface(id) => id,
1768
964
                _ => continue,
1769
            };
1770
3.09k
            let other_interface = match other.owner {
1771
3.09k
                TypeOwner::Interface(id) => id,
1772
0
                _ => continue,
1773
            };
1774
1775
3.09k
            let my_package = self.interfaces[my_interface].package;
1776
3.09k
            let other_package = self.interfaces[other_interface].package;
1777
3.09k
            let my_package_pos = positions.get_index_of(&my_package).unwrap();
1778
3.09k
            let other_package_pos = positions.get_index_of(&other_package).unwrap();
1779
1780
3.09k
            if my_package_pos == other_package_pos {
1781
1.76k
                let interfaces = &positions[&my_package];
1782
1.76k
                let my_interface_pos = interfaces.get_index_of(&my_interface).unwrap();
1783
1.76k
                let other_interface_pos = interfaces.get_index_of(&other_interface).unwrap();
1784
1.76k
                assert!(other_interface_pos <= my_interface_pos);
1785
            } else {
1786
1.32k
                assert!(other_package_pos < my_package_pos);
1787
            }
1788
        }
1789
5.46k
    }
1790
1791
8.14k
    fn assert_world_elaborated(&self, world: &World) {
1792
10.6k
        for (key, item) in world.imports.iter() {
1793
10.6k
            log::debug!(
1794
0
                "asserting elaborated world import {}",
1795
0
                self.name_world_key(key)
1796
            );
1797
10.6k
            match item {
1798
7.45k
                WorldItem::Type(t) => self.assert_world_imports_type_deps(world, key, *t),
1799
1800
                // All types referred to must be imported.
1801
1.80k
                WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1802
1803
                // All direct dependencies of this interface must be imported.
1804
1.39k
                WorldItem::Interface { id, .. } => {
1805
1.39k
                    for dep in self.interface_direct_deps(*id) {
1806
322
                        assert!(
1807
322
                            world.imports.contains_key(&WorldKey::Interface(dep)),
1808
0
                            "world import of {} is missing transitive dep of {}",
1809
0
                            self.name_world_key(key),
1810
0
                            self.id_of(dep).unwrap(),
1811
                        );
1812
                    }
1813
                }
1814
            }
1815
        }
1816
8.14k
        for (key, item) in world.exports.iter() {
1817
1.50k
            log::debug!(
1818
0
                "asserting elaborated world export {}",
1819
0
                self.name_world_key(key)
1820
            );
1821
1.50k
            match item {
1822
                // Types referred to by this function must be imported.
1823
666
                WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1824
1825
                // Dependencies of exported interfaces must also be exported, or
1826
                // if imported then that entire chain of imports must be
1827
                // imported and not exported.
1828
840
                WorldItem::Interface { id, .. } => {
1829
840
                    for dep in self.interface_direct_deps(*id) {
1830
140
                        let dep_key = WorldKey::Interface(dep);
1831
140
                        if world.exports.contains_key(&dep_key) {
1832
8
                            continue;
1833
132
                        }
1834
156
                        self.foreach_interface_dep(dep, &mut |dep| {
1835
156
                            let dep_key = WorldKey::Interface(dep);
1836
156
                            assert!(
1837
156
                                world.imports.contains_key(&dep_key),
1838
0
                                "world should import {} (required by {})",
1839
0
                                self.name_world_key(&dep_key),
1840
0
                                self.name_world_key(key),
1841
                            );
1842
156
                            assert!(
1843
156
                                !world.exports.contains_key(&dep_key),
1844
0
                                "world should not export {} (required by {})",
1845
0
                                self.name_world_key(&dep_key),
1846
0
                                self.name_world_key(key),
1847
                            );
1848
156
                        });
1849
                    }
1850
                }
1851
1852
                // exported types not allowed at this time
1853
0
                WorldItem::Type(_) => unreachable!(),
1854
            }
1855
        }
1856
8.14k
    }
1857
1858
9.70k
    fn assert_world_imports_type_deps(&self, world: &World, key: &WorldKey, ty: TypeId) {
1859
        // If this is a `use` statement then the referred-to interface must be
1860
        // imported into this world.
1861
9.70k
        let ty = &self.types[ty];
1862
1.14k
        if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
1863
974
            if let TypeOwner::Interface(id) = self.types[other].owner {
1864
970
                let key = WorldKey::Interface(id);
1865
970
                assert!(world.imports.contains_key(&key));
1866
970
                return;
1867
4
            }
1868
8.72k
        }
1869
1870
        // ... otherwise any named type that this type refers to, one level
1871
        // deep, must be imported into this world under that name.
1872
1873
8.73k
        let mut visitor = MyVisit(self, Vec::new());
1874
8.73k
        visitor.visit_type_def(self, ty);
1875
18.9k
        for ty in visitor.1 {
1876
10.2k
            let ty = &self.types[ty];
1877
10.2k
            let Some(name) = ty.name.clone() else {
1878
9.28k
                continue;
1879
            };
1880
936
            let dep_key = WorldKey::Name(name);
1881
936
            assert!(
1882
936
                world.imports.contains_key(&dep_key),
1883
0
                "world import `{}` should also force an import of `{}`",
1884
0
                self.name_world_key(key),
1885
0
                self.name_world_key(&dep_key),
1886
            );
1887
        }
1888
1889
        struct MyVisit<'a>(&'a Resolve, Vec<TypeId>);
1890
1891
        impl TypeIdVisitor for MyVisit<'_> {
1892
10.2k
            fn before_visit_type_id(&mut self, id: TypeId) -> bool {
1893
10.2k
                self.1.push(id);
1894
                // recurse into unnamed types to look at all named types
1895
10.2k
                self.0.types[id].name.is_none()
1896
10.2k
            }
1897
        }
1898
9.70k
    }
1899
1900
    /// This asserts that all types referred to by `func` are imported into
1901
    /// `world` under `WorldKey::Name`. Note that this is only applicable to
1902
    /// named type
1903
2.47k
    fn assert_world_function_imports_types(&self, world: &World, key: &WorldKey, func: &Function) {
1904
7.41k
        for ty in func
1905
2.47k
            .parameter_and_result_types()
1906
2.47k
            .chain(func.kind.resource().map(Type::Id))
1907
        {
1908
7.41k
            let Type::Id(id) = ty else {
1909
5.16k
                continue;
1910
            };
1911
2.25k
            self.assert_world_imports_type_deps(world, key, id);
1912
        }
1913
2.47k
    }
1914
1915
    /// Returns whether the `stability` annotation contained within `pkg_id`
1916
    /// should be included or not.
1917
    ///
1918
    /// The `span` provided here is an optional span pointing to the item that
1919
    /// is annotated with `stability`.
1920
    ///
1921
    /// Returns `Ok(true)` if the item is included, or `Ok(false)` if the item
1922
    /// is not.
1923
    ///
1924
    /// # Errors
1925
    ///
1926
    /// Returns an error if the `pkg_id` isn't annotated with sufficient version
1927
    /// information to have a `stability` annotation. For example if `pkg_id`
1928
    /// has no version listed then an error will be returned if `stability`
1929
    /// mentions a version.
1930
293k
    fn include_stability(
1931
293k
        &self,
1932
293k
        stability: &Stability,
1933
293k
        pkg_id: &PackageId,
1934
293k
        span: Option<Span>,
1935
293k
    ) -> Result<bool> {
1936
293k
        let err = |msg: String| match span {
1937
0
            Some(span) => Error::new(span, msg).into(),
1938
0
            None => anyhow::Error::msg(msg),
1939
0
        };
1940
293k
        Ok(match stability {
1941
286k
            Stability::Unknown => true,
1942
            // NOTE: deprecations are intentionally omitted -- an existing
1943
            // `@since` takes precedence over `@deprecated`
1944
5.65k
            Stability::Stable { since, .. } => {
1945
5.65k
                let Some(p) = self.packages.get(*pkg_id) else {
1946
                    // We can't check much without a package (possibly dealing
1947
                    // with an item in an `UnresolvedPackage`), @since version &
1948
                    // deprecations can't be checked because there's no package
1949
                    // version to compare to.
1950
                    //
1951
                    // Feature requirements on stabilized features are ignored
1952
                    // in resolved packages, so we do the same here.
1953
0
                    return Ok(true);
1954
                };
1955
1956
                // Use of feature gating with version specifiers inside a
1957
                // package that is not versioned is not allowed
1958
5.65k
                let package_version = p.name.version.as_ref().ok_or_else(|| {
1959
0
                    err(format!(
1960
0
                        "package [{}] contains a feature gate with a version \
1961
0
                         specifier, so it must have a version",
1962
0
                        p.name
1963
0
                    ))
1964
0
                })?;
1965
1966
                // If the version on the feature gate is:
1967
                // - released, then we can include it
1968
                // - unreleased, then we must check the feature (if present)
1969
5.65k
                if since > package_version {
1970
0
                    return Err(err(format!(
1971
0
                        "feature gate cannot reference unreleased version \
1972
0
                        {since} of package [{}] (current version {package_version})",
1973
0
                        p.name
1974
0
                    )));
1975
5.65k
                }
1976
1977
5.65k
                true
1978
            }
1979
2.02k
            Stability::Unstable { feature, .. } => {
1980
2.02k
                self.features.contains(feature) || self.all_features
1981
            }
1982
        })
1983
293k
    }
1984
1985
    /// Convenience wrapper around `include_stability` specialized for types
1986
    /// with a more targeted error message.
1987
143k
    fn include_type(&self, ty: &TypeDef, pkgid: PackageId, span: Span) -> Result<bool> {
1988
143k
        self.include_stability(&ty.stability, &pkgid, Some(span))
1989
143k
            .with_context(|| {
1990
0
                format!(
1991
0
                    "failed to process feature gate for type [{}] in package [{}]",
1992
0
                    ty.name.as_ref().map(String::as_str).unwrap_or("<unknown>"),
1993
0
                    self.packages[pkgid].name,
1994
                )
1995
0
            })
1996
143k
    }
1997
1998
    /// Performs the "elaboration process" necessary for the `world_id`
1999
    /// specified to ensure that all of its transitive imports are listed.
2000
    ///
2001
    /// This function will take the unordered lists of the specified world's
2002
    /// imports and exports and "elaborate" them to ensure that they're
2003
    /// topographically sorted where all transitively required interfaces by
2004
    /// imports, or exports, are listed. This will additionally validate that
2005
    /// the exports are all valid and present, specifically with the restriction
2006
    /// noted on `elaborate_world_exports`.
2007
    ///
2008
    /// The world is mutated in-place in this `Resolve`.
2009
34.8k
    fn elaborate_world(&mut self, world_id: WorldId) -> Result<()> {
2010
        // First process all imports. This is easier than exports since the only
2011
        // requirement here is that all interfaces need to be added with a
2012
        // topological order between them.
2013
34.8k
        let mut new_imports = IndexMap::new();
2014
34.8k
        let world = &self.worlds[world_id];
2015
2016
        // Sort the imports by "class" to ensure that this matches the order
2017
        // that items are printed and that items are in topological order.
2018
        //
2019
        // When printing worlds in WIT:
2020
        //
2021
        // * interfaces come first
2022
        // * types are next
2023
        //   * type imports are first
2024
        //   * type definitions are next
2025
        //   * resource definitions have methods printed inline
2026
        // * freestanding functions are last
2027
        //
2028
        // This reflects the topological order between items where types
2029
        // can refer to imports and functions can refer to these types. Ordering
2030
        // within a single class (e.g. imports depending on each other, types
2031
        // referring to each other) is already preserved by other passes in this
2032
        // file and general AST resolution. That means that a stable sort here
2033
        // can be used to ensure that each class is in the right location
2034
        // relative to the others.
2035
        //
2036
        // Overall this ensures that round-trips of WIT through wasm should
2037
        // always produce the same result.
2038
112k
        let sort_key = |resolve: &Resolve, item: &WorldItem| match item {
2039
12.0k
            WorldItem::Interface { .. } => 0,
2040
87.6k
            WorldItem::Type(ty) => {
2041
87.6k
                let ty = &resolve.types[*ty];
2042
11.6k
                match ty.kind {
2043
11.6k
                    TypeDefKind::Type(Type::Id(t)) if resolve.types[t].owner != ty.owner => 1,
2044
76.0k
                    _ => 2,
2045
                }
2046
            }
2047
12.8k
            WorldItem::Function(f) => {
2048
12.8k
                if f.kind.resource().is_none() {
2049
6.18k
                    3
2050
                } else {
2051
6.70k
                    4
2052
                }
2053
            }
2054
112k
        };
2055
2056
        // Sort world items when we start to elaborate the world to start with a
2057
        // topological view of items.
2058
34.8k
        let mut world_imports = world.imports.iter().collect::<Vec<_>>();
2059
70.0k
        world_imports.sort_by_key(|(_name, import)| sort_key(self, import));
2060
82.5k
        for (name, item) in world_imports {
2061
47.6k
            match item {
2062
                // Interfaces get their dependencies added first followed by the
2063
                // interface itself.
2064
5.15k
                WorldItem::Interface { id, stability } => {
2065
5.15k
                    self.elaborate_world_import(&mut new_imports, name.clone(), *id, &stability);
2066
5.15k
                }
2067
2068
                // Functions are added as-is since their dependence on types in
2069
                // the world should already be satisfied.
2070
                WorldItem::Function(_) => {
2071
6.88k
                    let prev = new_imports.insert(name.clone(), item.clone());
2072
6.88k
                    assert!(prev.is_none());
2073
                }
2074
2075
                // Types may depend on an interface, in which case a (possibly)
2076
                // recursive addition of that interface happens here. Afterwards
2077
                // the type itself can be added safely.
2078
35.5k
                WorldItem::Type(id) => {
2079
35.5k
                    if let Some(dep) = self.type_interface_dep(*id) {
2080
4.01k
                        self.elaborate_world_import(
2081
4.01k
                            &mut new_imports,
2082
4.01k
                            WorldKey::Interface(dep),
2083
4.01k
                            dep,
2084
4.01k
                            &self.types[*id].stability,
2085
4.01k
                        );
2086
31.5k
                    }
2087
35.5k
                    let prev = new_imports.insert(name.clone(), item.clone());
2088
35.5k
                    assert!(prev.is_none());
2089
                }
2090
            }
2091
        }
2092
2093
        // Exports are trickier than imports, notably to uphold the invariant
2094
        // required by `elaborate_world_exports`. To do this the exports are
2095
        // partitioned into interfaces/functions. All functions are added to
2096
        // the new exports list during this loop but interfaces are all deferred
2097
        // to be handled in the `elaborate_world_exports` function.
2098
34.8k
        let mut new_exports = IndexMap::new();
2099
34.8k
        let mut export_interfaces = IndexMap::new();
2100
34.8k
        for (name, item) in world.exports.iter() {
2101
5.33k
            match item {
2102
2.96k
                WorldItem::Interface { id, stability } => {
2103
2.96k
                    let prev = export_interfaces.insert(*id, (name.clone(), stability));
2104
2.96k
                    assert!(prev.is_none());
2105
                }
2106
                WorldItem::Function(_) => {
2107
2.36k
                    let prev = new_exports.insert(name.clone(), item.clone());
2108
2.36k
                    assert!(prev.is_none());
2109
                }
2110
0
                WorldItem::Type(_) => unreachable!(),
2111
            }
2112
        }
2113
2114
34.8k
        self.elaborate_world_exports(&export_interfaces, &mut new_imports, &mut new_exports)?;
2115
2116
        // In addition to sorting at the start of elaboration also sort here at
2117
        // the end of elaboration to handle types being interspersed with
2118
        // interfaces as they're found.
2119
42.5k
        new_imports.sort_by_cached_key(|_name, import| sort_key(self, import));
2120
2121
        // And with all that done the world is updated in-place with
2122
        // imports/exports.
2123
34.8k
        log::trace!("imports = {new_imports:?}");
2124
34.8k
        log::trace!("exports = {new_exports:?}");
2125
34.8k
        let world = &mut self.worlds[world_id];
2126
34.8k
        world.imports = new_imports;
2127
34.8k
        world.exports = new_exports;
2128
2129
34.8k
        Ok(())
2130
34.8k
    }
2131
2132
10.6k
    fn elaborate_world_import(
2133
10.6k
        &self,
2134
10.6k
        imports: &mut IndexMap<WorldKey, WorldItem>,
2135
10.6k
        key: WorldKey,
2136
10.6k
        id: InterfaceId,
2137
10.6k
        stability: &Stability,
2138
10.6k
    ) {
2139
10.6k
        if imports.contains_key(&key) {
2140
4.59k
            return;
2141
6.02k
        }
2142
6.02k
        for dep in self.interface_direct_deps(id) {
2143
1.44k
            self.elaborate_world_import(imports, WorldKey::Interface(dep), dep, stability);
2144
1.44k
        }
2145
6.02k
        let prev = imports.insert(
2146
6.02k
            key,
2147
6.02k
            WorldItem::Interface {
2148
6.02k
                id,
2149
6.02k
                stability: stability.clone(),
2150
6.02k
            },
2151
        );
2152
6.02k
        assert!(prev.is_none());
2153
10.6k
    }
2154
2155
    /// This function adds all of the interfaces in `export_interfaces` to the
2156
    /// list of exports of the `world` specified.
2157
    ///
2158
    /// This method is more involved than adding imports because it is fallible.
2159
    /// Chiefly what can happen is that the dependencies of all exports must be
2160
    /// satisfied by other exports or imports, but not both. For example given a
2161
    /// situation such as:
2162
    ///
2163
    /// ```wit
2164
    /// interface a {
2165
    ///     type t = u32
2166
    /// }
2167
    /// interface b {
2168
    ///     use a.{t}
2169
    /// }
2170
    /// interface c {
2171
    ///     use a.{t}
2172
    ///     use b.{t as t2}
2173
    /// }
2174
    /// ```
2175
    ///
2176
    /// where `c` depends on `b` and `a` where `b` depends on `a`, then the
2177
    /// purpose of this method is to reject this world:
2178
    ///
2179
    /// ```wit
2180
    /// world foo {
2181
    ///     export a
2182
    ///     export c
2183
    /// }
2184
    /// ```
2185
    ///
2186
    /// The reasoning here is unfortunately subtle and is additionally the
2187
    /// subject of WebAssembly/component-model#208. Effectively the `c`
2188
    /// interface depends on `b`, but it's not listed explicitly as an import,
2189
    /// so it's then implicitly added as an import. This then transitively
2190
    /// depends on `a` so it's also added as an import. At this point though `c`
2191
    /// also depends on `a`, and it's also exported, so naively it should depend
2192
    /// on the export and not implicitly add an import. This means though that
2193
    /// `c` has access to two copies of `a`, one imported and one exported. This
2194
    /// is not valid, especially in the face of resource types.
2195
    ///
2196
    /// Overall this method is tasked with rejecting the above world by walking
2197
    /// over all the exports and adding their dependencies. Each dependency is
2198
    /// recorded with whether it's required to be imported, and then if an
2199
    /// export is added for something that's required to be an error then the
2200
    /// operation fails.
2201
34.8k
    fn elaborate_world_exports(
2202
34.8k
        &self,
2203
34.8k
        export_interfaces: &IndexMap<InterfaceId, (WorldKey, &Stability)>,
2204
34.8k
        imports: &mut IndexMap<WorldKey, WorldItem>,
2205
34.8k
        exports: &mut IndexMap<WorldKey, WorldItem>,
2206
34.8k
    ) -> Result<()> {
2207
34.8k
        let mut required_imports = HashSet::new();
2208
34.8k
        for (id, (key, stability)) in export_interfaces.iter() {
2209
2.96k
            let name = self.name_world_key(&key);
2210
2.96k
            let ok = add_world_export(
2211
2.96k
                self,
2212
2.96k
                imports,
2213
2.96k
                exports,
2214
2.96k
                export_interfaces,
2215
2.96k
                &mut required_imports,
2216
2.96k
                *id,
2217
2.96k
                key,
2218
                true,
2219
2.96k
                stability,
2220
            );
2221
2.96k
            if !ok {
2222
0
                bail!(
2223
                    // FIXME: this is not a great error message and basically no
2224
                    // one will know what to do when it gets printed. Improving
2225
                    // this error message, however, is a chunk of work that may
2226
                    // not be best spent doing this at this time, so I'm writing
2227
                    // this comment instead.
2228
                    //
2229
                    // More-or-less what should happen here is that a "path"
2230
                    // from this interface to the conflicting interface should
2231
                    // be printed. It should be explained why an import is being
2232
                    // injected, why that's conflicting with an export, and
2233
                    // ideally with a suggestion of "add this interface to the
2234
                    // export list to fix this error".
2235
                    //
2236
                    // That's a lot of info that's not easy to get at without
2237
                    // more refactoring, so it's left to a future date in the
2238
                    // hopes that most folks won't actually run into this for
2239
                    // the time being.
2240
0
                    InvalidTransitiveDependency(name),
2241
                );
2242
2.96k
            }
2243
        }
2244
34.8k
        return Ok(());
2245
2246
3.56k
        fn add_world_export(
2247
3.56k
            resolve: &Resolve,
2248
3.56k
            imports: &mut IndexMap<WorldKey, WorldItem>,
2249
3.56k
            exports: &mut IndexMap<WorldKey, WorldItem>,
2250
3.56k
            export_interfaces: &IndexMap<InterfaceId, (WorldKey, &Stability)>,
2251
3.56k
            required_imports: &mut HashSet<InterfaceId>,
2252
3.56k
            id: InterfaceId,
2253
3.56k
            key: &WorldKey,
2254
3.56k
            add_export: bool,
2255
3.56k
            stability: &Stability,
2256
3.56k
        ) -> bool {
2257
3.56k
            if exports.contains_key(key) {
2258
26
                if add_export {
2259
26
                    return true;
2260
                } else {
2261
0
                    return false;
2262
                }
2263
3.53k
            }
2264
            // If this is an import and it's already in the `required_imports`
2265
            // set then we can skip it as we've already visited this interface.
2266
3.53k
            if !add_export && required_imports.contains(&id) {
2267
228
                return true;
2268
3.30k
            }
2269
3.30k
            let ok = resolve.interface_direct_deps(id).all(|dep| {
2270
596
                let key = WorldKey::Interface(dep);
2271
596
                let add_export = add_export && export_interfaces.contains_key(&dep);
2272
596
                add_world_export(
2273
596
                    resolve,
2274
596
                    imports,
2275
596
                    exports,
2276
596
                    export_interfaces,
2277
596
                    required_imports,
2278
596
                    dep,
2279
596
                    &key,
2280
596
                    add_export,
2281
596
                    stability,
2282
                )
2283
596
            });
2284
3.30k
            if !ok {
2285
0
                return false;
2286
3.30k
            }
2287
3.30k
            let item = WorldItem::Interface {
2288
3.30k
                id,
2289
3.30k
                stability: stability.clone(),
2290
3.30k
            };
2291
3.30k
            if add_export {
2292
2.96k
                if required_imports.contains(&id) {
2293
0
                    return false;
2294
2.96k
                }
2295
2.96k
                exports.insert(key.clone(), item);
2296
342
            } else {
2297
342
                required_imports.insert(id);
2298
342
                imports.insert(key.clone(), item);
2299
342
            }
2300
3.30k
            true
2301
3.56k
        }
2302
34.8k
    }
2303
2304
    /// Remove duplicate imports from a world if they import from the same
2305
    /// interface with semver-compatible versions.
2306
    ///
2307
    /// This will merge duplicate interfaces present at multiple versions in
2308
    /// both a world by selecting the larger version of the two interfaces. This
2309
    /// requires that the interfaces are indeed semver-compatible and it means
2310
    /// that some imports might be removed and replaced. Note that this is only
2311
    /// done within a single semver track, for example the world imports 0.2.0
2312
    /// and 0.2.1 then the result afterwards will be that it imports
2313
    /// 0.2.1. If, however, 0.3.0 where imported then the final result would
2314
    /// import both 0.2.0 and 0.3.0.
2315
4.70k
    pub fn merge_world_imports_based_on_semver(&mut self, world_id: WorldId) -> Result<()> {
2316
4.70k
        let world = &self.worlds[world_id];
2317
2318
        // The first pass here is to build a map of "semver tracks" where they
2319
        // key is per-interface and the value is the maximal version found in
2320
        // that semver-compatible-track plus the interface which is the maximal
2321
        // version.
2322
        //
2323
        // At the same time a `to_remove` set is maintained to remember what
2324
        // interfaces are being removed from `from` and `into`. All of
2325
        // `to_remove` are placed with a known other version.
2326
4.70k
        let mut semver_tracks = HashMap::new();
2327
4.70k
        let mut to_remove = HashSet::new();
2328
6.24k
        for (key, _) in world.imports.iter() {
2329
6.24k
            let iface_id = match key {
2330
422
                WorldKey::Interface(id) => *id,
2331
5.82k
                WorldKey::Name(_) => continue,
2332
            };
2333
422
            let (track, version) = match self.semver_track(iface_id) {
2334
332
                Some(track) => track,
2335
90
                None => continue,
2336
            };
2337
332
            log::debug!(
2338
0
                "{} is on track {}/{}",
2339
0
                self.id_of(iface_id).unwrap(),
2340
                track.0,
2341
                track.1,
2342
            );
2343
332
            match semver_tracks.entry(track.clone()) {
2344
332
                hash_map::Entry::Vacant(e) => {
2345
332
                    e.insert((version, iface_id));
2346
332
                }
2347
0
                hash_map::Entry::Occupied(mut e) => match version.cmp(&e.get().0) {
2348
0
                    Ordering::Greater => {
2349
0
                        to_remove.insert(e.get().1);
2350
0
                        e.insert((version, iface_id));
2351
0
                    }
2352
0
                    Ordering::Equal => {}
2353
0
                    Ordering::Less => {
2354
0
                        to_remove.insert(iface_id);
2355
0
                    }
2356
                },
2357
            }
2358
        }
2359
2360
        // Build a map of "this interface is replaced with this interface" using
2361
        // the results of the loop above.
2362
4.70k
        let mut replacements = HashMap::new();
2363
4.70k
        for id in to_remove {
2364
0
            let (track, _) = self.semver_track(id).unwrap();
2365
0
            let (_, latest) = semver_tracks[&track];
2366
0
            let prev = replacements.insert(id, latest);
2367
0
            assert!(prev.is_none());
2368
        }
2369
2370
        // Validate that `merge_world_item` succeeds for merging all removed
2371
        // interfaces with their replacement. This is a double-check that the
2372
        // semver version is actually correct and all items present in the old
2373
        // interface are in the new.
2374
4.70k
        for (to_replace, replace_with) in replacements.iter() {
2375
0
            self.merge_world_item(
2376
0
                &WorldItem::Interface {
2377
0
                    id: *to_replace,
2378
0
                    stability: Default::default(),
2379
0
                },
2380
0
                &WorldItem::Interface {
2381
0
                    id: *replace_with,
2382
0
                    stability: Default::default(),
2383
0
                },
2384
            )
2385
0
            .with_context(|| {
2386
0
                let old_name = self.id_of(*to_replace).unwrap();
2387
0
                let new_name = self.id_of(*replace_with).unwrap();
2388
0
                format!(
2389
0
                    "failed to upgrade `{old_name}` to `{new_name}`, was \
2390
0
                     this semver-compatible update not semver compatible?"
2391
                )
2392
0
            })?;
2393
        }
2394
2395
4.70k
        for (to_replace, replace_with) in replacements.iter() {
2396
0
            log::debug!(
2397
0
                "REPLACE {} => {}",
2398
0
                self.id_of(*to_replace).unwrap(),
2399
0
                self.id_of(*replace_with).unwrap(),
2400
            );
2401
        }
2402
2403
        // Finally perform the actual transformation of the imports/exports.
2404
        // Here all imports are removed if they're replaced and otherwise all
2405
        // imports have their dependencies updated, possibly transitively, to
2406
        // point to the new interfaces in `replacements`.
2407
        //
2408
        // Afterwards exports are additionally updated, but only their
2409
        // dependencies on imports which were remapped. Exports themselves are
2410
        // not deduplicated and/or removed.
2411
6.24k
        for (key, item) in mem::take(&mut self.worlds[world_id].imports) {
2412
6.24k
            if let WorldItem::Interface { id, .. } = item {
2413
819
                if replacements.contains_key(&id) {
2414
0
                    continue;
2415
819
                }
2416
5.42k
            }
2417
2418
6.24k
            self.update_interface_deps_of_world_item(&item, &replacements);
2419
2420
6.24k
            let prev = self.worlds[world_id].imports.insert(key, item);
2421
6.24k
            assert!(prev.is_none());
2422
        }
2423
4.70k
        for (key, item) in mem::take(&mut self.worlds[world_id].exports) {
2424
873
            self.update_interface_deps_of_world_item(&item, &replacements);
2425
873
            let prev = self.worlds[world_id].exports.insert(key, item);
2426
873
            assert!(prev.is_none());
2427
        }
2428
2429
        // Run through `elaborate_world` to reorder imports as appropriate and
2430
        // fill anything back in if it's actually required by exports. For now
2431
        // this doesn't tamper with exports at all. Also note that this is
2432
        // applied to all worlds in this `Resolve` because interfaces were
2433
        // modified directly.
2434
4.70k
        let ids = self.worlds.iter().map(|(id, _)| id).collect::<Vec<_>>();
2435
18.1k
        for world_id in ids {
2436
13.4k
            self.elaborate_world(world_id).with_context(|| {
2437
0
                let name = &self.worlds[world_id].name;
2438
0
                format!(
2439
0
                    "failed to elaborate world `{name}` after deduplicating imports \
2440
0
                     based on semver"
2441
                )
2442
0
            })?;
2443
        }
2444
2445
        #[cfg(debug_assertions)]
2446
        self.assert_valid();
2447
2448
4.70k
        Ok(())
2449
4.70k
    }
2450
2451
7.12k
    fn update_interface_deps_of_world_item(
2452
7.12k
        &mut self,
2453
7.12k
        item: &WorldItem,
2454
7.12k
        replacements: &HashMap<InterfaceId, InterfaceId>,
2455
7.12k
    ) {
2456
7.12k
        match *item {
2457
4.42k
            WorldItem::Type(t) => self.update_interface_dep_of_type(t, &replacements),
2458
1.30k
            WorldItem::Interface { id, .. } => {
2459
1.30k
                let types = self.interfaces[id]
2460
1.30k
                    .types
2461
1.30k
                    .values()
2462
1.30k
                    .copied()
2463
1.30k
                    .collect::<Vec<_>>();
2464
3.50k
                for ty in types {
2465
2.19k
                    self.update_interface_dep_of_type(ty, &replacements);
2466
2.19k
                }
2467
            }
2468
1.38k
            WorldItem::Function(_) => {}
2469
        }
2470
7.12k
    }
2471
2472
    /// Returns the "semver track" of an interface plus the interface's version.
2473
    ///
2474
    /// This function returns `None` if the interface `id` has a package without
2475
    /// a version. If the version is present, however, the first element of the
2476
    /// tuple returned is a "semver track" for the specific interface. The
2477
    /// version listed in `PackageName` will be modified so all
2478
    /// semver-compatible versions are listed the same way.
2479
    ///
2480
    /// The second element in the returned tuple is this interface's package's
2481
    /// version.
2482
422
    fn semver_track(&self, id: InterfaceId) -> Option<((PackageName, String), &Version)> {
2483
422
        let iface = &self.interfaces[id];
2484
422
        let pkg = &self.packages[iface.package?];
2485
422
        let version = pkg.name.version.as_ref()?;
2486
332
        let mut name = pkg.name.clone();
2487
332
        name.version = Some(PackageName::version_compat_track(version));
2488
332
        Some(((name, iface.name.clone()?), version))
2489
422
    }
2490
2491
    /// If `ty` is a definition where it's a `use` from another interface, then
2492
    /// change what interface it's using from according to the pairs in the
2493
    /// `replacements` map.
2494
6.62k
    fn update_interface_dep_of_type(
2495
6.62k
        &mut self,
2496
6.62k
        ty: TypeId,
2497
6.62k
        replacements: &HashMap<InterfaceId, InterfaceId>,
2498
6.62k
    ) {
2499
6.62k
        let to_replace = match self.type_interface_dep(ty) {
2500
858
            Some(id) => id,
2501
5.76k
            None => return,
2502
        };
2503
858
        let replace_with = match replacements.get(&to_replace) {
2504
0
            Some(id) => id,
2505
858
            None => return,
2506
        };
2507
0
        let dep = match self.types[ty].kind {
2508
0
            TypeDefKind::Type(Type::Id(id)) => id,
2509
0
            _ => return,
2510
        };
2511
0
        let name = self.types[dep].name.as_ref().unwrap();
2512
        // Note the infallible name indexing happening here. This should be
2513
        // previously validated with `merge_world_item` to succeed.
2514
0
        let replacement_id = self.interfaces[*replace_with].types[name];
2515
0
        self.types[ty].kind = TypeDefKind::Type(Type::Id(replacement_id));
2516
6.62k
    }
2517
2518
    /// Returns the core wasm module/field names for the specified `import`.
2519
    ///
2520
    /// This function will return the core wasm module/field that can be used to
2521
    /// use `import` with the name `mangling` scheme specified as well. This can
2522
    /// be useful for bindings generators, for example, and these names are
2523
    /// recognized by `wit-component` and `wasm-tools component new`.
2524
2.41k
    pub fn wasm_import_name(
2525
2.41k
        &self,
2526
2.41k
        mangling: ManglingAndAbi,
2527
2.41k
        import: WasmImport<'_>,
2528
2.41k
    ) -> (String, String) {
2529
2.41k
        match mangling {
2530
188
            ManglingAndAbi::Standard32 => match import {
2531
125
                WasmImport::Func { interface, func } => {
2532
125
                    let module = match interface {
2533
71
                        Some(key) => format!("cm32p2|{}", self.name_canonicalized_world_key(key)),
2534
54
                        None => format!("cm32p2"),
2535
                    };
2536
125
                    (module, func.name.clone())
2537
                }
2538
                WasmImport::ResourceIntrinsic {
2539
63
                    interface,
2540
63
                    resource,
2541
63
                    intrinsic,
2542
                } => {
2543
63
                    let name = self.types[resource].name.as_ref().unwrap();
2544
63
                    let (prefix, name) = match intrinsic {
2545
27
                        ResourceIntrinsic::ImportedDrop => ("", format!("{name}_drop")),
2546
12
                        ResourceIntrinsic::ExportedDrop => ("_ex_", format!("{name}_drop")),
2547
12
                        ResourceIntrinsic::ExportedNew => ("_ex_", format!("{name}_new")),
2548
12
                        ResourceIntrinsic::ExportedRep => ("_ex_", format!("{name}_rep")),
2549
                    };
2550
63
                    let module = match interface {
2551
47
                        Some(key) => {
2552
47
                            format!("cm32p2|{prefix}{}", self.name_canonicalized_world_key(key))
2553
                        }
2554
                        None => {
2555
16
                            assert_eq!(prefix, "");
2556
16
                            format!("cm32p2")
2557
                        }
2558
                    };
2559
63
                    (module, name)
2560
                }
2561
            },
2562
2.22k
            ManglingAndAbi::Legacy(abi) => match import {
2563
1.75k
                WasmImport::Func { interface, func } => {
2564
1.75k
                    let module = match interface {
2565
907
                        Some(key) => self.name_world_key(key),
2566
849
                        None => format!("$root"),
2567
                    };
2568
1.75k
                    (module, format!("{}{}", abi.import_prefix(), func.name))
2569
                }
2570
                WasmImport::ResourceIntrinsic {
2571
470
                    interface,
2572
470
                    resource,
2573
470
                    intrinsic,
2574
                } => {
2575
470
                    let name = self.types[resource].name.as_ref().unwrap();
2576
470
                    let (prefix, name) = match intrinsic {
2577
254
                        ResourceIntrinsic::ImportedDrop => ("", format!("[resource-drop]{name}")),
2578
                        ResourceIntrinsic::ExportedDrop => {
2579
72
                            ("[export]", format!("[resource-drop]{name}"))
2580
                        }
2581
                        ResourceIntrinsic::ExportedNew => {
2582
72
                            ("[export]", format!("[resource-new]{name}"))
2583
                        }
2584
                        ResourceIntrinsic::ExportedRep => {
2585
72
                            ("[export]", format!("[resource-rep]{name}"))
2586
                        }
2587
                    };
2588
470
                    let module = match interface {
2589
285
                        Some(key) => format!("{prefix}{}", self.name_world_key(key)),
2590
                        None => {
2591
185
                            assert_eq!(prefix, "");
2592
185
                            format!("$root")
2593
                        }
2594
                    };
2595
470
                    (module, format!("{}{name}", abi.import_prefix()))
2596
                }
2597
            },
2598
        }
2599
2.41k
    }
2600
2601
    /// Returns the core wasm export name for the specified `export`.
2602
    ///
2603
    /// This is the same as [`Resolve::wasm_import_name`], except for exports.
2604
14.5k
    pub fn wasm_export_name(&self, mangling: ManglingAndAbi, export: WasmExport<'_>) -> String {
2605
14.5k
        match mangling {
2606
888
            ManglingAndAbi::Standard32 => match export {
2607
                WasmExport::Func {
2608
246
                    interface,
2609
246
                    func,
2610
246
                    kind,
2611
                } => {
2612
246
                    let mut name = String::from("cm32p2|");
2613
246
                    if let Some(interface) = interface {
2614
188
                        let s = self.name_canonicalized_world_key(interface);
2615
188
                        name.push_str(&s);
2616
188
                    }
2617
246
                    name.push_str("|");
2618
246
                    name.push_str(&func.name);
2619
246
                    match kind {
2620
123
                        WasmExportKind::Normal => {}
2621
123
                        WasmExportKind::PostReturn => name.push_str("_post"),
2622
0
                        WasmExportKind::Callback => todo!(
2623
                            "not yet supported: \
2624
                             async callback functions using standard name mangling"
2625
                        ),
2626
                    }
2627
246
                    name
2628
                }
2629
                WasmExport::ResourceDtor {
2630
12
                    interface,
2631
12
                    resource,
2632
                } => {
2633
12
                    let name = self.types[resource].name.as_ref().unwrap();
2634
12
                    let interface = self.name_canonicalized_world_key(interface);
2635
12
                    format!("cm32p2|{interface}|{name}_dtor")
2636
                }
2637
210
                WasmExport::Memory => "cm32p2_memory".to_string(),
2638
210
                WasmExport::Initialize => "cm32p2_initialize".to_string(),
2639
210
                WasmExport::Realloc => "cm32p2_realloc".to_string(),
2640
            },
2641
13.6k
            ManglingAndAbi::Legacy(abi) => match export {
2642
                WasmExport::Func {
2643
1.98k
                    interface,
2644
1.98k
                    func,
2645
1.98k
                    kind,
2646
                } => {
2647
1.98k
                    let mut name = abi.export_prefix().to_string();
2648
1.98k
                    match kind {
2649
1.02k
                        WasmExportKind::Normal => {}
2650
813
                        WasmExportKind::PostReturn => name.push_str("cabi_post_"),
2651
                        WasmExportKind::Callback => {
2652
150
                            assert!(matches!(abi, LiftLowerAbi::AsyncCallback));
2653
150
                            name = format!("[callback]{name}")
2654
                        }
2655
                    }
2656
1.98k
                    if let Some(interface) = interface {
2657
1.39k
                        let s = self.name_world_key(interface);
2658
1.39k
                        name.push_str(&s);
2659
1.39k
                        name.push_str("#");
2660
1.39k
                    }
2661
1.98k
                    name.push_str(&func.name);
2662
1.98k
                    name
2663
                }
2664
                WasmExport::ResourceDtor {
2665
72
                    interface,
2666
72
                    resource,
2667
                } => {
2668
72
                    let name = self.types[resource].name.as_ref().unwrap();
2669
72
                    let interface = self.name_world_key(interface);
2670
72
                    format!("{}{interface}#[dtor]{name}", abi.export_prefix())
2671
                }
2672
3.86k
                WasmExport::Memory => "memory".to_string(),
2673
3.86k
                WasmExport::Initialize => "_initialize".to_string(),
2674
3.86k
                WasmExport::Realloc => "cabi_realloc".to_string(),
2675
            },
2676
        }
2677
14.5k
    }
2678
}
2679
2680
/// Possible imports that can be passed to [`Resolve::wasm_import_name`].
2681
#[derive(Debug)]
2682
pub enum WasmImport<'a> {
2683
    /// A WIT function is being imported. Optionally from an interface.
2684
    Func {
2685
        /// The name of the interface that the function is being imported from.
2686
        ///
2687
        /// If the function is imported directly from the world then this is
2688
        /// `Noen`.
2689
        interface: Option<&'a WorldKey>,
2690
2691
        /// The function being imported.
2692
        func: &'a Function,
2693
    },
2694
2695
    /// A resource-related intrinsic is being imported.
2696
    ResourceIntrinsic {
2697
        /// The optional interface to import from, same as `WasmImport::Func`.
2698
        interface: Option<&'a WorldKey>,
2699
2700
        /// The resource that's being operated on.
2701
        resource: TypeId,
2702
2703
        /// The intrinsic that's being imported.
2704
        intrinsic: ResourceIntrinsic,
2705
    },
2706
}
2707
2708
/// Intrinsic definitions to go with [`WasmImport::ResourceIntrinsic`] which
2709
/// also goes with [`Resolve::wasm_import_name`].
2710
#[derive(Debug)]
2711
pub enum ResourceIntrinsic {
2712
    ImportedDrop,
2713
    ExportedDrop,
2714
    ExportedNew,
2715
    ExportedRep,
2716
}
2717
2718
/// Indicates whether a function export is a normal export, a post-return
2719
/// function, or a callback function.
2720
#[derive(Debug)]
2721
pub enum WasmExportKind {
2722
    /// Normal function export.
2723
    Normal,
2724
2725
    /// Post-return function.
2726
    PostReturn,
2727
2728
    /// Async callback function.
2729
    Callback,
2730
}
2731
2732
/// Different kinds of exports that can be passed to
2733
/// [`Resolve::wasm_export_name`] to export from core wasm modules.
2734
#[derive(Debug)]
2735
pub enum WasmExport<'a> {
2736
    /// A WIT function is being exported, optionally from an interface.
2737
    Func {
2738
        /// An optional interface which owns `func`. Use `None` for top-level
2739
        /// world function.
2740
        interface: Option<&'a WorldKey>,
2741
2742
        /// The function being exported.
2743
        func: &'a Function,
2744
2745
        /// Kind of function (normal, post-return, or callback) being exported.
2746
        kind: WasmExportKind,
2747
    },
2748
2749
    /// A destructor for a resource exported from this module.
2750
    ResourceDtor {
2751
        /// The interface that owns the resource.
2752
        interface: &'a WorldKey,
2753
        /// The resource itself that the destructor is for.
2754
        resource: TypeId,
2755
    },
2756
2757
    /// Linear memory, the one that the canonical ABI uses.
2758
    Memory,
2759
2760
    /// An initialization function (not the core wasm `start`).
2761
    Initialize,
2762
2763
    /// The general-purpose realloc hook.
2764
    Realloc,
2765
}
2766
2767
/// Structure returned by [`Resolve::merge`] which contains mappings from
2768
/// old-ids to new-ids after the merge.
2769
#[derive(Default)]
2770
pub struct Remap {
2771
    pub types: Vec<Option<TypeId>>,
2772
    pub interfaces: Vec<Option<InterfaceId>>,
2773
    pub worlds: Vec<Option<WorldId>>,
2774
    pub packages: Vec<PackageId>,
2775
2776
    /// A cache of anonymous `own<T>` handles for resource types.
2777
    ///
2778
    /// The appending operation of `Remap` is the one responsible for
2779
    /// translating references to `T` where `T` is a resource into `own<T>`
2780
    /// instead. This map is used to deduplicate the `own<T>` types generated
2781
    /// to generate as few as possible.
2782
    ///
2783
    /// The key of this map is the resource id `T` in the new resolve, and
2784
    /// the value is the `own<T>` type pointing to `T`.
2785
    own_handles: HashMap<TypeId, TypeId>,
2786
2787
    type_has_borrow: Vec<Option<bool>>,
2788
}
2789
2790
435k
fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Option<Span>) -> Result<Id<T>> {
2791
435k
    match map.get(id.index()) {
2792
435k
        Some(Some(id)) => Ok(*id),
2793
        Some(None) => {
2794
0
            let msg = format!(
2795
0
                "found a reference to a {desc} which is excluded \
2796
0
                 due to its feature not being activated"
2797
            );
2798
0
            match span {
2799
0
                Some(span) => Err(Error::new(span, msg).into()),
2800
0
                None => bail!("{msg}"),
2801
            }
2802
        }
2803
0
        None => panic!("request to remap a {desc} that has not yet been registered"),
2804
    }
2805
435k
}
wit_parser::resolve::apply_map::<wit_parser::World>
Line
Count
Source
2790
80.0k
fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Option<Span>) -> Result<Id<T>> {
2791
80.0k
    match map.get(id.index()) {
2792
80.0k
        Some(Some(id)) => Ok(*id),
2793
        Some(None) => {
2794
0
            let msg = format!(
2795
0
                "found a reference to a {desc} which is excluded \
2796
0
                 due to its feature not being activated"
2797
            );
2798
0
            match span {
2799
0
                Some(span) => Err(Error::new(span, msg).into()),
2800
0
                None => bail!("{msg}"),
2801
            }
2802
        }
2803
0
        None => panic!("request to remap a {desc} that has not yet been registered"),
2804
    }
2805
80.0k
}
wit_parser::resolve::apply_map::<wit_parser::TypeDef>
Line
Count
Source
2790
298k
fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Option<Span>) -> Result<Id<T>> {
2791
298k
    match map.get(id.index()) {
2792
298k
        Some(Some(id)) => Ok(*id),
2793
        Some(None) => {
2794
0
            let msg = format!(
2795
0
                "found a reference to a {desc} which is excluded \
2796
0
                 due to its feature not being activated"
2797
            );
2798
0
            match span {
2799
0
                Some(span) => Err(Error::new(span, msg).into()),
2800
0
                None => bail!("{msg}"),
2801
            }
2802
        }
2803
0
        None => panic!("request to remap a {desc} that has not yet been registered"),
2804
    }
2805
298k
}
wit_parser::resolve::apply_map::<wit_parser::Interface>
Line
Count
Source
2790
56.7k
fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Option<Span>) -> Result<Id<T>> {
2791
56.7k
    match map.get(id.index()) {
2792
56.7k
        Some(Some(id)) => Ok(*id),
2793
        Some(None) => {
2794
0
            let msg = format!(
2795
0
                "found a reference to a {desc} which is excluded \
2796
0
                 due to its feature not being activated"
2797
            );
2798
0
            match span {
2799
0
                Some(span) => Err(Error::new(span, msg).into()),
2800
0
                None => bail!("{msg}"),
2801
            }
2802
        }
2803
0
        None => panic!("request to remap a {desc} that has not yet been registered"),
2804
    }
2805
56.7k
}
2806
2807
0
fn rename(original_name: &str, include_name: &IncludeName) -> Option<String> {
2808
0
    if original_name == include_name.name {
2809
0
        return Some(include_name.as_.to_string());
2810
0
    }
2811
0
    let (kind, rest) = original_name.split_once(']')?;
2812
0
    match rest.split_once('.') {
2813
0
        Some((name, rest)) if name == include_name.name => {
2814
0
            Some(format!("{kind}]{}.{rest}", include_name.as_))
2815
        }
2816
0
        _ if rest == include_name.name => Some(format!("{kind}]{}", include_name.as_)),
2817
0
        _ => None,
2818
    }
2819
0
}
2820
2821
impl Remap {
2822
298k
    pub fn map_type(&self, id: TypeId, span: Option<Span>) -> Result<TypeId> {
2823
298k
        apply_map(&self.types, id, "type", span)
2824
298k
    }
2825
2826
56.7k
    pub fn map_interface(&self, id: InterfaceId, span: Option<Span>) -> Result<InterfaceId> {
2827
56.7k
        apply_map(&self.interfaces, id, "interface", span)
2828
56.7k
    }
2829
2830
80.0k
    pub fn map_world(&self, id: WorldId, span: Option<Span>) -> Result<WorldId> {
2831
80.0k
        apply_map(&self.worlds, id, "world", span)
2832
80.0k
    }
2833
2834
13.1k
    fn append(
2835
13.1k
        &mut self,
2836
13.1k
        resolve: &mut Resolve,
2837
13.1k
        unresolved: UnresolvedPackage,
2838
13.1k
    ) -> Result<PackageId> {
2839
13.1k
        let pkgid = resolve.packages.alloc(Package {
2840
13.1k
            name: unresolved.name.clone(),
2841
13.1k
            docs: unresolved.docs.clone(),
2842
13.1k
            interfaces: Default::default(),
2843
13.1k
            worlds: Default::default(),
2844
13.1k
        });
2845
13.1k
        let prev = resolve.package_names.insert(unresolved.name.clone(), pkgid);
2846
13.1k
        if let Some(prev) = prev {
2847
0
            resolve.package_names.insert(unresolved.name.clone(), prev);
2848
0
            bail!(
2849
0
                "attempting to re-add package `{}` when it's already present in this `Resolve`",
2850
                unresolved.name,
2851
            );
2852
13.1k
        }
2853
2854
13.1k
        self.process_foreign_deps(resolve, pkgid, &unresolved)?;
2855
2856
13.1k
        let foreign_types = self.types.len();
2857
13.1k
        let foreign_interfaces = self.interfaces.len();
2858
13.1k
        let foreign_worlds = self.worlds.len();
2859
2860
        // Copy over all types first, updating any intra-type references. Note
2861
        // that types are sorted topologically which means this iteration
2862
        // order should be sufficient. Also note though that the interface
2863
        // owner of a type isn't updated here due to interfaces not being known
2864
        // yet.
2865
13.1k
        assert_eq!(unresolved.types.len(), unresolved.type_spans.len());
2866
141k
        for ((id, mut ty), span) in unresolved
2867
13.1k
            .types
2868
13.1k
            .into_iter()
2869
13.1k
            .zip(&unresolved.type_spans)
2870
13.1k
            .skip(foreign_types)
2871
        {
2872
141k
            if !resolve.include_type(&ty, pkgid, *span)? {
2873
0
                self.types.push(None);
2874
0
                continue;
2875
141k
            }
2876
2877
141k
            self.update_typedef(resolve, &mut ty, Some(*span))?;
2878
141k
            let new_id = resolve.types.alloc(ty);
2879
141k
            assert_eq!(self.types.len(), id.index());
2880
2881
141k
            let new_id = match resolve.types[new_id] {
2882
                // If this is an `own<T>` handle then either replace it with a
2883
                // preexisting `own<T>` handle which may have been generated in
2884
                // `update_ty`. If that doesn't exist though then insert it into
2885
                // the `own_handles` cache.
2886
                TypeDef {
2887
                    name: None,
2888
                    owner: TypeOwner::None,
2889
0
                    kind: TypeDefKind::Handle(Handle::Own(id)),
2890
                    docs: _,
2891
                    stability: _,
2892
0
                } => *self.own_handles.entry(id).or_insert(new_id),
2893
2894
                // Everything not-related to `own<T>` doesn't get its ID
2895
                // modified.
2896
141k
                _ => new_id,
2897
            };
2898
141k
            self.types.push(Some(new_id));
2899
        }
2900
2901
        // Next transfer all interfaces into `Resolve`, updating type ids
2902
        // referenced along the way.
2903
13.1k
        assert_eq!(
2904
13.1k
            unresolved.interfaces.len(),
2905
13.1k
            unresolved.interface_spans.len()
2906
        );
2907
54.6k
        for ((id, mut iface), span) in unresolved
2908
13.1k
            .interfaces
2909
13.1k
            .into_iter()
2910
13.1k
            .zip(&unresolved.interface_spans)
2911
13.1k
            .skip(foreign_interfaces)
2912
        {
2913
54.6k
            if !resolve
2914
54.6k
                .include_stability(&iface.stability, &pkgid, Some(span.span))
2915
54.6k
                .with_context(|| {
2916
0
                    format!(
2917
0
                        "failed to process feature gate for interface [{}] in package [{}]",
2918
0
                        iface
2919
0
                            .name
2920
0
                            .as_ref()
2921
0
                            .map(String::as_str)
2922
0
                            .unwrap_or("<unknown>"),
2923
0
                        resolve.packages[pkgid].name,
2924
                    )
2925
0
                })?
2926
            {
2927
0
                self.interfaces.push(None);
2928
0
                continue;
2929
54.6k
            }
2930
54.6k
            assert!(iface.package.is_none());
2931
54.6k
            iface.package = Some(pkgid);
2932
54.6k
            self.update_interface(resolve, &mut iface, Some(span))?;
2933
54.6k
            let new_id = resolve.interfaces.alloc(iface);
2934
54.6k
            assert_eq!(self.interfaces.len(), id.index());
2935
54.6k
            self.interfaces.push(Some(new_id));
2936
        }
2937
2938
        // Now that interfaces are identified go back through the types and
2939
        // update their interface owners.
2940
141k
        for (i, id) in self.types.iter().enumerate().skip(foreign_types) {
2941
141k
            let id = match id {
2942
141k
                Some(id) => *id,
2943
0
                None => continue,
2944
            };
2945
141k
            match &mut resolve.types[id].owner {
2946
31.5k
                TypeOwner::Interface(id) => {
2947
31.5k
                    let span = unresolved.type_spans[i];
2948
31.5k
                    *id = self.map_interface(*id, Some(span))
2949
31.5k
                        .with_context(|| {
2950
0
                            "this type is not gated by a feature but its interface is gated by a feature"
2951
0
                        })?;
2952
                }
2953
109k
                TypeOwner::World(_) | TypeOwner::None => {}
2954
            }
2955
        }
2956
2957
        // Expand worlds. Note that this does NOT process `include` statements,
2958
        // that's handled below. Instead this just handles world item updates
2959
        // and resolves references to types/items within `Resolve`.
2960
        //
2961
        // This is done after types/interfaces are fully settled so the
2962
        // transitive relation between interfaces, through types, is understood
2963
        // here.
2964
13.1k
        assert_eq!(unresolved.worlds.len(), unresolved.world_spans.len());
2965
17.4k
        for ((id, mut world), span) in unresolved
2966
13.1k
            .worlds
2967
13.1k
            .into_iter()
2968
13.1k
            .zip(&unresolved.world_spans)
2969
13.1k
            .skip(foreign_worlds)
2970
        {
2971
17.4k
            if !resolve
2972
17.4k
                .include_stability(&world.stability, &pkgid, Some(span.span))
2973
17.4k
                .with_context(|| {
2974
0
                    format!(
2975
0
                        "failed to process feature gate for world [{}] in package [{}]",
2976
0
                        world.name, resolve.packages[pkgid].name,
2977
                    )
2978
0
                })?
2979
            {
2980
0
                self.worlds.push(None);
2981
0
                continue;
2982
17.4k
            }
2983
17.4k
            self.update_world(&mut world, resolve, &pkgid, &span)?;
2984
2985
17.4k
            let new_id = resolve.worlds.alloc(world);
2986
17.4k
            assert_eq!(self.worlds.len(), id.index());
2987
17.4k
            self.worlds.push(Some(new_id));
2988
        }
2989
2990
        // As with interfaces, now update the ids of world-owned types.
2991
141k
        for (i, id) in self.types.iter().enumerate().skip(foreign_types) {
2992
141k
            let id = match id {
2993
141k
                Some(id) => *id,
2994
0
                None => continue,
2995
            };
2996
141k
            match &mut resolve.types[id].owner {
2997
19.6k
                TypeOwner::World(id) => {
2998
19.6k
                    let span = unresolved.type_spans[i];
2999
19.6k
                    *id = self.map_world(*id, Some(span))
3000
19.6k
                        .with_context(|| {
3001
0
                            "this type is not gated by a feature but its interface is gated by a feature"
3002
0
                        })?;
3003
                }
3004
121k
                TypeOwner::Interface(_) | TypeOwner::None => {}
3005
            }
3006
        }
3007
3008
        // After the above, process `include` statements for worlds and
3009
        // additionally fully elaborate them. Processing of `include` is
3010
        // deferred until after the steps above so the fully resolved state of
3011
        // local types in this package are all available. This is required
3012
        // because `include` may copy types between worlds when the type is
3013
        // defined in the world itself.
3014
        //
3015
        // This step, after processing `include`, will also use
3016
        // `elaborate_world` to fully expand the world in terms of
3017
        // imports/exports and ensure that all necessary imports/exports are all
3018
        // listed.
3019
        //
3020
        // Note that `self.worlds` is already sorted in topological order so if
3021
        // one world refers to another via `include` then it's guaranteed that
3022
        // the one we're referring to is already expanded and ready to be
3023
        // included.
3024
13.1k
        assert_eq!(self.worlds.len(), unresolved.world_spans.len());
3025
17.4k
        for (id, span) in self
3026
13.1k
            .worlds
3027
13.1k
            .iter()
3028
13.1k
            .zip(unresolved.world_spans.iter())
3029
13.1k
            .skip(foreign_worlds)
3030
        {
3031
17.4k
            let Some(id) = *id else {
3032
0
                continue;
3033
            };
3034
17.4k
            self.process_world_includes(id, resolve, &pkgid, &span)?;
3035
3036
17.4k
            resolve.elaborate_world(id).with_context(|| {
3037
0
                Error::new(
3038
0
                    span.span,
3039
0
                    format!(
3040
0
                        "failed to elaborate world imports/exports of `{}`",
3041
0
                        resolve.worlds[id].name
3042
                    ),
3043
                )
3044
0
            })?;
3045
        }
3046
3047
        // Fixup "parent" ids now that everything has been identified
3048
54.6k
        for id in self.interfaces.iter().skip(foreign_interfaces) {
3049
54.6k
            let id = match id {
3050
54.6k
                Some(id) => *id,
3051
0
                None => continue,
3052
            };
3053
54.6k
            let iface = &mut resolve.interfaces[id];
3054
54.6k
            iface.package = Some(pkgid);
3055
54.6k
            if let Some(name) = &iface.name {
3056
51.7k
                let prev = resolve.packages[pkgid].interfaces.insert(name.clone(), id);
3057
51.7k
                assert!(prev.is_none());
3058
2.94k
            }
3059
        }
3060
17.4k
        for id in self.worlds.iter().skip(foreign_worlds) {
3061
17.4k
            let id = match id {
3062
17.4k
                Some(id) => *id,
3063
0
                None => continue,
3064
            };
3065
17.4k
            let world = &mut resolve.worlds[id];
3066
17.4k
            world.package = Some(pkgid);
3067
17.4k
            let prev = resolve.packages[pkgid]
3068
17.4k
                .worlds
3069
17.4k
                .insert(world.name.clone(), id);
3070
17.4k
            assert!(prev.is_none());
3071
        }
3072
13.1k
        Ok(pkgid)
3073
13.1k
    }
3074
3075
13.1k
    fn process_foreign_deps(
3076
13.1k
        &mut self,
3077
13.1k
        resolve: &mut Resolve,
3078
13.1k
        pkgid: PackageId,
3079
13.1k
        unresolved: &UnresolvedPackage,
3080
13.1k
    ) -> Result<()> {
3081
        // Invert the `foreign_deps` map to be keyed by world id to get
3082
        // used in the loops below.
3083
13.1k
        let mut world_to_package = HashMap::new();
3084
13.1k
        let mut interface_to_package = HashMap::new();
3085
13.1k
        for (i, (pkg_name, worlds_or_ifaces)) in unresolved.foreign_deps.iter().enumerate() {
3086
4.04k
            for (name, item) in worlds_or_ifaces {
3087
2.17k
                match item {
3088
2.17k
                    AstItem::Interface(unresolved_interface_id) => {
3089
2.17k
                        let prev = interface_to_package.insert(
3090
2.17k
                            *unresolved_interface_id,
3091
2.17k
                            (pkg_name, name, unresolved.foreign_dep_spans[i]),
3092
                        );
3093
2.17k
                        assert!(prev.is_none());
3094
                    }
3095
0
                    AstItem::World(unresolved_world_id) => {
3096
0
                        let prev = world_to_package.insert(
3097
0
                            *unresolved_world_id,
3098
0
                            (pkg_name, name, unresolved.foreign_dep_spans[i]),
3099
                        );
3100
0
                        assert!(prev.is_none());
3101
                    }
3102
                }
3103
            }
3104
        }
3105
3106
        // Connect all interfaces referred to in `interface_to_package`, which
3107
        // are at the front of `unresolved.interfaces`, to interfaces already
3108
        // contained within `resolve`.
3109
13.1k
        self.process_foreign_interfaces(unresolved, &interface_to_package, resolve)?;
3110
3111
        // Connect all worlds referred to in `world_to_package`, which
3112
        // are at the front of `unresolved.worlds`, to worlds already
3113
        // contained within `resolve`.
3114
13.1k
        self.process_foreign_worlds(unresolved, &world_to_package, resolve)?;
3115
3116
        // Finally, iterate over all foreign-defined types and determine
3117
        // what they map to.
3118
13.1k
        self.process_foreign_types(unresolved, pkgid, resolve)?;
3119
3120
13.1k
        for (id, span) in unresolved.required_resource_types.iter() {
3121
            // Note that errors are ignored here because an error represents a
3122
            // type that has been configured away. If a type is configured away
3123
            // then any future use of it will generate an error so there's no
3124
            // need to validate that it's a resource here.
3125
16
            let Ok(mut id) = self.map_type(*id, Some(*span)) else {
3126
0
                continue;
3127
            };
3128
            loop {
3129
20
                match resolve.types[id].kind {
3130
4
                    TypeDefKind::Type(Type::Id(i)) => id = i,
3131
16
                    TypeDefKind::Resource => break,
3132
0
                    _ => bail!(Error::new(
3133
0
                        *span,
3134
0
                        format!("type used in a handle must be a resource"),
3135
0
                    )),
3136
                }
3137
            }
3138
        }
3139
3140
        #[cfg(debug_assertions)]
3141
        resolve.assert_valid();
3142
3143
13.1k
        Ok(())
3144
13.1k
    }
3145
3146
13.1k
    fn process_foreign_interfaces(
3147
13.1k
        &mut self,
3148
13.1k
        unresolved: &UnresolvedPackage,
3149
13.1k
        interface_to_package: &HashMap<InterfaceId, (&PackageName, &String, Span)>,
3150
13.1k
        resolve: &mut Resolve,
3151
13.1k
    ) -> Result<(), anyhow::Error> {
3152
13.8k
        for (unresolved_iface_id, unresolved_iface) in unresolved.interfaces.iter() {
3153
13.8k
            let (pkg_name, interface, span) = match interface_to_package.get(&unresolved_iface_id) {
3154
2.17k
                Some(items) => *items,
3155
                // All foreign interfaces are defined first, so the first one
3156
                // which is defined in a non-foreign document means that all
3157
                // further interfaces will be non-foreign as well.
3158
11.7k
                None => break,
3159
            };
3160
2.17k
            let pkgid = resolve
3161
2.17k
                .package_names
3162
2.17k
                .get(pkg_name)
3163
2.17k
                .copied()
3164
2.17k
                .ok_or_else(|| {
3165
0
                    PackageNotFoundError::new(
3166
0
                        span,
3167
0
                        pkg_name.clone(),
3168
0
                        resolve.package_names.keys().cloned().collect(),
3169
                    )
3170
0
                })?;
3171
3172
            // Functions can't be imported so this should be empty.
3173
2.17k
            assert!(unresolved_iface.functions.is_empty());
3174
3175
2.17k
            let pkg = &resolve.packages[pkgid];
3176
2.17k
            let span = &unresolved.interface_spans[unresolved_iface_id.index()];
3177
2.17k
            let iface_id = pkg
3178
2.17k
                .interfaces
3179
2.17k
                .get(interface)
3180
2.17k
                .copied()
3181
2.17k
                .ok_or_else(|| Error::new(span.span, "interface not found in package"))?;
3182
2.17k
            assert_eq!(self.interfaces.len(), unresolved_iface_id.index());
3183
2.17k
            self.interfaces.push(Some(iface_id));
3184
        }
3185
54.6k
        for (id, _) in unresolved.interfaces.iter().skip(self.interfaces.len()) {
3186
54.6k
            assert!(
3187
54.6k
                interface_to_package.get(&id).is_none(),
3188
0
                "found foreign interface after local interface"
3189
            );
3190
        }
3191
13.1k
        Ok(())
3192
13.1k
    }
3193
3194
13.1k
    fn process_foreign_worlds(
3195
13.1k
        &mut self,
3196
13.1k
        unresolved: &UnresolvedPackage,
3197
13.1k
        world_to_package: &HashMap<WorldId, (&PackageName, &String, Span)>,
3198
13.1k
        resolve: &mut Resolve,
3199
13.1k
    ) -> Result<(), anyhow::Error> {
3200
13.1k
        for (unresolved_world_id, _) in unresolved.worlds.iter() {
3201
9.71k
            let (pkg_name, world, span) = match world_to_package.get(&unresolved_world_id) {
3202
0
                Some(items) => *items,
3203
                // Same as above, all worlds are foreign until we find a
3204
                // non-foreign one.
3205
9.71k
                None => break,
3206
            };
3207
3208
0
            let pkgid = resolve
3209
0
                .package_names
3210
0
                .get(pkg_name)
3211
0
                .copied()
3212
0
                .ok_or_else(|| Error::new(span, "package not found"))?;
3213
0
            let pkg = &resolve.packages[pkgid];
3214
0
            let span = &unresolved.world_spans[unresolved_world_id.index()];
3215
0
            let world_id = pkg
3216
0
                .worlds
3217
0
                .get(world)
3218
0
                .copied()
3219
0
                .ok_or_else(|| Error::new(span.span, "world not found in package"))?;
3220
0
            assert_eq!(self.worlds.len(), unresolved_world_id.index());
3221
0
            self.worlds.push(Some(world_id));
3222
        }
3223
17.4k
        for (id, _) in unresolved.worlds.iter().skip(self.worlds.len()) {
3224
17.4k
            assert!(
3225
17.4k
                world_to_package.get(&id).is_none(),
3226
0
                "found foreign world after local world"
3227
            );
3228
        }
3229
13.1k
        Ok(())
3230
13.1k
    }
3231
3232
13.1k
    fn process_foreign_types(
3233
13.1k
        &mut self,
3234
13.1k
        unresolved: &UnresolvedPackage,
3235
13.1k
        pkgid: PackageId,
3236
13.1k
        resolve: &mut Resolve,
3237
13.1k
    ) -> Result<(), anyhow::Error> {
3238
10.5k
        for ((unresolved_type_id, unresolved_ty), span) in
3239
13.1k
            unresolved.types.iter().zip(&unresolved.type_spans)
3240
        {
3241
            // All "Unknown" types should appear first so once we're no longer
3242
            // in unknown territory it's package-defined types so break out of
3243
            // this loop.
3244
10.5k
            match unresolved_ty.kind {
3245
2.05k
                TypeDefKind::Unknown => {}
3246
8.49k
                _ => break,
3247
            }
3248
3249
2.05k
            if !resolve.include_type(unresolved_ty, pkgid, *span)? {
3250
0
                self.types.push(None);
3251
0
                continue;
3252
2.05k
            }
3253
3254
2.05k
            let unresolved_iface_id = match unresolved_ty.owner {
3255
2.05k
                TypeOwner::Interface(id) => id,
3256
0
                _ => unreachable!(),
3257
            };
3258
2.05k
            let iface_id = self.map_interface(unresolved_iface_id, None)?;
3259
2.05k
            let name = unresolved_ty.name.as_ref().unwrap();
3260
2.05k
            let span = unresolved.unknown_type_spans[unresolved_type_id.index()];
3261
2.05k
            let type_id = *resolve.interfaces[iface_id]
3262
2.05k
                .types
3263
2.05k
                .get(name)
3264
2.05k
                .ok_or_else(|| {
3265
0
                    Error::new(span, format!("type `{name}` not defined in interface"))
3266
0
                })?;
3267
2.05k
            assert_eq!(self.types.len(), unresolved_type_id.index());
3268
2.05k
            self.types.push(Some(type_id));
3269
        }
3270
141k
        for (_, ty) in unresolved.types.iter().skip(self.types.len()) {
3271
141k
            if let TypeDefKind::Unknown = ty.kind {
3272
0
                panic!("unknown type after defined type");
3273
141k
            }
3274
        }
3275
13.1k
        Ok(())
3276
13.1k
    }
3277
3278
198k
    fn update_typedef(
3279
198k
        &mut self,
3280
198k
        resolve: &mut Resolve,
3281
198k
        ty: &mut TypeDef,
3282
198k
        span: Option<Span>,
3283
198k
    ) -> Result<()> {
3284
        // NB: note that `ty.owner` is not updated here since interfaces
3285
        // haven't been mapped yet and that's done in a separate step.
3286
        use crate::TypeDefKind::*;
3287
6.19k
        match &mut ty.kind {
3288
2.22k
            Handle(handle) => match handle {
3289
1.74k
                crate::Handle::Own(ty) | crate::Handle::Borrow(ty) => {
3290
2.22k
                    self.update_type_id(ty, span)?
3291
                }
3292
            },
3293
3.88k
            Resource => {}
3294
5.83k
            Record(r) => {
3295
16.0k
                for field in r.fields.iter_mut() {
3296
16.0k
                    self.update_ty(resolve, &mut field.ty, span)
3297
16.0k
                        .with_context(|| format!("failed to update field `{}`", field.name))?;
3298
                }
3299
            }
3300
28.6k
            Tuple(t) => {
3301
107k
                for ty in t.types.iter_mut() {
3302
107k
                    self.update_ty(resolve, ty, span)?;
3303
                }
3304
            }
3305
7.79k
            Variant(v) => {
3306
26.9k
                for case in v.cases.iter_mut() {
3307
26.9k
                    if let Some(t) = &mut case.ty {
3308
22.7k
                        self.update_ty(resolve, t, span)?;
3309
4.22k
                    }
3310
                }
3311
            }
3312
30.5k
            Option(t) | List(t, ..) | FixedSizeList(t, ..) | Future(Some(t)) | Stream(Some(t)) => {
3313
56.1k
                self.update_ty(resolve, t, span)?
3314
            }
3315
39.1k
            Result(r) => {
3316
39.1k
                if let Some(ty) = &mut r.ok {
3317
35.2k
                    self.update_ty(resolve, ty, span)?;
3318
3.89k
                }
3319
39.1k
                if let Some(ty) = &mut r.err {
3320
32.9k
                    self.update_ty(resolve, ty, span)?;
3321
6.25k
                }
3322
            }
3323
3324
            // Note that `update_ty` is specifically not used here as typedefs
3325
            // because for the `type a = b` form that doesn't force `a` to be a
3326
            // handle type if `b` is a resource type, instead `a` is
3327
            // simultaneously usable as a resource and a handle type
3328
16.6k
            Type(crate::Type::Id(id)) => self.update_type_id(id, span)?,
3329
1.90k
            Type(_) => {}
3330
3331
            // nothing to do for these as they're just names or empty
3332
36.0k
            Flags(_) | Enum(_) | Future(None) | Stream(None) => {}
3333
3334
0
            Unknown => unreachable!(),
3335
        }
3336
3337
198k
        Ok(())
3338
198k
    }
3339
3340
376k
    fn update_ty(
3341
376k
        &mut self,
3342
376k
        resolve: &mut Resolve,
3343
376k
        ty: &mut Type,
3344
376k
        span: Option<Span>,
3345
376k
    ) -> Result<()> {
3346
376k
        let id = match ty {
3347
142k
            Type::Id(id) => id,
3348
233k
            _ => return Ok(()),
3349
        };
3350
142k
        self.update_type_id(id, span)?;
3351
3352
        // If `id` points to a `Resource` type then this means that what was
3353
        // just discovered was a reference to what will implicitly become an
3354
        // `own<T>` handle. This `own` handle is implicitly allocated here
3355
        // and handled during the merging process.
3356
142k
        let mut cur = *id;
3357
142k
        let points_to_resource = loop {
3358
143k
            match resolve.types[cur].kind {
3359
381
                TypeDefKind::Type(Type::Id(id)) => cur = id,
3360
1.35k
                TypeDefKind::Resource => break true,
3361
141k
                _ => break false,
3362
            }
3363
        };
3364
3365
142k
        if points_to_resource {
3366
1.35k
            *id = *self.own_handles.entry(*id).or_insert_with(|| {
3367
766
                resolve.types.alloc(TypeDef {
3368
766
                    name: None,
3369
766
                    owner: TypeOwner::None,
3370
766
                    kind: TypeDefKind::Handle(Handle::Own(*id)),
3371
766
                    docs: Default::default(),
3372
766
                    stability: Default::default(),
3373
766
                })
3374
766
            });
3375
141k
        }
3376
142k
        Ok(())
3377
376k
    }
3378
3379
206k
    fn update_type_id(&self, id: &mut TypeId, span: Option<Span>) -> Result<()> {
3380
206k
        *id = self.map_type(*id, span)?;
3381
206k
        Ok(())
3382
206k
    }
3383
3384
58.7k
    fn update_interface(
3385
58.7k
        &mut self,
3386
58.7k
        resolve: &mut Resolve,
3387
58.7k
        iface: &mut Interface,
3388
58.7k
        spans: Option<&InterfaceSpan>,
3389
58.7k
    ) -> Result<()> {
3390
58.7k
        iface.types.retain(|_, ty| self.types[ty.index()].is_some());
3391
58.7k
        let iface_pkg_id = iface.package.as_ref().unwrap_or_else(|| {
3392
0
            panic!(
3393
0
                "unexpectedly missing package on interface [{}]",
3394
0
                iface
3395
0
                    .name
3396
0
                    .as_ref()
3397
0
                    .map(String::as_str)
3398
0
                    .unwrap_or("<unknown>"),
3399
            )
3400
        });
3401
3402
        // NB: note that `iface.doc` is not updated here since interfaces
3403
        // haven't been mapped yet and that's done in a separate step.
3404
58.7k
        for (_name, ty) in iface.types.iter_mut() {
3405
38.0k
            self.update_type_id(ty, spans.map(|s| s.span))?;
3406
        }
3407
58.7k
        if let Some(spans) = spans {
3408
54.6k
            assert_eq!(iface.functions.len(), spans.funcs.len());
3409
4.03k
        }
3410
58.7k
        for (i, (func_name, func)) in iface.functions.iter_mut().enumerate() {
3411
24.8k
            let span = spans.map(|s| s.funcs[i]);
3412
24.8k
            if !resolve
3413
24.8k
                .include_stability(&func.stability, iface_pkg_id, span)
3414
24.8k
                .with_context(|| {
3415
0
                    format!(
3416
0
                        "failed to process feature gate for function [{func_name}] in package [{}]",
3417
0
                        resolve.packages[*iface_pkg_id].name,
3418
                    )
3419
0
                })?
3420
            {
3421
0
                continue;
3422
24.8k
            }
3423
24.8k
            self.update_function(resolve, func, span)
3424
24.8k
                .with_context(|| format!("failed to update function `{}`", func.name))?;
3425
        }
3426
3427
        // Filter out all of the existing functions in interface which fail the
3428
        // `include_stability()` check, as they shouldn't be available.
3429
58.7k
        for (name, func) in mem::take(&mut iface.functions) {
3430
24.8k
            if resolve.include_stability(&func.stability, iface_pkg_id, None)? {
3431
24.8k
                iface.functions.insert(name, func);
3432
24.8k
            }
3433
        }
3434
3435
58.7k
        Ok(())
3436
58.7k
    }
3437
3438
34.8k
    fn update_function(
3439
34.8k
        &mut self,
3440
34.8k
        resolve: &mut Resolve,
3441
34.8k
        func: &mut Function,
3442
34.8k
        span: Option<Span>,
3443
34.8k
    ) -> Result<()> {
3444
34.8k
        if let Some(id) = func.kind.resource_mut() {
3445
7.06k
            self.update_type_id(id, span)?;
3446
27.8k
        }
3447
80.9k
        for (_, ty) in func.params.iter_mut() {
3448
80.9k
            self.update_ty(resolve, ty, span)?;
3449
        }
3450
34.8k
        if let Some(ty) = &mut func.result {
3451
25.0k
            self.update_ty(resolve, ty, span)?;
3452
9.81k
        }
3453
3454
34.8k
        if let Some(ty) = &func.result {
3455
25.0k
            if self.type_has_borrow(resolve, ty) {
3456
0
                match span {
3457
0
                    Some(span) => {
3458
0
                        bail!(Error::new(
3459
0
                            span,
3460
0
                            format!(
3461
0
                                "function returns a type which contains \
3462
0
                                 a `borrow<T>` which is not supported"
3463
0
                            )
3464
0
                        ))
3465
                    }
3466
0
                    None => unreachable!(),
3467
                }
3468
25.0k
            }
3469
9.81k
        }
3470
3471
34.8k
        Ok(())
3472
34.8k
    }
3473
3474
17.4k
    fn update_world(
3475
17.4k
        &mut self,
3476
17.4k
        world: &mut World,
3477
17.4k
        resolve: &mut Resolve,
3478
17.4k
        pkg_id: &PackageId,
3479
17.4k
        spans: &WorldSpan,
3480
17.4k
    ) -> Result<()> {
3481
17.4k
        assert_eq!(world.imports.len(), spans.imports.len());
3482
17.4k
        assert_eq!(world.exports.len(), spans.exports.len());
3483
3484
        // Rewrite imports/exports with their updated versions. Note that this
3485
        // may involve updating the key of the imports/exports maps so this
3486
        // starts by emptying them out and then everything is re-inserted.
3487
17.4k
        let imports = mem::take(&mut world.imports).into_iter();
3488
25.8k
        let imports = imports.zip(&spans.imports).map(|p| (p, true));
3489
17.4k
        let exports = mem::take(&mut world.exports).into_iter();
3490
17.4k
        let exports = exports.zip(&spans.exports).map(|p| (p, false));
3491
28.6k
        for (((mut name, mut item), span), import) in imports.chain(exports) {
3492
            // Update the `id` eagerly here so `item.stability(..)` below
3493
            // works.
3494
28.6k
            if let WorldItem::Type(id) = &mut item {
3495
19.6k
                *id = self.map_type(*id, Some(*span))?;
3496
9.05k
            }
3497
28.6k
            let stability = item.stability(resolve);
3498
28.6k
            if !resolve
3499
28.6k
                .include_stability(stability, pkg_id, Some(*span))
3500
28.6k
                .with_context(|| format!("failed to process world item in `{}`", world.name))?
3501
            {
3502
0
                continue;
3503
28.6k
            }
3504
28.6k
            self.update_world_key(&mut name, Some(*span))?;
3505
28.6k
            match &mut item {
3506
4.06k
                WorldItem::Interface { id, .. } => {
3507
4.06k
                    *id = self.map_interface(*id, Some(*span))?;
3508
                }
3509
4.98k
                WorldItem::Function(f) => {
3510
4.98k
                    self.update_function(resolve, f, Some(*span))?;
3511
                }
3512
19.6k
                WorldItem::Type(_) => {
3513
19.6k
                    // already mapped above
3514
19.6k
                }
3515
            }
3516
3517
28.6k
            let dst = if import {
3518
25.8k
                &mut world.imports
3519
            } else {
3520
2.83k
                &mut world.exports
3521
            };
3522
28.6k
            let prev = dst.insert(name, item);
3523
28.6k
            assert!(prev.is_none());
3524
        }
3525
3526
17.4k
        Ok(())
3527
17.4k
    }
3528
3529
17.4k
    fn process_world_includes(
3530
17.4k
        &self,
3531
17.4k
        id: WorldId,
3532
17.4k
        resolve: &mut Resolve,
3533
17.4k
        pkg_id: &PackageId,
3534
17.4k
        spans: &WorldSpan,
3535
17.4k
    ) -> Result<()> {
3536
17.4k
        let world = &mut resolve.worlds[id];
3537
        // Resolve all `include` statements of the world which will add more
3538
        // entries to the imports/exports list for this world.
3539
17.4k
        assert_eq!(world.includes.len(), spans.includes.len());
3540
17.4k
        let includes = mem::take(&mut world.includes);
3541
17.4k
        let include_names = mem::take(&mut world.include_names);
3542
17.4k
        for (((stability, include_world), span), names) in includes
3543
17.4k
            .into_iter()
3544
17.4k
            .zip(&spans.includes)
3545
17.4k
            .zip(&include_names)
3546
        {
3547
0
            if !resolve
3548
0
                .include_stability(&stability, pkg_id, Some(*span))
3549
0
                .with_context(|| {
3550
0
                    format!(
3551
0
                        "failed to process feature gate for included world [{}] in package [{}]",
3552
0
                        resolve.worlds[include_world].name.as_str(),
3553
0
                        resolve.packages[*pkg_id].name
3554
                    )
3555
0
                })?
3556
            {
3557
0
                continue;
3558
0
            }
3559
0
            self.resolve_include(id, include_world, names, *span, pkg_id, resolve)?;
3560
        }
3561
3562
        // Validate that there are no case-insensitive duplicate names in imports/exports
3563
17.4k
        Self::validate_world_case_insensitive_names(resolve, id)?;
3564
3565
17.4k
        Ok(())
3566
17.4k
    }
3567
3568
    /// Validates that a world's imports and exports don't have case-insensitive
3569
    /// duplicate names. Per the WIT specification, kebab-case identifiers are
3570
    /// case-insensitive within the same scope.
3571
17.4k
    fn validate_world_case_insensitive_names(resolve: &Resolve, world_id: WorldId) -> Result<()> {
3572
17.4k
        let world = &resolve.worlds[world_id];
3573
3574
        // Helper closure to check for case-insensitive duplicates in a map
3575
17.4k
        let validate_names = |items: &IndexMap<WorldKey, WorldItem>,
3576
                              item_type: &str|
3577
34.9k
         -> Result<()> {
3578
34.9k
            let mut seen_lowercase: HashMap<String, String> = HashMap::new();
3579
3580
34.9k
            for key in items.keys() {
3581
                // Only WorldKey::Name variants can have case-insensitive conflicts
3582
28.6k
                if let WorldKey::Name(name) = key {
3583
27.5k
                    let lowercase_name = name.to_lowercase();
3584
3585
27.5k
                    if let Some(existing_name) = seen_lowercase.get(&lowercase_name) {
3586
                        // Only error on case-insensitive duplicates (e.g., "foo" vs "FOO").
3587
                        // Exact duplicates would have been caught earlier.
3588
0
                        if existing_name != name {
3589
0
                            bail!(
3590
0
                                "{item_type} `{name}` conflicts with {item_type} `{existing_name}` \
3591
0
                                (kebab-case identifiers are case-insensitive)"
3592
                            );
3593
0
                        }
3594
27.5k
                    }
3595
3596
27.5k
                    seen_lowercase.insert(lowercase_name, name.clone());
3597
1.12k
                }
3598
            }
3599
3600
34.9k
            Ok(())
3601
34.9k
        };
3602
3603
17.4k
        validate_names(&world.imports, "import")
3604
17.4k
            .with_context(|| format!("failed to validate imports in world `{}`", world.name))?;
3605
17.4k
        validate_names(&world.exports, "export")
3606
17.4k
            .with_context(|| format!("failed to validate exports in world `{}`", world.name))?;
3607
3608
17.4k
        Ok(())
3609
17.4k
    }
3610
3611
53.3k
    fn update_world_key(&self, key: &mut WorldKey, span: Option<Span>) -> Result<()> {
3612
53.3k
        match key {
3613
50.5k
            WorldKey::Name(_) => {}
3614
2.80k
            WorldKey::Interface(id) => {
3615
2.80k
                *id = self.map_interface(*id, span)?;
3616
            }
3617
        }
3618
53.3k
        Ok(())
3619
53.3k
    }
3620
3621
0
    fn resolve_include(
3622
0
        &self,
3623
0
        id: WorldId,
3624
0
        include_world_id_orig: WorldId,
3625
0
        names: &[IncludeName],
3626
0
        span: Span,
3627
0
        pkg_id: &PackageId,
3628
0
        resolve: &mut Resolve,
3629
0
    ) -> Result<()> {
3630
0
        let world = &resolve.worlds[id];
3631
0
        let include_world_id = self.map_world(include_world_id_orig, Some(span))?;
3632
0
        let include_world = resolve.worlds[include_world_id].clone();
3633
0
        let mut names_ = names.to_owned();
3634
0
        let is_external_include = world.package != include_world.package;
3635
3636
        // remove all imports and exports that match the names we're including
3637
0
        for import in include_world.imports.iter() {
3638
0
            self.remove_matching_name(import, &mut names_);
3639
0
        }
3640
0
        for export in include_world.exports.iter() {
3641
0
            self.remove_matching_name(export, &mut names_);
3642
0
        }
3643
0
        if !names_.is_empty() {
3644
0
            bail!(Error::new(
3645
0
                span,
3646
0
                format!(
3647
0
                    "no import or export kebab-name `{}`. Note that an ID does not support renaming",
3648
0
                    names_[0].name
3649
0
                ),
3650
0
            ));
3651
0
        }
3652
3653
0
        let mut cloner = clone::Cloner::new(
3654
0
            resolve,
3655
0
            TypeOwner::World(if is_external_include {
3656
0
                include_world_id
3657
            } else {
3658
0
                include_world_id
3659
                // include_world_id_orig
3660
            }),
3661
0
            TypeOwner::World(id),
3662
        );
3663
0
        cloner.new_package = Some(*pkg_id);
3664
3665
        // copy the imports and exports from the included world into the current world
3666
0
        for import in include_world.imports.iter() {
3667
0
            self.resolve_include_item(
3668
0
                &mut cloner,
3669
0
                names,
3670
0
                |resolve| &mut resolve.worlds[id].imports,
3671
0
                import,
3672
0
                span,
3673
0
                "import",
3674
0
                is_external_include,
3675
0
            )?;
3676
        }
3677
3678
0
        for export in include_world.exports.iter() {
3679
0
            self.resolve_include_item(
3680
0
                &mut cloner,
3681
0
                names,
3682
0
                |resolve| &mut resolve.worlds[id].exports,
3683
0
                export,
3684
0
                span,
3685
0
                "export",
3686
0
                is_external_include,
3687
0
            )?;
3688
        }
3689
0
        Ok(())
3690
0
    }
3691
3692
0
    fn resolve_include_item(
3693
0
        &self,
3694
0
        cloner: &mut clone::Cloner<'_>,
3695
0
        names: &[IncludeName],
3696
0
        get_items: impl Fn(&mut Resolve) -> &mut IndexMap<WorldKey, WorldItem>,
3697
0
        item: (&WorldKey, &WorldItem),
3698
0
        span: Span,
3699
0
        item_type: &str,
3700
0
        is_external_include: bool,
3701
0
    ) -> Result<()> {
3702
0
        match item.0 {
3703
0
            WorldKey::Name(n) => {
3704
0
                let n = names
3705
0
                    .into_iter()
3706
0
                    .find_map(|include_name| rename(n, include_name))
Unexecuted instantiation: <wit_parser::resolve::Remap>::resolve_include_item::<<wit_parser::resolve::Remap>::resolve_include::{closure#0}>::{closure#0}
Unexecuted instantiation: <wit_parser::resolve::Remap>::resolve_include_item::<<wit_parser::resolve::Remap>::resolve_include::{closure#1}>::{closure#0}
3707
0
                    .unwrap_or(n.clone());
3708
3709
                // When the `with` option to the `include` directive is
3710
                // specified and is used to rename a function that means that
3711
                // the function's own original name needs to be updated, so
3712
                // reflect the change not only in the world key but additionally
3713
                // in the function itself.
3714
0
                let mut new_item = item.1.clone();
3715
0
                let key = WorldKey::Name(n.clone());
3716
0
                cloner.world_item(&key, &mut new_item, &mut CloneMaps::default());
3717
0
                match &mut new_item {
3718
0
                    WorldItem::Function(f) => f.name = n.clone(),
3719
0
                    WorldItem::Type(id) => cloner.resolve.types[*id].name = Some(n.clone()),
3720
0
                    WorldItem::Interface { .. } => {}
3721
                }
3722
3723
0
                let prev = get_items(cloner.resolve).insert(key, new_item);
3724
0
                if prev.is_some() {
3725
0
                    bail!(Error::new(
3726
0
                        span,
3727
0
                        format!("{item_type} of `{n}` shadows previously {item_type}ed items"),
3728
0
                    ))
3729
0
                }
3730
            }
3731
0
            key @ WorldKey::Interface(_) => {
3732
0
                let prev = get_items(cloner.resolve)
3733
0
                    .entry(key.clone())
3734
0
                    .or_insert(item.1.clone());
3735
0
                match (&item.1, prev) {
3736
                    (
3737
                        WorldItem::Interface {
3738
0
                            id: aid,
3739
0
                            stability: astability,
3740
                        },
3741
                        WorldItem::Interface {
3742
0
                            id: bid,
3743
0
                            stability: bstability,
3744
                        },
3745
                    ) => {
3746
0
                        assert_eq!(*aid, *bid);
3747
0
                        merge_include_stability(astability, bstability, is_external_include)?;
3748
                    }
3749
0
                    (WorldItem::Interface { .. }, _) => unreachable!(),
3750
0
                    (WorldItem::Function(_), _) => unreachable!(),
3751
0
                    (WorldItem::Type(_), _) => unreachable!(),
3752
                }
3753
            }
3754
        };
3755
3756
0
        Ok(())
3757
0
    }
Unexecuted instantiation: <wit_parser::resolve::Remap>::resolve_include_item::<<wit_parser::resolve::Remap>::resolve_include::{closure#0}>
Unexecuted instantiation: <wit_parser::resolve::Remap>::resolve_include_item::<<wit_parser::resolve::Remap>::resolve_include::{closure#1}>
3758
3759
0
    fn remove_matching_name(&self, item: (&WorldKey, &WorldItem), names: &mut Vec<IncludeName>) {
3760
0
        match item.0 {
3761
0
            WorldKey::Name(n) => {
3762
0
                names.retain(|name| rename(n, name).is_none());
3763
            }
3764
0
            _ => {}
3765
        }
3766
0
    }
3767
3768
72.2k
    fn type_has_borrow(&mut self, resolve: &Resolve, ty: &Type) -> bool {
3769
72.2k
        let id = match ty {
3770
31.2k
            Type::Id(id) => *id,
3771
40.9k
            _ => return false,
3772
        };
3773
3774
31.2k
        if let Some(Some(has_borrow)) = self.type_has_borrow.get(id.index()) {
3775
2.18k
            return *has_borrow;
3776
29.0k
        }
3777
3778
29.0k
        let result = self.typedef_has_borrow(resolve, &resolve.types[id]);
3779
29.0k
        if self.type_has_borrow.len() <= id.index() {
3780
26.8k
            self.type_has_borrow.resize(id.index() + 1, None);
3781
26.8k
        }
3782
29.0k
        self.type_has_borrow[id.index()] = Some(result);
3783
29.0k
        result
3784
72.2k
    }
3785
3786
29.0k
    fn typedef_has_borrow(&mut self, resolve: &Resolve, ty: &TypeDef) -> bool {
3787
1.01k
        match &ty.kind {
3788
55
            TypeDefKind::Type(t) => self.type_has_borrow(resolve, t),
3789
38
            TypeDefKind::Variant(v) => v
3790
38
                .cases
3791
38
                .iter()
3792
144
                .filter_map(|case| case.ty.as_ref())
3793
87
                .any(|ty| self.type_has_borrow(resolve, ty)),
3794
0
            TypeDefKind::Handle(Handle::Borrow(_)) => true,
3795
1.01k
            TypeDefKind::Handle(Handle::Own(_)) => false,
3796
0
            TypeDefKind::Resource => false,
3797
45
            TypeDefKind::Record(r) => r
3798
45
                .fields
3799
45
                .iter()
3800
143
                .any(|case| self.type_has_borrow(resolve, &case.ty)),
3801
9
            TypeDefKind::Flags(_) => false,
3802
17.6k
            TypeDefKind::Tuple(t) => t.types.iter().any(|t| self.type_has_borrow(resolve, t)),
3803
84
            TypeDefKind::Enum(_) => false,
3804
1.60k
            TypeDefKind::List(ty)
3805
3.20k
            | TypeDefKind::FixedSizeList(ty, ..)
3806
705
            | TypeDefKind::Future(Some(ty))
3807
1.43k
            | TypeDefKind::Stream(Some(ty))
3808
13.4k
            | TypeDefKind::Option(ty) => self.type_has_borrow(resolve, ty),
3809
8.74k
            TypeDefKind::Result(r) => [&r.ok, &r.err]
3810
8.74k
                .iter()
3811
17.4k
                .filter_map(|t| t.as_ref())
3812
15.7k
                .any(|t| self.type_has_borrow(resolve, t)),
3813
71
            TypeDefKind::Future(None) | TypeDefKind::Stream(None) => false,
3814
0
            TypeDefKind::Unknown => unreachable!(),
3815
        }
3816
29.0k
    }
3817
}
3818
3819
struct MergeMap<'a> {
3820
    /// A map of package ids in `from` to those in `into` for those that are
3821
    /// found to be equivalent.
3822
    package_map: HashMap<PackageId, PackageId>,
3823
3824
    /// A map of interface ids in `from` to those in `into` for those that are
3825
    /// found to be equivalent.
3826
    interface_map: HashMap<InterfaceId, InterfaceId>,
3827
3828
    /// A map of type ids in `from` to those in `into` for those that are
3829
    /// found to be equivalent.
3830
    type_map: HashMap<TypeId, TypeId>,
3831
3832
    /// A map of world ids in `from` to those in `into` for those that are
3833
    /// found to be equivalent.
3834
    world_map: HashMap<WorldId, WorldId>,
3835
3836
    /// A list of documents that need to be added to packages in `into`.
3837
    ///
3838
    /// The elements here are:
3839
    ///
3840
    /// * The name of the interface/world
3841
    /// * The ID within `into` of the package being added to
3842
    /// * The ID within `from` of the item being added.
3843
    interfaces_to_add: Vec<(String, PackageId, InterfaceId)>,
3844
    worlds_to_add: Vec<(String, PackageId, WorldId)>,
3845
3846
    /// Which `Resolve` is being merged from.
3847
    from: &'a Resolve,
3848
3849
    /// Which `Resolve` is being merged into.
3850
    into: &'a Resolve,
3851
}
3852
3853
impl<'a> MergeMap<'a> {
3854
12.3k
    fn new(from: &'a Resolve, into: &'a Resolve) -> MergeMap<'a> {
3855
12.3k
        MergeMap {
3856
12.3k
            package_map: Default::default(),
3857
12.3k
            interface_map: Default::default(),
3858
12.3k
            type_map: Default::default(),
3859
12.3k
            world_map: Default::default(),
3860
12.3k
            interfaces_to_add: Default::default(),
3861
12.3k
            worlds_to_add: Default::default(),
3862
12.3k
            from,
3863
12.3k
            into,
3864
12.3k
        }
3865
12.3k
    }
3866
3867
12.3k
    fn build(&mut self) -> Result<()> {
3868
16.8k
        for from_id in self.from.topological_packages() {
3869
16.8k
            let from = &self.from.packages[from_id];
3870
16.8k
            let into_id = match self.into.package_names.get(&from.name) {
3871
105
                Some(id) => *id,
3872
3873
                // This package, according to its name and url, is not present
3874
                // in `self` so it needs to get added below.
3875
                None => {
3876
16.7k
                    log::trace!("adding unique package {}", from.name);
3877
16.7k
                    continue;
3878
                }
3879
            };
3880
105
            log::trace!("merging duplicate package {}", from.name);
3881
3882
105
            self.build_package(from_id, into_id).with_context(|| {
3883
0
                format!("failed to merge package `{}` into existing copy", from.name)
3884
0
            })?;
3885
        }
3886
3887
12.3k
        Ok(())
3888
12.3k
    }
3889
3890
105
    fn build_package(&mut self, from_id: PackageId, into_id: PackageId) -> Result<()> {
3891
105
        let prev = self.package_map.insert(from_id, into_id);
3892
105
        assert!(prev.is_none());
3893
3894
105
        let from = &self.from.packages[from_id];
3895
105
        let into = &self.into.packages[into_id];
3896
3897
        // If an interface is present in `from_id` but not present in `into_id`
3898
        // then it can be copied over wholesale. That copy is scheduled to
3899
        // happen within the `self.interfaces_to_add` list.
3900
105
        for (name, from_interface_id) in from.interfaces.iter() {
3901
14
            let into_interface_id = match into.interfaces.get(name) {
3902
6
                Some(id) => *id,
3903
                None => {
3904
8
                    log::trace!("adding unique interface {name}");
3905
8
                    self.interfaces_to_add
3906
8
                        .push((name.clone(), into_id, *from_interface_id));
3907
8
                    continue;
3908
                }
3909
            };
3910
3911
6
            log::trace!("merging duplicate interfaces {name}");
3912
6
            self.build_interface(*from_interface_id, into_interface_id)
3913
6
                .with_context(|| format!("failed to merge interface `{name}`"))?;
3914
        }
3915
3916
105
        for (name, from_world_id) in from.worlds.iter() {
3917
103
            let into_world_id = match into.worlds.get(name) {
3918
0
                Some(id) => *id,
3919
                None => {
3920
103
                    log::trace!("adding unique world {name}");
3921
103
                    self.worlds_to_add
3922
103
                        .push((name.clone(), into_id, *from_world_id));
3923
103
                    continue;
3924
                }
3925
            };
3926
3927
0
            log::trace!("merging duplicate worlds {name}");
3928
0
            self.build_world(*from_world_id, into_world_id)
3929
0
                .with_context(|| format!("failed to merge world `{name}`"))?;
3930
        }
3931
3932
105
        Ok(())
3933
105
    }
3934
3935
8
    fn build_interface(&mut self, from_id: InterfaceId, into_id: InterfaceId) -> Result<()> {
3936
8
        let prev = self.interface_map.insert(from_id, into_id);
3937
8
        assert!(prev.is_none());
3938
3939
8
        let from_interface = &self.from.interfaces[from_id];
3940
8
        let into_interface = &self.into.interfaces[into_id];
3941
3942
        // Unlike documents/interfaces above if an interface in `from`
3943
        // differs from the interface in `into` then that's considered an
3944
        // error. Changing interfaces can reflect changes in imports/exports
3945
        // which may not be expected so it's currently required that all
3946
        // interfaces, when merged, exactly match.
3947
        //
3948
        // One case to consider here, for example, is that if a world in
3949
        // `into` exports the interface `into_id` then if `from_id` were to
3950
        // add more items into `into` then it would unexpectedly require more
3951
        // items to be exported which may not work. In an import context this
3952
        // might work since it's "just more items available for import", but
3953
        // for now a conservative route of "interfaces must match" is taken.
3954
3955
11
        for (name, from_type_id) in from_interface.types.iter() {
3956
11
            let into_type_id = *into_interface
3957
11
                .types
3958
11
                .get(name)
3959
11
                .ok_or_else(|| anyhow!("expected type `{name}` to be present"))?;
3960
10
            let prev = self.type_map.insert(*from_type_id, into_type_id);
3961
10
            assert!(prev.is_none());
3962
3963
10
            self.build_type_id(*from_type_id, into_type_id)
3964
10
                .with_context(|| format!("mismatch in type `{name}`"))?;
3965
        }
3966
3967
15
        for (name, from_func) in from_interface.functions.iter() {
3968
15
            let into_func = match into_interface.functions.get(name) {
3969
15
                Some(func) => func,
3970
0
                None => bail!("expected function `{name}` to be present"),
3971
            };
3972
15
            self.build_function(from_func, into_func)
3973
15
                .with_context(|| format!("mismatch in function `{name}`"))?;
3974
        }
3975
3976
7
        Ok(())
3977
8
    }
3978
3979
87
    fn build_type_id(&mut self, from_id: TypeId, into_id: TypeId) -> Result<()> {
3980
        // FIXME: ideally the types should be "structurally
3981
        // equal" but that's not trivial to do in the face of
3982
        // resources.
3983
87
        let _ = from_id;
3984
87
        let _ = into_id;
3985
87
        Ok(())
3986
87
    }
3987
3988
40
    fn build_type(&mut self, from_ty: &Type, into_ty: &Type) -> Result<()> {
3989
40
        match (from_ty, into_ty) {
3990
16
            (Type::Id(from), Type::Id(into)) => {
3991
16
                self.build_type_id(*from, *into)?;
3992
            }
3993
24
            (from, into) if from != into => bail!("different kinds of types"),
3994
24
            _ => {}
3995
        }
3996
40
        Ok(())
3997
40
    }
3998
3999
17
    fn build_function(&mut self, from_func: &Function, into_func: &Function) -> Result<()> {
4000
17
        if from_func.name != into_func.name {
4001
0
            bail!(
4002
0
                "different function names `{}` and `{}`",
4003
                from_func.name,
4004
                into_func.name
4005
            );
4006
17
        }
4007
17
        match (&from_func.kind, &into_func.kind) {
4008
4
            (FunctionKind::Freestanding, FunctionKind::Freestanding) => {}
4009
1
            (FunctionKind::AsyncFreestanding, FunctionKind::AsyncFreestanding) => {}
4010
4011
0
            (FunctionKind::Method(from), FunctionKind::Method(into))
4012
0
            | (FunctionKind::Static(from), FunctionKind::Static(into))
4013
7
            | (FunctionKind::AsyncMethod(from), FunctionKind::AsyncMethod(into))
4014
3
            | (FunctionKind::AsyncStatic(from), FunctionKind::AsyncStatic(into))
4015
2
            | (FunctionKind::Constructor(from), FunctionKind::Constructor(into)) => {
4016
12
                self.build_type_id(*from, *into)
4017
12
                    .context("different function kind types")?;
4018
            }
4019
4020
            (FunctionKind::Method(_), _)
4021
            | (FunctionKind::Constructor(_), _)
4022
            | (FunctionKind::Static(_), _)
4023
            | (FunctionKind::Freestanding, _)
4024
            | (FunctionKind::AsyncFreestanding, _)
4025
            | (FunctionKind::AsyncMethod(_), _)
4026
            | (FunctionKind::AsyncStatic(_), _) => {
4027
0
                bail!("different function kind types")
4028
            }
4029
        }
4030
4031
17
        if from_func.params.len() != into_func.params.len() {
4032
0
            bail!("different number of function parameters");
4033
17
        }
4034
27
        for ((from_name, from_ty), (into_name, into_ty)) in
4035
17
            from_func.params.iter().zip(&into_func.params)
4036
        {
4037
27
            if from_name != into_name {
4038
0
                bail!("different function parameter names: {from_name} != {into_name}");
4039
27
            }
4040
27
            self.build_type(from_ty, into_ty)
4041
27
                .with_context(|| format!("different function parameter types for `{from_name}`"))?;
4042
        }
4043
17
        match (&from_func.result, &into_func.result) {
4044
13
            (Some(from_ty), Some(into_ty)) => {
4045
13
                self.build_type(from_ty, into_ty)
4046
13
                    .context("different function result types")?;
4047
            }
4048
4
            (None, None) => {}
4049
0
            (Some(_), None) | (None, Some(_)) => bail!("different number of function results"),
4050
        }
4051
17
        Ok(())
4052
17
    }
4053
4054
0
    fn build_world(&mut self, from_id: WorldId, into_id: WorldId) -> Result<()> {
4055
0
        let prev = self.world_map.insert(from_id, into_id);
4056
0
        assert!(prev.is_none());
4057
4058
0
        let from_world = &self.from.worlds[from_id];
4059
0
        let into_world = &self.into.worlds[into_id];
4060
4061
        // Same as interfaces worlds are expected to exactly match to avoid
4062
        // unexpectedly changing a particular component's view of imports and
4063
        // exports.
4064
        //
4065
        // FIXME: this should probably share functionality with
4066
        // `Resolve::merge_worlds` to support adding imports but not changing
4067
        // exports.
4068
4069
0
        if from_world.imports.len() != into_world.imports.len() {
4070
0
            bail!("world contains different number of imports than expected");
4071
0
        }
4072
0
        if from_world.exports.len() != into_world.exports.len() {
4073
0
            bail!("world contains different number of exports than expected");
4074
0
        }
4075
4076
0
        for (from_name, from) in from_world.imports.iter() {
4077
0
            let into_name = MergeMap::map_name(from_name, &self.interface_map);
4078
0
            let name_str = self.from.name_world_key(from_name);
4079
0
            let into = into_world
4080
0
                .imports
4081
0
                .get(&into_name)
4082
0
                .ok_or_else(|| anyhow!("import `{name_str}` not found in target world"))?;
4083
0
            self.match_world_item(from, into)
4084
0
                .with_context(|| format!("import `{name_str}` didn't match target world"))?;
4085
        }
4086
4087
0
        for (from_name, from) in from_world.exports.iter() {
4088
0
            let into_name = MergeMap::map_name(from_name, &self.interface_map);
4089
0
            let name_str = self.from.name_world_key(from_name);
4090
0
            let into = into_world
4091
0
                .exports
4092
0
                .get(&into_name)
4093
0
                .ok_or_else(|| anyhow!("export `{name_str}` not found in target world"))?;
4094
0
            self.match_world_item(from, into)
4095
0
                .with_context(|| format!("export `{name_str}` didn't match target world"))?;
4096
        }
4097
4098
0
        Ok(())
4099
0
    }
4100
4101
0
    fn map_name(
4102
0
        from_name: &WorldKey,
4103
0
        interface_map: &HashMap<InterfaceId, InterfaceId>,
4104
0
    ) -> WorldKey {
4105
0
        match from_name {
4106
0
            WorldKey::Name(s) => WorldKey::Name(s.clone()),
4107
0
            WorldKey::Interface(id) => {
4108
0
                WorldKey::Interface(interface_map.get(id).copied().unwrap_or(*id))
4109
            }
4110
        }
4111
0
    }
4112
4113
0
    fn match_world_item(&mut self, from: &WorldItem, into: &WorldItem) -> Result<()> {
4114
0
        match (from, into) {
4115
0
            (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
4116
                match (
4117
0
                    &self.from.interfaces[*from].name,
4118
0
                    &self.into.interfaces[*into].name,
4119
                ) {
4120
                    // If one interface is unnamed then they must both be
4121
                    // unnamed and they must both have the same structure for
4122
                    // now.
4123
0
                    (None, None) => self.build_interface(*from, *into)?,
4124
4125
                    // Otherwise both interfaces must be named and they must
4126
                    // have been previously found to be equivalent. Note that
4127
                    // if either is unnamed it won't be present in
4128
                    // `interface_map` so this'll return an error.
4129
                    _ => {
4130
0
                        if self.interface_map.get(&from) != Some(&into) {
4131
0
                            bail!("interfaces are not the same");
4132
0
                        }
4133
                    }
4134
                }
4135
            }
4136
0
            (WorldItem::Function(from), WorldItem::Function(into)) => {
4137
0
                let _ = (from, into);
4138
0
                // FIXME: should assert an check that `from` structurally
4139
0
                // matches `into`
4140
0
            }
4141
0
            (WorldItem::Type(from), WorldItem::Type(into)) => {
4142
                // FIXME: should assert an check that `from` structurally
4143
                // matches `into`
4144
0
                let prev = self.type_map.insert(*from, *into);
4145
0
                assert!(prev.is_none());
4146
            }
4147
4148
            (WorldItem::Interface { .. }, _)
4149
            | (WorldItem::Function(_), _)
4150
            | (WorldItem::Type(_), _) => {
4151
0
                bail!("world items do not have the same type")
4152
            }
4153
        }
4154
0
        Ok(())
4155
0
    }
4156
}
4157
4158
/// Updates stability annotations when merging `from` into `into`.
4159
///
4160
/// This is done to keep up-to-date stability information if possible.
4161
/// Components for example don't carry stability information but WIT does so
4162
/// this tries to move from "unknown" to stable/unstable if possible.
4163
16
fn update_stability(from: &Stability, into: &mut Stability) -> Result<()> {
4164
    // If `from` is unknown or the two stability annotations are equal then
4165
    // there's nothing to do here.
4166
16
    if from == into || from.is_unknown() {
4167
16
        return Ok(());
4168
0
    }
4169
    // Otherwise if `into` is unknown then inherit the stability listed in
4170
    // `from`.
4171
0
    if into.is_unknown() {
4172
0
        *into = from.clone();
4173
0
        return Ok(());
4174
0
    }
4175
4176
    // Failing all that this means that the two attributes are different so
4177
    // generate an error.
4178
0
    bail!("mismatch in stability from '{:?}' to '{:?}'", from, into)
4179
16
}
4180
4181
0
fn merge_include_stability(
4182
0
    from: &Stability,
4183
0
    into: &mut Stability,
4184
0
    is_external_include: bool,
4185
0
) -> Result<()> {
4186
0
    if is_external_include && from.is_stable() {
4187
0
        log::trace!("dropped stability from external package");
4188
0
        *into = Stability::Unknown;
4189
0
        return Ok(());
4190
0
    }
4191
4192
0
    return update_stability(from, into);
4193
0
}
4194
4195
/// An error that can be returned during "world elaboration" during various
4196
/// [`Resolve`] operations.
4197
///
4198
/// Methods on [`Resolve`] which mutate its internals, such as
4199
/// [`Resolve::push_dir`] or [`Resolve::importize`] can fail if `world` imports
4200
/// in WIT packages are invalid. This error indicates one of these situations
4201
/// where an invalid dependency graph between imports and exports are detected.
4202
///
4203
/// Note that at this time this error is subtle and not easy to understand, and
4204
/// work needs to be done to explain this better and additionally provide a
4205
/// better error message. For now though this type enables callers to test for
4206
/// the exact kind of error emitted.
4207
#[derive(Debug, Clone)]
4208
pub struct InvalidTransitiveDependency(String);
4209
4210
impl fmt::Display for InvalidTransitiveDependency {
4211
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4212
0
        write!(
4213
0
            f,
4214
0
            "interface `{}` transitively depends on an interface in \
4215
0
             incompatible ways",
4216
            self.0
4217
        )
4218
0
    }
4219
}
4220
4221
impl std::error::Error for InvalidTransitiveDependency {}
4222
4223
#[cfg(test)]
4224
mod tests {
4225
    use crate::Resolve;
4226
    use anyhow::Result;
4227
4228
    #[test]
4229
    fn select_world() -> Result<()> {
4230
        let mut resolve = Resolve::default();
4231
        resolve.push_str(
4232
            "test.wit",
4233
            r#"
4234
                package foo:bar@0.1.0;
4235
4236
                world foo {}
4237
            "#,
4238
        )?;
4239
        resolve.push_str(
4240
            "test.wit",
4241
            r#"
4242
                package foo:baz@0.1.0;
4243
4244
                world foo {}
4245
            "#,
4246
        )?;
4247
        resolve.push_str(
4248
            "test.wit",
4249
            r#"
4250
                package foo:baz@0.2.0;
4251
4252
                world foo {}
4253
            "#,
4254
        )?;
4255
4256
        let dummy = resolve.push_str(
4257
            "test.wit",
4258
            r#"
4259
                package foo:dummy;
4260
4261
                world foo {}
4262
            "#,
4263
        )?;
4264
4265
        assert!(resolve.select_world(&[dummy], None).is_ok());
4266
        assert!(resolve.select_world(&[dummy], Some("xx")).is_err());
4267
        assert!(resolve.select_world(&[dummy], Some("")).is_err());
4268
        assert!(resolve.select_world(&[dummy], Some("foo:bar/foo")).is_ok());
4269
        assert!(
4270
            resolve
4271
                .select_world(&[dummy], Some("foo:bar/foo@0.1.0"))
4272
                .is_ok()
4273
        );
4274
        assert!(resolve.select_world(&[dummy], Some("foo:baz/foo")).is_err());
4275
        assert!(
4276
            resolve
4277
                .select_world(&[dummy], Some("foo:baz/foo@0.1.0"))
4278
                .is_ok()
4279
        );
4280
        assert!(
4281
            resolve
4282
                .select_world(&[dummy], Some("foo:baz/foo@0.2.0"))
4283
                .is_ok()
4284
        );
4285
        Ok(())
4286
    }
4287
4288
    /// When there are multiple packages and there's no main package, don't
4289
    /// pick a world just based on it being the only one that matches.
4290
    #[test]
4291
    fn select_world_multiple_packages() -> Result<()> {
4292
        use wit_parser::Resolve;
4293
4294
        let mut resolve = Resolve::default();
4295
4296
        // Just one world in one package; we always succeed.
4297
        let stuff = resolve.push_str(
4298
            "./my-test.wit",
4299
            r#"
4300
                    package test:stuff;
4301
4302
                    world foo {
4303
                        // ...
4304
                    }
4305
                "#,
4306
        )?;
4307
        assert!(resolve.select_world(&[stuff], None).is_ok());
4308
        assert!(resolve.select_world(&[stuff], Some("foo")).is_ok());
4309
4310
        // Multiple packages, but still just one total world. Lookups
4311
        // without a main package now fail.
4312
        let empty = resolve.push_str(
4313
            "./my-test.wit",
4314
            r#"
4315
                    package test:empty;
4316
                "#,
4317
        )?;
4318
        assert!(resolve.select_world(&[stuff, empty], None).is_err());
4319
        assert!(resolve.select_world(&[stuff, empty], Some("foo")).is_err());
4320
        assert!(resolve.select_world(&[empty], None).is_err());
4321
        assert!(resolve.select_world(&[empty], Some("foo")).is_err());
4322
4323
        Ok(())
4324
    }
4325
4326
    /// Test selecting a world with multiple versions of a package name.
4327
    #[test]
4328
    fn select_world_versions() -> Result<()> {
4329
        use wit_parser::Resolve;
4330
4331
        let mut resolve = Resolve::default();
4332
4333
        let _id = resolve.push_str(
4334
            "./my-test.wit",
4335
            r#"
4336
                    package example:distraction;
4337
                "#,
4338
        )?;
4339
4340
        // When selecting with a version it's ok to drop the version when
4341
        // there's only a single copy of that package in `Resolve`.
4342
        let versions_1 = resolve.push_str(
4343
            "./my-test.wit",
4344
            r#"
4345
                    package example:versions@1.0.0;
4346
4347
                    world foo { /* ... */ }
4348
                "#,
4349
        )?;
4350
        assert!(resolve.select_world(&[versions_1], Some("foo")).is_ok());
4351
        assert!(
4352
            resolve
4353
                .select_world(&[versions_1], Some("foo@1.0.0"))
4354
                .is_err()
4355
        );
4356
        assert!(
4357
            resolve
4358
                .select_world(&[versions_1], Some("example:versions/foo"))
4359
                .is_ok()
4360
        );
4361
        assert!(
4362
            resolve
4363
                .select_world(&[versions_1], Some("example:versions/foo@1.0.0"))
4364
                .is_ok()
4365
        );
4366
4367
        // However when a single package has multiple versions in a resolve
4368
        // it's required to specify the version to select which one.
4369
        let versions_2 = resolve.push_str(
4370
            "./my-test.wit",
4371
            r#"
4372
                    package example:versions@2.0.0;
4373
4374
                    world foo { /* ... */ }
4375
                "#,
4376
        )?;
4377
        assert!(
4378
            resolve
4379
                .select_world(&[versions_1, versions_2], Some("foo"))
4380
                .is_err()
4381
        );
4382
        assert!(
4383
            resolve
4384
                .select_world(&[versions_1, versions_2], Some("foo@1.0.0"))
4385
                .is_err()
4386
        );
4387
        assert!(
4388
            resolve
4389
                .select_world(&[versions_1, versions_2], Some("foo@2.0.0"))
4390
                .is_err()
4391
        );
4392
        assert!(
4393
            resolve
4394
                .select_world(&[versions_1, versions_2], Some("example:versions/foo"))
4395
                .is_err()
4396
        );
4397
        assert!(
4398
            resolve
4399
                .select_world(
4400
                    &[versions_1, versions_2],
4401
                    Some("example:versions/foo@1.0.0")
4402
                )
4403
                .is_ok()
4404
        );
4405
        assert!(
4406
            resolve
4407
                .select_world(
4408
                    &[versions_1, versions_2],
4409
                    Some("example:versions/foo@2.0.0")
4410
                )
4411
                .is_ok()
4412
        );
4413
4414
        Ok(())
4415
    }
4416
4417
    /// Test overriding a main package using name qualification
4418
    #[test]
4419
    fn select_world_override_qualification() -> Result<()> {
4420
        use wit_parser::Resolve;
4421
4422
        let mut resolve = Resolve::default();
4423
4424
        let other = resolve.push_str(
4425
            "./my-test.wit",
4426
            r#"
4427
                    package example:other;
4428
4429
                    world foo { }
4430
                "#,
4431
        )?;
4432
4433
        // A fully-qualified name overrides a main package.
4434
        let fq = resolve.push_str(
4435
            "./my-test.wit",
4436
            r#"
4437
                    package example:fq;
4438
4439
                    world bar { }
4440
                "#,
4441
        )?;
4442
        assert!(resolve.select_world(&[other, fq], Some("foo")).is_err());
4443
        assert!(resolve.select_world(&[other, fq], Some("bar")).is_err());
4444
        assert!(
4445
            resolve
4446
                .select_world(&[other, fq], Some("example:other/foo"))
4447
                .is_ok()
4448
        );
4449
        assert!(
4450
            resolve
4451
                .select_world(&[other, fq], Some("example:fq/bar"))
4452
                .is_ok()
4453
        );
4454
        assert!(
4455
            resolve
4456
                .select_world(&[other, fq], Some("example:other/bar"))
4457
                .is_err()
4458
        );
4459
        assert!(
4460
            resolve
4461
                .select_world(&[other, fq], Some("example:fq/foo"))
4462
                .is_err()
4463
        );
4464
4465
        Ok(())
4466
    }
4467
4468
    /// Test selecting with fully-qualified world names.
4469
    #[test]
4470
    fn select_world_fully_qualified() -> Result<()> {
4471
        use wit_parser::Resolve;
4472
4473
        let mut resolve = Resolve::default();
4474
4475
        let distraction = resolve.push_str(
4476
            "./my-test.wit",
4477
            r#"
4478
                    package example:distraction;
4479
                "#,
4480
        )?;
4481
4482
        // If a package has multiple worlds, then we can't guess the world
4483
        // even if we know the package.
4484
        let multiworld = resolve.push_str(
4485
            "./my-test.wit",
4486
            r#"
4487
                    package example:multiworld;
4488
4489
                    world foo { /* ... */ }
4490
4491
                    world bar { /* ... */ }
4492
                "#,
4493
        )?;
4494
        assert!(
4495
            resolve
4496
                .select_world(&[distraction, multiworld], None)
4497
                .is_err()
4498
        );
4499
        assert!(
4500
            resolve
4501
                .select_world(&[distraction, multiworld], Some("foo"))
4502
                .is_err()
4503
        );
4504
        assert!(
4505
            resolve
4506
                .select_world(&[distraction, multiworld], Some("example:multiworld/foo"))
4507
                .is_ok()
4508
        );
4509
        assert!(
4510
            resolve
4511
                .select_world(&[distraction, multiworld], Some("bar"))
4512
                .is_err()
4513
        );
4514
        assert!(
4515
            resolve
4516
                .select_world(&[distraction, multiworld], Some("example:multiworld/bar"))
4517
                .is_ok()
4518
        );
4519
4520
        Ok(())
4521
    }
4522
4523
    /// Test `select_world` with single and multiple packages.
4524
    #[test]
4525
    fn select_world_packages() -> Result<()> {
4526
        use wit_parser::Resolve;
4527
4528
        let mut resolve = Resolve::default();
4529
4530
        // If there's a single package and only one world, that world is
4531
        // the obvious choice.
4532
        let wit1 = resolve.push_str(
4533
            "./my-test.wit",
4534
            r#"
4535
                    package example:wit1;
4536
4537
                    world foo {
4538
                        // ...
4539
                    }
4540
                "#,
4541
        )?;
4542
        assert!(resolve.select_world(&[wit1], None).is_ok());
4543
        assert!(resolve.select_world(&[wit1], Some("foo")).is_ok());
4544
        assert!(
4545
            resolve
4546
                .select_world(&[wit1], Some("example:wit1/foo"))
4547
                .is_ok()
4548
        );
4549
        assert!(resolve.select_world(&[wit1], Some("bar")).is_err());
4550
        assert!(
4551
            resolve
4552
                .select_world(&[wit1], Some("example:wit2/foo"))
4553
                .is_err()
4554
        );
4555
4556
        // If there are multiple packages, we need to be told which package
4557
        // to use.
4558
        let wit2 = resolve.push_str(
4559
            "./my-test.wit",
4560
            r#"
4561
                    package example:wit2;
4562
4563
                    world foo { /* ... */ }
4564
                "#,
4565
        )?;
4566
        assert!(resolve.select_world(&[wit1, wit2], None).is_err());
4567
        assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
4568
        assert!(
4569
            resolve
4570
                .select_world(&[wit1, wit2], Some("example:wit1/foo"))
4571
                .is_ok()
4572
        );
4573
        assert!(resolve.select_world(&[wit2], None).is_ok());
4574
        assert!(resolve.select_world(&[wit2], Some("foo")).is_ok());
4575
        assert!(
4576
            resolve
4577
                .select_world(&[wit2], Some("example:wit1/foo"))
4578
                .is_ok()
4579
        );
4580
        assert!(resolve.select_world(&[wit1, wit2], Some("bar")).is_err());
4581
        assert!(
4582
            resolve
4583
                .select_world(&[wit1, wit2], Some("example:wit2/foo"))
4584
                .is_ok()
4585
        );
4586
        assert!(resolve.select_world(&[wit2], Some("bar")).is_err());
4587
        assert!(
4588
            resolve
4589
                .select_world(&[wit2], Some("example:wit2/foo"))
4590
                .is_ok()
4591
        );
4592
4593
        Ok(())
4594
    }
4595
}