wit_parser/
resolve.rs

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