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) | TypeDefKind::FixedSizeList(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
1935        // Sort the imports by "class" to ensure that this matches the order
1936        // that items are printed and that items are in topological order.
1937        //
1938        // When printing worlds in WIT:
1939        //
1940        // * interfaces come first
1941        // * types are next
1942        //   * type imports are first
1943        //   * type definitions are next
1944        //   * resource definitions have methods printed inline
1945        // * freestanding functions are last
1946        //
1947        // This reflects the topological order between items where types
1948        // can refer to imports and functions can refer to these types. Ordering
1949        // within a single class (e.g. imports depending on each other, types
1950        // referring to each other) is already preserved by other passes in this
1951        // file and general AST resolution. That means that a stable sort here
1952        // can be used to ensure that each class is in the right location
1953        // relative to the others.
1954        //
1955        // Overall this ensures that round-trips of WIT through wasm should
1956        // always produce the same result.
1957        let sort_key = |resolve: &Resolve, item: &WorldItem| match item {
1958            WorldItem::Interface { .. } => 0,
1959            WorldItem::Type(ty) => {
1960                let ty = &resolve.types[*ty];
1961                match ty.kind {
1962                    TypeDefKind::Type(Type::Id(t)) if resolve.types[t].owner != ty.owner => 1,
1963                    _ => 2,
1964                }
1965            }
1966            WorldItem::Function(f) => {
1967                if f.kind.resource().is_none() {
1968                    3
1969                } else {
1970                    4
1971                }
1972            }
1973        };
1974
1975        // Sort world items when we start to elaborate the world to start with a
1976        // topological view of items.
1977        let mut world_imports = world.imports.iter().collect::<Vec<_>>();
1978        world_imports.sort_by_key(|(_name, import)| sort_key(self, import));
1979        for (name, item) in world_imports {
1980            match item {
1981                // Interfaces get their dependencies added first followed by the
1982                // interface itself.
1983                WorldItem::Interface { id, stability } => {
1984                    self.elaborate_world_import(&mut new_imports, name.clone(), *id, &stability);
1985                }
1986
1987                // Functions are added as-is since their dependence on types in
1988                // the world should already be satisfied.
1989                WorldItem::Function(_) => {
1990                    let prev = new_imports.insert(name.clone(), item.clone());
1991                    assert!(prev.is_none());
1992                }
1993
1994                // Types may depend on an interface, in which case a (possibly)
1995                // recursive addition of that interface happens here. Afterwards
1996                // the type itself can be added safely.
1997                WorldItem::Type(id) => {
1998                    if let Some(dep) = self.type_interface_dep(*id) {
1999                        self.elaborate_world_import(
2000                            &mut new_imports,
2001                            WorldKey::Interface(dep),
2002                            dep,
2003                            &self.types[*id].stability,
2004                        );
2005                    }
2006                    let prev = new_imports.insert(name.clone(), item.clone());
2007                    assert!(prev.is_none());
2008                }
2009            }
2010        }
2011
2012        // Exports are trickier than imports, notably to uphold the invariant
2013        // required by `elaborate_world_exports`. To do this the exports are
2014        // partitioned into interfaces/functions. All functions are added to
2015        // the new exports list during this loop but interfaces are all deferred
2016        // to be handled in the `elaborate_world_exports` function.
2017        let mut new_exports = IndexMap::new();
2018        let mut export_interfaces = IndexMap::new();
2019        for (name, item) in world.exports.iter() {
2020            match item {
2021                WorldItem::Interface { id, stability } => {
2022                    let prev = export_interfaces.insert(*id, (name.clone(), stability));
2023                    assert!(prev.is_none());
2024                }
2025                WorldItem::Function(_) => {
2026                    let prev = new_exports.insert(name.clone(), item.clone());
2027                    assert!(prev.is_none());
2028                }
2029                WorldItem::Type(_) => unreachable!(),
2030            }
2031        }
2032
2033        self.elaborate_world_exports(&export_interfaces, &mut new_imports, &mut new_exports)?;
2034
2035        // In addition to sorting at the start of elaboration also sort here at
2036        // the end of elaboration to handle types being interspersed with
2037        // interfaces as they're found.
2038        new_imports.sort_by_cached_key(|_name, import| sort_key(self, import));
2039
2040        // And with all that done the world is updated in-place with
2041        // imports/exports.
2042        log::trace!("imports = {:?}", new_imports);
2043        log::trace!("exports = {:?}", new_exports);
2044        let world = &mut self.worlds[world_id];
2045        world.imports = new_imports;
2046        world.exports = new_exports;
2047
2048        Ok(())
2049    }
2050
2051    fn elaborate_world_import(
2052        &self,
2053        imports: &mut IndexMap<WorldKey, WorldItem>,
2054        key: WorldKey,
2055        id: InterfaceId,
2056        stability: &Stability,
2057    ) {
2058        if imports.contains_key(&key) {
2059            return;
2060        }
2061        for dep in self.interface_direct_deps(id) {
2062            self.elaborate_world_import(imports, WorldKey::Interface(dep), dep, stability);
2063        }
2064        let prev = imports.insert(
2065            key,
2066            WorldItem::Interface {
2067                id,
2068                stability: stability.clone(),
2069            },
2070        );
2071        assert!(prev.is_none());
2072    }
2073
2074    /// This function adds all of the interfaces in `export_interfaces` to the
2075    /// list of exports of the `world` specified.
2076    ///
2077    /// This method is more involved than adding imports because it is fallible.
2078    /// Chiefly what can happen is that the dependencies of all exports must be
2079    /// satisfied by other exports or imports, but not both. For example given a
2080    /// situation such as:
2081    ///
2082    /// ```wit
2083    /// interface a {
2084    ///     type t = u32
2085    /// }
2086    /// interface b {
2087    ///     use a.{t}
2088    /// }
2089    /// interface c {
2090    ///     use a.{t}
2091    ///     use b.{t as t2}
2092    /// }
2093    /// ```
2094    ///
2095    /// where `c` depends on `b` and `a` where `b` depends on `a`, then the
2096    /// purpose of this method is to reject this world:
2097    ///
2098    /// ```wit
2099    /// world foo {
2100    ///     export a
2101    ///     export c
2102    /// }
2103    /// ```
2104    ///
2105    /// The reasoning here is unfortunately subtle and is additionally the
2106    /// subject of WebAssembly/component-model#208. Effectively the `c`
2107    /// interface depends on `b`, but it's not listed explicitly as an import,
2108    /// so it's then implicitly added as an import. This then transitively
2109    /// depends on `a` so it's also added as an import. At this point though `c`
2110    /// also depends on `a`, and it's also exported, so naively it should depend
2111    /// on the export and not implicitly add an import. This means though that
2112    /// `c` has access to two copies of `a`, one imported and one exported. This
2113    /// is not valid, especially in the face of resource types.
2114    ///
2115    /// Overall this method is tasked with rejecting the above world by walking
2116    /// over all the exports and adding their dependencies. Each dependency is
2117    /// recorded with whether it's required to be imported, and then if an
2118    /// export is added for something that's required to be an error then the
2119    /// operation fails.
2120    fn elaborate_world_exports(
2121        &self,
2122        export_interfaces: &IndexMap<InterfaceId, (WorldKey, &Stability)>,
2123        imports: &mut IndexMap<WorldKey, WorldItem>,
2124        exports: &mut IndexMap<WorldKey, WorldItem>,
2125    ) -> Result<()> {
2126        let mut required_imports = HashSet::new();
2127        for (id, (key, stability)) in export_interfaces.iter() {
2128            let name = self.name_world_key(&key);
2129            let ok = add_world_export(
2130                self,
2131                imports,
2132                exports,
2133                export_interfaces,
2134                &mut required_imports,
2135                *id,
2136                key,
2137                true,
2138                stability,
2139            );
2140            if !ok {
2141                bail!(
2142                    // FIXME: this is not a great error message and basically no
2143                    // one will know what to do when it gets printed. Improving
2144                    // this error message, however, is a chunk of work that may
2145                    // not be best spent doing this at this time, so I'm writing
2146                    // this comment instead.
2147                    //
2148                    // More-or-less what should happen here is that a "path"
2149                    // from this interface to the conflicting interface should
2150                    // be printed. It should be explained why an import is being
2151                    // injected, why that's conflicting with an export, and
2152                    // ideally with a suggestion of "add this interface to the
2153                    // export list to fix this error".
2154                    //
2155                    // That's a lot of info that's not easy to get at without
2156                    // more refactoring, so it's left to a future date in the
2157                    // hopes that most folks won't actually run into this for
2158                    // the time being.
2159                    InvalidTransitiveDependency(name),
2160                );
2161            }
2162        }
2163        return Ok(());
2164
2165        fn add_world_export(
2166            resolve: &Resolve,
2167            imports: &mut IndexMap<WorldKey, WorldItem>,
2168            exports: &mut IndexMap<WorldKey, WorldItem>,
2169            export_interfaces: &IndexMap<InterfaceId, (WorldKey, &Stability)>,
2170            required_imports: &mut HashSet<InterfaceId>,
2171            id: InterfaceId,
2172            key: &WorldKey,
2173            add_export: bool,
2174            stability: &Stability,
2175        ) -> bool {
2176            if exports.contains_key(key) {
2177                if add_export {
2178                    return true;
2179                } else {
2180                    return false;
2181                }
2182            }
2183            // If this is an import and it's already in the `required_imports`
2184            // set then we can skip it as we've already visited this interface.
2185            if !add_export && required_imports.contains(&id) {
2186                return true;
2187            }
2188            let ok = resolve.interface_direct_deps(id).all(|dep| {
2189                let key = WorldKey::Interface(dep);
2190                let add_export = add_export && export_interfaces.contains_key(&dep);
2191                add_world_export(
2192                    resolve,
2193                    imports,
2194                    exports,
2195                    export_interfaces,
2196                    required_imports,
2197                    dep,
2198                    &key,
2199                    add_export,
2200                    stability,
2201                )
2202            });
2203            if !ok {
2204                return false;
2205            }
2206            let item = WorldItem::Interface {
2207                id,
2208                stability: stability.clone(),
2209            };
2210            if add_export {
2211                if required_imports.contains(&id) {
2212                    return false;
2213                }
2214                exports.insert(key.clone(), item);
2215            } else {
2216                required_imports.insert(id);
2217                imports.insert(key.clone(), item);
2218            }
2219            true
2220        }
2221    }
2222
2223    /// Remove duplicate imports from a world if they import from the same
2224    /// interface with semver-compatible versions.
2225    ///
2226    /// This will merge duplicate interfaces present at multiple versions in
2227    /// both a world by selecting the larger version of the two interfaces. This
2228    /// requires that the interfaces are indeed semver-compatible and it means
2229    /// that some imports might be removed and replaced. Note that this is only
2230    /// done within a single semver track, for example the world imports 0.2.0
2231    /// and 0.2.1 then the result afterwards will be that it imports
2232    /// 0.2.1. If, however, 0.3.0 where imported then the final result would
2233    /// import both 0.2.0 and 0.3.0.
2234    pub fn merge_world_imports_based_on_semver(&mut self, world_id: WorldId) -> Result<()> {
2235        let world = &self.worlds[world_id];
2236
2237        // The first pass here is to build a map of "semver tracks" where they
2238        // key is per-interface and the value is the maximal version found in
2239        // that semver-compatible-track plus the interface which is the maximal
2240        // version.
2241        //
2242        // At the same time a `to_remove` set is maintained to remember what
2243        // interfaces are being removed from `from` and `into`. All of
2244        // `to_remove` are placed with a known other version.
2245        let mut semver_tracks = HashMap::new();
2246        let mut to_remove = HashSet::new();
2247        for (key, _) in world.imports.iter() {
2248            let iface_id = match key {
2249                WorldKey::Interface(id) => *id,
2250                WorldKey::Name(_) => continue,
2251            };
2252            let (track, version) = match self.semver_track(iface_id) {
2253                Some(track) => track,
2254                None => continue,
2255            };
2256            log::debug!(
2257                "{} is on track {}/{}",
2258                self.id_of(iface_id).unwrap(),
2259                track.0,
2260                track.1,
2261            );
2262            match semver_tracks.entry(track.clone()) {
2263                hash_map::Entry::Vacant(e) => {
2264                    e.insert((version, iface_id));
2265                }
2266                hash_map::Entry::Occupied(mut e) => match version.cmp(&e.get().0) {
2267                    Ordering::Greater => {
2268                        to_remove.insert(e.get().1);
2269                        e.insert((version, iface_id));
2270                    }
2271                    Ordering::Equal => {}
2272                    Ordering::Less => {
2273                        to_remove.insert(iface_id);
2274                    }
2275                },
2276            }
2277        }
2278
2279        // Build a map of "this interface is replaced with this interface" using
2280        // the results of the loop above.
2281        let mut replacements = HashMap::new();
2282        for id in to_remove {
2283            let (track, _) = self.semver_track(id).unwrap();
2284            let (_, latest) = semver_tracks[&track];
2285            let prev = replacements.insert(id, latest);
2286            assert!(prev.is_none());
2287        }
2288
2289        // Validate that `merge_world_item` succeeds for merging all removed
2290        // interfaces with their replacement. This is a double-check that the
2291        // semver version is actually correct and all items present in the old
2292        // interface are in the new.
2293        for (to_replace, replace_with) in replacements.iter() {
2294            self.merge_world_item(
2295                &WorldItem::Interface {
2296                    id: *to_replace,
2297                    stability: Default::default(),
2298                },
2299                &WorldItem::Interface {
2300                    id: *replace_with,
2301                    stability: Default::default(),
2302                },
2303            )
2304            .with_context(|| {
2305                let old_name = self.id_of(*to_replace).unwrap();
2306                let new_name = self.id_of(*replace_with).unwrap();
2307                format!(
2308                    "failed to upgrade `{old_name}` to `{new_name}`, was \
2309                     this semver-compatible update not semver compatible?"
2310                )
2311            })?;
2312        }
2313
2314        for (to_replace, replace_with) in replacements.iter() {
2315            log::debug!(
2316                "REPLACE {} => {}",
2317                self.id_of(*to_replace).unwrap(),
2318                self.id_of(*replace_with).unwrap(),
2319            );
2320        }
2321
2322        // Finally perform the actual transformation of the imports/exports.
2323        // Here all imports are removed if they're replaced and otherwise all
2324        // imports have their dependencies updated, possibly transitively, to
2325        // point to the new interfaces in `replacements`.
2326        //
2327        // Afterwards exports are additionally updated, but only their
2328        // dependencies on imports which were remapped. Exports themselves are
2329        // not deduplicated and/or removed.
2330        for (key, item) in mem::take(&mut self.worlds[world_id].imports) {
2331            if let WorldItem::Interface { id, .. } = item {
2332                if replacements.contains_key(&id) {
2333                    continue;
2334                }
2335            }
2336
2337            self.update_interface_deps_of_world_item(&item, &replacements);
2338
2339            let prev = self.worlds[world_id].imports.insert(key, item);
2340            assert!(prev.is_none());
2341        }
2342        for (key, item) in mem::take(&mut self.worlds[world_id].exports) {
2343            self.update_interface_deps_of_world_item(&item, &replacements);
2344            let prev = self.worlds[world_id].exports.insert(key, item);
2345            assert!(prev.is_none());
2346        }
2347
2348        // Run through `elaborate_world` to reorder imports as appropriate and
2349        // fill anything back in if it's actually required by exports. For now
2350        // this doesn't tamper with exports at all. Also note that this is
2351        // applied to all worlds in this `Resolve` because interfaces were
2352        // modified directly.
2353        let ids = self.worlds.iter().map(|(id, _)| id).collect::<Vec<_>>();
2354        for world_id in ids {
2355            self.elaborate_world(world_id).with_context(|| {
2356                let name = &self.worlds[world_id].name;
2357                format!(
2358                    "failed to elaborate world `{name}` after deduplicating imports \
2359                     based on semver"
2360                )
2361            })?;
2362        }
2363
2364        #[cfg(debug_assertions)]
2365        self.assert_valid();
2366
2367        Ok(())
2368    }
2369
2370    fn update_interface_deps_of_world_item(
2371        &mut self,
2372        item: &WorldItem,
2373        replacements: &HashMap<InterfaceId, InterfaceId>,
2374    ) {
2375        match *item {
2376            WorldItem::Type(t) => self.update_interface_dep_of_type(t, &replacements),
2377            WorldItem::Interface { id, .. } => {
2378                let types = self.interfaces[id]
2379                    .types
2380                    .values()
2381                    .copied()
2382                    .collect::<Vec<_>>();
2383                for ty in types {
2384                    self.update_interface_dep_of_type(ty, &replacements);
2385                }
2386            }
2387            WorldItem::Function(_) => {}
2388        }
2389    }
2390
2391    /// Returns the "semver track" of an interface plus the interface's version.
2392    ///
2393    /// This function returns `None` if the interface `id` has a package without
2394    /// a version. If the version is present, however, the first element of the
2395    /// tuple returned is a "semver track" for the specific interface. The
2396    /// version listed in `PackageName` will be modified so all
2397    /// semver-compatible versions are listed the same way.
2398    ///
2399    /// The second element in the returned tuple is this interface's package's
2400    /// version.
2401    fn semver_track(&self, id: InterfaceId) -> Option<((PackageName, String), &Version)> {
2402        let iface = &self.interfaces[id];
2403        let pkg = &self.packages[iface.package?];
2404        let version = pkg.name.version.as_ref()?;
2405        let mut name = pkg.name.clone();
2406        name.version = Some(PackageName::version_compat_track(version));
2407        Some(((name, iface.name.clone()?), version))
2408    }
2409
2410    /// If `ty` is a definition where it's a `use` from another interface, then
2411    /// change what interface it's using from according to the pairs in the
2412    /// `replacements` map.
2413    fn update_interface_dep_of_type(
2414        &mut self,
2415        ty: TypeId,
2416        replacements: &HashMap<InterfaceId, InterfaceId>,
2417    ) {
2418        let to_replace = match self.type_interface_dep(ty) {
2419            Some(id) => id,
2420            None => return,
2421        };
2422        let replace_with = match replacements.get(&to_replace) {
2423            Some(id) => id,
2424            None => return,
2425        };
2426        let dep = match self.types[ty].kind {
2427            TypeDefKind::Type(Type::Id(id)) => id,
2428            _ => return,
2429        };
2430        let name = self.types[dep].name.as_ref().unwrap();
2431        // Note the infallible name indexing happening here. This should be
2432        // previously validated with `merge_world_item` to succeed.
2433        let replacement_id = self.interfaces[*replace_with].types[name];
2434        self.types[ty].kind = TypeDefKind::Type(Type::Id(replacement_id));
2435    }
2436
2437    /// Returns the core wasm module/field names for the specified `import`.
2438    ///
2439    /// This function will return the core wasm module/field that can be used to
2440    /// use `import` with the name `mangling` scheme specified as well. This can
2441    /// be useful for bindings generators, for example, and these names are
2442    /// recognized by `wit-component` and `wasm-tools component new`.
2443    pub fn wasm_import_name(
2444        &self,
2445        mangling: ManglingAndAbi,
2446        import: WasmImport<'_>,
2447    ) -> (String, String) {
2448        match mangling {
2449            ManglingAndAbi::Standard32 => match import {
2450                WasmImport::Func { interface, func } => {
2451                    let module = match interface {
2452                        Some(key) => format!("cm32p2|{}", self.name_canonicalized_world_key(key)),
2453                        None => format!("cm32p2"),
2454                    };
2455                    (module, func.name.clone())
2456                }
2457                WasmImport::ResourceIntrinsic {
2458                    interface,
2459                    resource,
2460                    intrinsic,
2461                } => {
2462                    let name = self.types[resource].name.as_ref().unwrap();
2463                    let (prefix, name) = match intrinsic {
2464                        ResourceIntrinsic::ImportedDrop => ("", format!("{name}_drop")),
2465                        ResourceIntrinsic::ExportedDrop => ("_ex_", format!("{name}_drop")),
2466                        ResourceIntrinsic::ExportedNew => ("_ex_", format!("{name}_new")),
2467                        ResourceIntrinsic::ExportedRep => ("_ex_", format!("{name}_rep")),
2468                    };
2469                    let module = match interface {
2470                        Some(key) => {
2471                            format!("cm32p2|{prefix}{}", self.name_canonicalized_world_key(key))
2472                        }
2473                        None => {
2474                            assert_eq!(prefix, "");
2475                            format!("cm32p2")
2476                        }
2477                    };
2478                    (module, name)
2479                }
2480            },
2481            ManglingAndAbi::Legacy(abi) => match import {
2482                WasmImport::Func { interface, func } => {
2483                    let module = match interface {
2484                        Some(key) => self.name_world_key(key),
2485                        None => format!("$root"),
2486                    };
2487                    (module, format!("{}{}", abi.import_prefix(), func.name))
2488                }
2489                WasmImport::ResourceIntrinsic {
2490                    interface,
2491                    resource,
2492                    intrinsic,
2493                } => {
2494                    let name = self.types[resource].name.as_ref().unwrap();
2495                    let (prefix, name) = match intrinsic {
2496                        ResourceIntrinsic::ImportedDrop => ("", format!("[resource-drop]{name}")),
2497                        ResourceIntrinsic::ExportedDrop => {
2498                            ("[export]", format!("[resource-drop]{name}"))
2499                        }
2500                        ResourceIntrinsic::ExportedNew => {
2501                            ("[export]", format!("[resource-new]{name}"))
2502                        }
2503                        ResourceIntrinsic::ExportedRep => {
2504                            ("[export]", format!("[resource-rep]{name}"))
2505                        }
2506                    };
2507                    let module = match interface {
2508                        Some(key) => format!("{prefix}{}", self.name_world_key(key)),
2509                        None => {
2510                            assert_eq!(prefix, "");
2511                            format!("$root")
2512                        }
2513                    };
2514                    (module, format!("{}{name}", abi.import_prefix()))
2515                }
2516            },
2517        }
2518    }
2519
2520    /// Returns the core wasm export name for the specified `export`.
2521    ///
2522    /// This is the same as [`Resolve::wasm_import_name`], except for exports.
2523    pub fn wasm_export_name(&self, mangling: ManglingAndAbi, export: WasmExport<'_>) -> String {
2524        match mangling {
2525            ManglingAndAbi::Standard32 => match export {
2526                WasmExport::Func {
2527                    interface,
2528                    func,
2529                    kind,
2530                } => {
2531                    let mut name = String::from("cm32p2|");
2532                    if let Some(interface) = interface {
2533                        let s = self.name_canonicalized_world_key(interface);
2534                        name.push_str(&s);
2535                    }
2536                    name.push_str("|");
2537                    name.push_str(&func.name);
2538                    match kind {
2539                        WasmExportKind::Normal => {}
2540                        WasmExportKind::PostReturn => name.push_str("_post"),
2541                        WasmExportKind::Callback => todo!(
2542                            "not yet supported: \
2543                             async callback functions using standard name mangling"
2544                        ),
2545                    }
2546                    name
2547                }
2548                WasmExport::ResourceDtor {
2549                    interface,
2550                    resource,
2551                } => {
2552                    let name = self.types[resource].name.as_ref().unwrap();
2553                    let interface = self.name_canonicalized_world_key(interface);
2554                    format!("cm32p2|{interface}|{name}_dtor")
2555                }
2556                WasmExport::Memory => "cm32p2_memory".to_string(),
2557                WasmExport::Initialize => "cm32p2_initialize".to_string(),
2558                WasmExport::Realloc => "cm32p2_realloc".to_string(),
2559            },
2560            ManglingAndAbi::Legacy(abi) => match export {
2561                WasmExport::Func {
2562                    interface,
2563                    func,
2564                    kind,
2565                } => {
2566                    let mut name = abi.export_prefix().to_string();
2567                    match kind {
2568                        WasmExportKind::Normal => {}
2569                        WasmExportKind::PostReturn => name.push_str("cabi_post_"),
2570                        WasmExportKind::Callback => {
2571                            assert!(matches!(abi, LiftLowerAbi::AsyncCallback));
2572                            name = format!("[callback]{name}")
2573                        }
2574                    }
2575                    if let Some(interface) = interface {
2576                        let s = self.name_world_key(interface);
2577                        name.push_str(&s);
2578                        name.push_str("#");
2579                    }
2580                    name.push_str(&func.name);
2581                    name
2582                }
2583                WasmExport::ResourceDtor {
2584                    interface,
2585                    resource,
2586                } => {
2587                    let name = self.types[resource].name.as_ref().unwrap();
2588                    let interface = self.name_world_key(interface);
2589                    format!("{}{interface}#[dtor]{name}", abi.export_prefix())
2590                }
2591                WasmExport::Memory => "memory".to_string(),
2592                WasmExport::Initialize => "_initialize".to_string(),
2593                WasmExport::Realloc => "cabi_realloc".to_string(),
2594            },
2595        }
2596    }
2597}
2598
2599/// Possible imports that can be passed to [`Resolve::wasm_import_name`].
2600#[derive(Debug)]
2601pub enum WasmImport<'a> {
2602    /// A WIT function is being imported. Optionally from an interface.
2603    Func {
2604        /// The name of the interface that the function is being imported from.
2605        ///
2606        /// If the function is imported directly from the world then this is
2607        /// `Noen`.
2608        interface: Option<&'a WorldKey>,
2609
2610        /// The function being imported.
2611        func: &'a Function,
2612    },
2613
2614    /// A resource-related intrinsic is being imported.
2615    ResourceIntrinsic {
2616        /// The optional interface to import from, same as `WasmImport::Func`.
2617        interface: Option<&'a WorldKey>,
2618
2619        /// The resource that's being operated on.
2620        resource: TypeId,
2621
2622        /// The intrinsic that's being imported.
2623        intrinsic: ResourceIntrinsic,
2624    },
2625}
2626
2627/// Intrinsic definitions to go with [`WasmImport::ResourceIntrinsic`] which
2628/// also goes with [`Resolve::wasm_import_name`].
2629#[derive(Debug)]
2630pub enum ResourceIntrinsic {
2631    ImportedDrop,
2632    ExportedDrop,
2633    ExportedNew,
2634    ExportedRep,
2635}
2636
2637/// Indicates whether a function export is a normal export, a post-return
2638/// function, or a callback function.
2639#[derive(Debug)]
2640pub enum WasmExportKind {
2641    /// Normal function export.
2642    Normal,
2643
2644    /// Post-return function.
2645    PostReturn,
2646
2647    /// Async callback function.
2648    Callback,
2649}
2650
2651/// Different kinds of exports that can be passed to
2652/// [`Resolve::wasm_export_name`] to export from core wasm modules.
2653#[derive(Debug)]
2654pub enum WasmExport<'a> {
2655    /// A WIT function is being exported, optionally from an interface.
2656    Func {
2657        /// An optional interface which owns `func`. Use `None` for top-level
2658        /// world function.
2659        interface: Option<&'a WorldKey>,
2660
2661        /// The function being exported.
2662        func: &'a Function,
2663
2664        /// Kind of function (normal, post-return, or callback) being exported.
2665        kind: WasmExportKind,
2666    },
2667
2668    /// A destructor for a resource exported from this module.
2669    ResourceDtor {
2670        /// The interface that owns the resource.
2671        interface: &'a WorldKey,
2672        /// The resource itself that the destructor is for.
2673        resource: TypeId,
2674    },
2675
2676    /// Linear memory, the one that the canonical ABI uses.
2677    Memory,
2678
2679    /// An initialization function (not the core wasm `start`).
2680    Initialize,
2681
2682    /// The general-purpose realloc hook.
2683    Realloc,
2684}
2685
2686/// Structure returned by [`Resolve::merge`] which contains mappings from
2687/// old-ids to new-ids after the merge.
2688#[derive(Default)]
2689pub struct Remap {
2690    pub types: Vec<Option<TypeId>>,
2691    pub interfaces: Vec<Option<InterfaceId>>,
2692    pub worlds: Vec<Option<WorldId>>,
2693    pub packages: Vec<PackageId>,
2694
2695    /// A cache of anonymous `own<T>` handles for resource types.
2696    ///
2697    /// The appending operation of `Remap` is the one responsible for
2698    /// translating references to `T` where `T` is a resource into `own<T>`
2699    /// instead. This map is used to deduplicate the `own<T>` types generated
2700    /// to generate as few as possible.
2701    ///
2702    /// The key of this map is the resource id `T` in the new resolve, and
2703    /// the value is the `own<T>` type pointing to `T`.
2704    own_handles: HashMap<TypeId, TypeId>,
2705
2706    type_has_borrow: Vec<Option<bool>>,
2707}
2708
2709fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Option<Span>) -> Result<Id<T>> {
2710    match map.get(id.index()) {
2711        Some(Some(id)) => Ok(*id),
2712        Some(None) => {
2713            let msg = format!(
2714                "found a reference to a {desc} which is excluded \
2715                 due to its feature not being activated"
2716            );
2717            match span {
2718                Some(span) => Err(Error::new(span, msg).into()),
2719                None => bail!("{msg}"),
2720            }
2721        }
2722        None => panic!("request to remap a {desc} that has not yet been registered"),
2723    }
2724}
2725
2726impl Remap {
2727    pub fn map_type(&self, id: TypeId, span: Option<Span>) -> Result<TypeId> {
2728        apply_map(&self.types, id, "type", span)
2729    }
2730
2731    pub fn map_interface(&self, id: InterfaceId, span: Option<Span>) -> Result<InterfaceId> {
2732        apply_map(&self.interfaces, id, "interface", span)
2733    }
2734
2735    pub fn map_world(&self, id: WorldId, span: Option<Span>) -> Result<WorldId> {
2736        apply_map(&self.worlds, id, "world", span)
2737    }
2738
2739    fn append(
2740        &mut self,
2741        resolve: &mut Resolve,
2742        unresolved: UnresolvedPackage,
2743    ) -> Result<PackageId> {
2744        let pkgid = resolve.packages.alloc(Package {
2745            name: unresolved.name.clone(),
2746            docs: unresolved.docs.clone(),
2747            interfaces: Default::default(),
2748            worlds: Default::default(),
2749        });
2750        let prev = resolve.package_names.insert(unresolved.name.clone(), pkgid);
2751        if let Some(prev) = prev {
2752            resolve.package_names.insert(unresolved.name.clone(), prev);
2753            bail!(
2754                "attempting to re-add package `{}` when it's already present in this `Resolve`",
2755                unresolved.name,
2756            );
2757        }
2758
2759        self.process_foreign_deps(resolve, pkgid, &unresolved)?;
2760
2761        let foreign_types = self.types.len();
2762        let foreign_interfaces = self.interfaces.len();
2763        let foreign_worlds = self.worlds.len();
2764
2765        // Copy over all types first, updating any intra-type references. Note
2766        // that types are sorted topologically which means this iteration
2767        // order should be sufficient. Also note though that the interface
2768        // owner of a type isn't updated here due to interfaces not being known
2769        // yet.
2770        assert_eq!(unresolved.types.len(), unresolved.type_spans.len());
2771        for ((id, mut ty), span) in unresolved
2772            .types
2773            .into_iter()
2774            .zip(&unresolved.type_spans)
2775            .skip(foreign_types)
2776        {
2777            if !resolve.include_type(&ty, pkgid, *span)? {
2778                self.types.push(None);
2779                continue;
2780            }
2781
2782            self.update_typedef(resolve, &mut ty, Some(*span))?;
2783            let new_id = resolve.types.alloc(ty);
2784            assert_eq!(self.types.len(), id.index());
2785
2786            let new_id = match resolve.types[new_id] {
2787                // If this is an `own<T>` handle then either replace it with a
2788                // preexisting `own<T>` handle which may have been generated in
2789                // `update_ty`. If that doesn't exist though then insert it into
2790                // the `own_handles` cache.
2791                TypeDef {
2792                    name: None,
2793                    owner: TypeOwner::None,
2794                    kind: TypeDefKind::Handle(Handle::Own(id)),
2795                    docs: _,
2796                    stability: _,
2797                } => *self.own_handles.entry(id).or_insert(new_id),
2798
2799                // Everything not-related to `own<T>` doesn't get its ID
2800                // modified.
2801                _ => new_id,
2802            };
2803            self.types.push(Some(new_id));
2804        }
2805
2806        // Next transfer all interfaces into `Resolve`, updating type ids
2807        // referenced along the way.
2808        assert_eq!(
2809            unresolved.interfaces.len(),
2810            unresolved.interface_spans.len()
2811        );
2812        for ((id, mut iface), span) in unresolved
2813            .interfaces
2814            .into_iter()
2815            .zip(&unresolved.interface_spans)
2816            .skip(foreign_interfaces)
2817        {
2818            if !resolve
2819                .include_stability(&iface.stability, &pkgid, Some(span.span))
2820                .with_context(|| {
2821                    format!(
2822                        "failed to process feature gate for interface [{}] in package [{}]",
2823                        iface
2824                            .name
2825                            .as_ref()
2826                            .map(String::as_str)
2827                            .unwrap_or("<unknown>"),
2828                        resolve.packages[pkgid].name,
2829                    )
2830                })?
2831            {
2832                self.interfaces.push(None);
2833                continue;
2834            }
2835            assert!(iface.package.is_none());
2836            iface.package = Some(pkgid);
2837            self.update_interface(resolve, &mut iface, Some(span))?;
2838            let new_id = resolve.interfaces.alloc(iface);
2839            assert_eq!(self.interfaces.len(), id.index());
2840            self.interfaces.push(Some(new_id));
2841        }
2842
2843        // Now that interfaces are identified go back through the types and
2844        // update their interface owners.
2845        for (i, id) in self.types.iter().enumerate().skip(foreign_types) {
2846            let id = match id {
2847                Some(id) => *id,
2848                None => continue,
2849            };
2850            match &mut resolve.types[id].owner {
2851                TypeOwner::Interface(id) => {
2852                    let span = unresolved.type_spans[i];
2853                    *id = self.map_interface(*id, Some(span))
2854                        .with_context(|| {
2855                            "this type is not gated by a feature but its interface is gated by a feature"
2856                        })?;
2857                }
2858                TypeOwner::World(_) | TypeOwner::None => {}
2859            }
2860        }
2861
2862        // Perform a weighty step of full resolution of worlds. This will fully
2863        // expand imports/exports for a world and create the topological
2864        // ordering necessary for this.
2865        //
2866        // This is done after types/interfaces are fully settled so the
2867        // transitive relation between interfaces, through types, is understood
2868        // here.
2869        assert_eq!(unresolved.worlds.len(), unresolved.world_spans.len());
2870        for ((id, mut world), span) in unresolved
2871            .worlds
2872            .into_iter()
2873            .zip(&unresolved.world_spans)
2874            .skip(foreign_worlds)
2875        {
2876            if !resolve
2877                .include_stability(&world.stability, &pkgid, Some(span.span))
2878                .with_context(|| {
2879                    format!(
2880                        "failed to process feature gate for world [{}] in package [{}]",
2881                        world.name, resolve.packages[pkgid].name,
2882                    )
2883                })?
2884            {
2885                self.worlds.push(None);
2886                continue;
2887            }
2888            self.update_world(&mut world, resolve, &pkgid, &span)?;
2889
2890            let new_id = resolve.worlds.alloc(world);
2891            assert_eq!(self.worlds.len(), id.index());
2892            self.worlds.push(Some(new_id));
2893
2894            resolve.elaborate_world(new_id).with_context(|| {
2895                Error::new(
2896                    span.span,
2897                    format!(
2898                        "failed to elaborate world imports/exports of `{}`",
2899                        resolve.worlds[new_id].name
2900                    ),
2901                )
2902            })?;
2903        }
2904
2905        // As with interfaces, now update the ids of world-owned types.
2906        for (i, id) in self.types.iter().enumerate().skip(foreign_types) {
2907            let id = match id {
2908                Some(id) => *id,
2909                None => continue,
2910            };
2911            match &mut resolve.types[id].owner {
2912                TypeOwner::World(id) => {
2913                    let span = unresolved.type_spans[i];
2914                    *id = self.map_world(*id, Some(span))
2915                        .with_context(|| {
2916                            "this type is not gated by a feature but its interface is gated by a feature"
2917                        })?;
2918                }
2919                TypeOwner::Interface(_) | TypeOwner::None => {}
2920            }
2921        }
2922
2923        // Fixup "parent" ids now that everything has been identified
2924        for id in self.interfaces.iter().skip(foreign_interfaces) {
2925            let id = match id {
2926                Some(id) => *id,
2927                None => continue,
2928            };
2929            let iface = &mut resolve.interfaces[id];
2930            iface.package = Some(pkgid);
2931            if let Some(name) = &iface.name {
2932                let prev = resolve.packages[pkgid].interfaces.insert(name.clone(), id);
2933                assert!(prev.is_none());
2934            }
2935        }
2936        for id in self.worlds.iter().skip(foreign_worlds) {
2937            let id = match id {
2938                Some(id) => *id,
2939                None => continue,
2940            };
2941            let world = &mut resolve.worlds[id];
2942            world.package = Some(pkgid);
2943            let prev = resolve.packages[pkgid]
2944                .worlds
2945                .insert(world.name.clone(), id);
2946            assert!(prev.is_none());
2947        }
2948        Ok(pkgid)
2949    }
2950
2951    fn process_foreign_deps(
2952        &mut self,
2953        resolve: &mut Resolve,
2954        pkgid: PackageId,
2955        unresolved: &UnresolvedPackage,
2956    ) -> Result<()> {
2957        // Invert the `foreign_deps` map to be keyed by world id to get
2958        // used in the loops below.
2959        let mut world_to_package = HashMap::new();
2960        let mut interface_to_package = HashMap::new();
2961        for (i, (pkg_name, worlds_or_ifaces)) in unresolved.foreign_deps.iter().enumerate() {
2962            for (name, item) in worlds_or_ifaces {
2963                match item {
2964                    AstItem::Interface(unresolved_interface_id) => {
2965                        let prev = interface_to_package.insert(
2966                            *unresolved_interface_id,
2967                            (pkg_name, name, unresolved.foreign_dep_spans[i]),
2968                        );
2969                        assert!(prev.is_none());
2970                    }
2971                    AstItem::World(unresolved_world_id) => {
2972                        let prev = world_to_package.insert(
2973                            *unresolved_world_id,
2974                            (pkg_name, name, unresolved.foreign_dep_spans[i]),
2975                        );
2976                        assert!(prev.is_none());
2977                    }
2978                }
2979            }
2980        }
2981
2982        // Connect all interfaces referred to in `interface_to_package`, which
2983        // are at the front of `unresolved.interfaces`, to interfaces already
2984        // contained within `resolve`.
2985        self.process_foreign_interfaces(unresolved, &interface_to_package, resolve)?;
2986
2987        // Connect all worlds referred to in `world_to_package`, which
2988        // are at the front of `unresolved.worlds`, to worlds already
2989        // contained within `resolve`.
2990        self.process_foreign_worlds(unresolved, &world_to_package, resolve)?;
2991
2992        // Finally, iterate over all foreign-defined types and determine
2993        // what they map to.
2994        self.process_foreign_types(unresolved, pkgid, resolve)?;
2995
2996        for (id, span) in unresolved.required_resource_types.iter() {
2997            // Note that errors are ignored here because an error represents a
2998            // type that has been configured away. If a type is configured away
2999            // then any future use of it will generate an error so there's no
3000            // need to validate that it's a resource here.
3001            let Ok(mut id) = self.map_type(*id, Some(*span)) else {
3002                continue;
3003            };
3004            loop {
3005                match resolve.types[id].kind {
3006                    TypeDefKind::Type(Type::Id(i)) => id = i,
3007                    TypeDefKind::Resource => break,
3008                    _ => bail!(Error::new(
3009                        *span,
3010                        format!("type used in a handle must be a resource"),
3011                    )),
3012                }
3013            }
3014        }
3015
3016        #[cfg(debug_assertions)]
3017        resolve.assert_valid();
3018
3019        Ok(())
3020    }
3021
3022    fn process_foreign_interfaces(
3023        &mut self,
3024        unresolved: &UnresolvedPackage,
3025        interface_to_package: &HashMap<InterfaceId, (&PackageName, &String, Span)>,
3026        resolve: &mut Resolve,
3027    ) -> Result<(), anyhow::Error> {
3028        for (unresolved_iface_id, unresolved_iface) in unresolved.interfaces.iter() {
3029            let (pkg_name, interface, span) = match interface_to_package.get(&unresolved_iface_id) {
3030                Some(items) => *items,
3031                // All foreign interfaces are defined first, so the first one
3032                // which is defined in a non-foreign document means that all
3033                // further interfaces will be non-foreign as well.
3034                None => break,
3035            };
3036            let pkgid = resolve
3037                .package_names
3038                .get(pkg_name)
3039                .copied()
3040                .ok_or_else(|| {
3041                    PackageNotFoundError::new(
3042                        span,
3043                        pkg_name.clone(),
3044                        resolve.package_names.keys().cloned().collect(),
3045                    )
3046                })?;
3047
3048            // Functions can't be imported so this should be empty.
3049            assert!(unresolved_iface.functions.is_empty());
3050
3051            let pkg = &resolve.packages[pkgid];
3052            let span = &unresolved.interface_spans[unresolved_iface_id.index()];
3053            let iface_id = pkg
3054                .interfaces
3055                .get(interface)
3056                .copied()
3057                .ok_or_else(|| Error::new(span.span, "interface not found in package"))?;
3058            assert_eq!(self.interfaces.len(), unresolved_iface_id.index());
3059            self.interfaces.push(Some(iface_id));
3060        }
3061        for (id, _) in unresolved.interfaces.iter().skip(self.interfaces.len()) {
3062            assert!(
3063                interface_to_package.get(&id).is_none(),
3064                "found foreign interface after local interface"
3065            );
3066        }
3067        Ok(())
3068    }
3069
3070    fn process_foreign_worlds(
3071        &mut self,
3072        unresolved: &UnresolvedPackage,
3073        world_to_package: &HashMap<WorldId, (&PackageName, &String, Span)>,
3074        resolve: &mut Resolve,
3075    ) -> Result<(), anyhow::Error> {
3076        for (unresolved_world_id, _) in unresolved.worlds.iter() {
3077            let (pkg_name, world, span) = match world_to_package.get(&unresolved_world_id) {
3078                Some(items) => *items,
3079                // Same as above, all worlds are foreign until we find a
3080                // non-foreign one.
3081                None => break,
3082            };
3083
3084            let pkgid = resolve
3085                .package_names
3086                .get(pkg_name)
3087                .copied()
3088                .ok_or_else(|| Error::new(span, "package not found"))?;
3089            let pkg = &resolve.packages[pkgid];
3090            let span = &unresolved.world_spans[unresolved_world_id.index()];
3091            let world_id = pkg
3092                .worlds
3093                .get(world)
3094                .copied()
3095                .ok_or_else(|| Error::new(span.span, "world not found in package"))?;
3096            assert_eq!(self.worlds.len(), unresolved_world_id.index());
3097            self.worlds.push(Some(world_id));
3098        }
3099        for (id, _) in unresolved.worlds.iter().skip(self.worlds.len()) {
3100            assert!(
3101                world_to_package.get(&id).is_none(),
3102                "found foreign world after local world"
3103            );
3104        }
3105        Ok(())
3106    }
3107
3108    fn process_foreign_types(
3109        &mut self,
3110        unresolved: &UnresolvedPackage,
3111        pkgid: PackageId,
3112        resolve: &mut Resolve,
3113    ) -> Result<(), anyhow::Error> {
3114        for ((unresolved_type_id, unresolved_ty), span) in
3115            unresolved.types.iter().zip(&unresolved.type_spans)
3116        {
3117            // All "Unknown" types should appear first so once we're no longer
3118            // in unknown territory it's package-defined types so break out of
3119            // this loop.
3120            match unresolved_ty.kind {
3121                TypeDefKind::Unknown => {}
3122                _ => break,
3123            }
3124
3125            if !resolve.include_type(unresolved_ty, pkgid, *span)? {
3126                self.types.push(None);
3127                continue;
3128            }
3129
3130            let unresolved_iface_id = match unresolved_ty.owner {
3131                TypeOwner::Interface(id) => id,
3132                _ => unreachable!(),
3133            };
3134            let iface_id = self.map_interface(unresolved_iface_id, None)?;
3135            let name = unresolved_ty.name.as_ref().unwrap();
3136            let span = unresolved.unknown_type_spans[unresolved_type_id.index()];
3137            let type_id = *resolve.interfaces[iface_id]
3138                .types
3139                .get(name)
3140                .ok_or_else(|| {
3141                    Error::new(span, format!("type `{name}` not defined in interface"))
3142                })?;
3143            assert_eq!(self.types.len(), unresolved_type_id.index());
3144            self.types.push(Some(type_id));
3145        }
3146        for (_, ty) in unresolved.types.iter().skip(self.types.len()) {
3147            if let TypeDefKind::Unknown = ty.kind {
3148                panic!("unknown type after defined type");
3149            }
3150        }
3151        Ok(())
3152    }
3153
3154    fn update_typedef(
3155        &mut self,
3156        resolve: &mut Resolve,
3157        ty: &mut TypeDef,
3158        span: Option<Span>,
3159    ) -> Result<()> {
3160        // NB: note that `ty.owner` is not updated here since interfaces
3161        // haven't been mapped yet and that's done in a separate step.
3162        use crate::TypeDefKind::*;
3163        match &mut ty.kind {
3164            Handle(handle) => match handle {
3165                crate::Handle::Own(ty) | crate::Handle::Borrow(ty) => {
3166                    self.update_type_id(ty, span)?
3167                }
3168            },
3169            Resource => {}
3170            Record(r) => {
3171                for field in r.fields.iter_mut() {
3172                    self.update_ty(resolve, &mut field.ty, span)
3173                        .with_context(|| format!("failed to update field `{}`", field.name))?;
3174                }
3175            }
3176            Tuple(t) => {
3177                for ty in t.types.iter_mut() {
3178                    self.update_ty(resolve, ty, span)?;
3179                }
3180            }
3181            Variant(v) => {
3182                for case in v.cases.iter_mut() {
3183                    if let Some(t) = &mut case.ty {
3184                        self.update_ty(resolve, t, span)?;
3185                    }
3186                }
3187            }
3188            Option(t) | List(t, ..) | FixedSizeList(t, ..) | Future(Some(t)) | Stream(Some(t)) => {
3189                self.update_ty(resolve, t, span)?
3190            }
3191            Result(r) => {
3192                if let Some(ty) = &mut r.ok {
3193                    self.update_ty(resolve, ty, span)?;
3194                }
3195                if let Some(ty) = &mut r.err {
3196                    self.update_ty(resolve, ty, span)?;
3197                }
3198            }
3199
3200            // Note that `update_ty` is specifically not used here as typedefs
3201            // because for the `type a = b` form that doesn't force `a` to be a
3202            // handle type if `b` is a resource type, instead `a` is
3203            // simultaneously usable as a resource and a handle type
3204            Type(crate::Type::Id(id)) => self.update_type_id(id, span)?,
3205            Type(_) => {}
3206
3207            // nothing to do for these as they're just names or empty
3208            Flags(_) | Enum(_) | Future(None) | Stream(None) => {}
3209
3210            Unknown => unreachable!(),
3211        }
3212
3213        Ok(())
3214    }
3215
3216    fn update_ty(
3217        &mut self,
3218        resolve: &mut Resolve,
3219        ty: &mut Type,
3220        span: Option<Span>,
3221    ) -> Result<()> {
3222        let id = match ty {
3223            Type::Id(id) => id,
3224            _ => return Ok(()),
3225        };
3226        self.update_type_id(id, span)?;
3227
3228        // If `id` points to a `Resource` type then this means that what was
3229        // just discovered was a reference to what will implicitly become an
3230        // `own<T>` handle. This `own` handle is implicitly allocated here
3231        // and handled during the merging process.
3232        let mut cur = *id;
3233        let points_to_resource = loop {
3234            match resolve.types[cur].kind {
3235                TypeDefKind::Type(Type::Id(id)) => cur = id,
3236                TypeDefKind::Resource => break true,
3237                _ => break false,
3238            }
3239        };
3240
3241        if points_to_resource {
3242            *id = *self.own_handles.entry(*id).or_insert_with(|| {
3243                resolve.types.alloc(TypeDef {
3244                    name: None,
3245                    owner: TypeOwner::None,
3246                    kind: TypeDefKind::Handle(Handle::Own(*id)),
3247                    docs: Default::default(),
3248                    stability: Default::default(),
3249                })
3250            });
3251        }
3252        Ok(())
3253    }
3254
3255    fn update_type_id(&self, id: &mut TypeId, span: Option<Span>) -> Result<()> {
3256        *id = self.map_type(*id, span)?;
3257        Ok(())
3258    }
3259
3260    fn update_interface(
3261        &mut self,
3262        resolve: &mut Resolve,
3263        iface: &mut Interface,
3264        spans: Option<&InterfaceSpan>,
3265    ) -> Result<()> {
3266        iface.types.retain(|_, ty| self.types[ty.index()].is_some());
3267        let iface_pkg_id = iface.package.as_ref().unwrap_or_else(|| {
3268            panic!(
3269                "unexpectedly missing package on interface [{}]",
3270                iface
3271                    .name
3272                    .as_ref()
3273                    .map(String::as_str)
3274                    .unwrap_or("<unknown>"),
3275            )
3276        });
3277
3278        // NB: note that `iface.doc` is not updated here since interfaces
3279        // haven't been mapped yet and that's done in a separate step.
3280        for (_name, ty) in iface.types.iter_mut() {
3281            self.update_type_id(ty, spans.map(|s| s.span))?;
3282        }
3283        if let Some(spans) = spans {
3284            assert_eq!(iface.functions.len(), spans.funcs.len());
3285        }
3286        for (i, (func_name, func)) in iface.functions.iter_mut().enumerate() {
3287            let span = spans.map(|s| s.funcs[i]);
3288            if !resolve
3289                .include_stability(&func.stability, iface_pkg_id, span)
3290                .with_context(|| {
3291                    format!(
3292                        "failed to process feature gate for function [{func_name}] in package [{}]",
3293                        resolve.packages[*iface_pkg_id].name,
3294                    )
3295                })?
3296            {
3297                continue;
3298            }
3299            self.update_function(resolve, func, span)
3300                .with_context(|| format!("failed to update function `{}`", func.name))?;
3301        }
3302
3303        // Filter out all of the existing functions in interface which fail the
3304        // `include_stability()` check, as they shouldn't be available.
3305        for (name, func) in mem::take(&mut iface.functions) {
3306            if resolve.include_stability(&func.stability, iface_pkg_id, None)? {
3307                iface.functions.insert(name, func);
3308            }
3309        }
3310
3311        Ok(())
3312    }
3313
3314    fn update_function(
3315        &mut self,
3316        resolve: &mut Resolve,
3317        func: &mut Function,
3318        span: Option<Span>,
3319    ) -> Result<()> {
3320        if let Some(id) = func.kind.resource_mut() {
3321            self.update_type_id(id, span)?;
3322        }
3323        for (_, ty) in func.params.iter_mut() {
3324            self.update_ty(resolve, ty, span)?;
3325        }
3326        if let Some(ty) = &mut func.result {
3327            self.update_ty(resolve, ty, span)?;
3328        }
3329
3330        if let Some(ty) = &func.result {
3331            if self.type_has_borrow(resolve, ty) {
3332                match span {
3333                    Some(span) => {
3334                        bail!(Error::new(
3335                            span,
3336                            format!(
3337                                "function returns a type which contains \
3338                                 a `borrow<T>` which is not supported"
3339                            )
3340                        ))
3341                    }
3342                    None => unreachable!(),
3343                }
3344            }
3345        }
3346
3347        Ok(())
3348    }
3349
3350    fn update_world(
3351        &mut self,
3352        world: &mut World,
3353        resolve: &mut Resolve,
3354        pkg_id: &PackageId,
3355        spans: &WorldSpan,
3356    ) -> Result<()> {
3357        assert_eq!(world.imports.len(), spans.imports.len());
3358        assert_eq!(world.exports.len(), spans.exports.len());
3359
3360        // Rewrite imports/exports with their updated versions. Note that this
3361        // may involve updating the key of the imports/exports maps so this
3362        // starts by emptying them out and then everything is re-inserted.
3363        let imports = mem::take(&mut world.imports).into_iter();
3364        let imports = imports.zip(&spans.imports).map(|p| (p, true));
3365        let exports = mem::take(&mut world.exports).into_iter();
3366        let exports = exports.zip(&spans.exports).map(|p| (p, false));
3367        for (((mut name, mut item), span), import) in imports.chain(exports) {
3368            // Update the `id` eagerly here so `item.stability(..)` below
3369            // works.
3370            if let WorldItem::Type(id) = &mut item {
3371                *id = self.map_type(*id, Some(*span))?;
3372            }
3373            let stability = item.stability(resolve);
3374            if !resolve
3375                .include_stability(stability, pkg_id, Some(*span))
3376                .with_context(|| format!("failed to process world item in `{}`", world.name))?
3377            {
3378                continue;
3379            }
3380            self.update_world_key(&mut name, Some(*span))?;
3381            match &mut item {
3382                WorldItem::Interface { id, .. } => {
3383                    *id = self.map_interface(*id, Some(*span))?;
3384                }
3385                WorldItem::Function(f) => {
3386                    self.update_function(resolve, f, Some(*span))?;
3387                }
3388                WorldItem::Type(_) => {
3389                    // already mapped above
3390                }
3391            }
3392
3393            let dst = if import {
3394                &mut world.imports
3395            } else {
3396                &mut world.exports
3397            };
3398            let prev = dst.insert(name, item);
3399            assert!(prev.is_none());
3400        }
3401
3402        // Resolve all `include` statements of the world which will add more
3403        // entries to the imports/exports list for this world.
3404        assert_eq!(world.includes.len(), spans.includes.len());
3405        let includes = mem::take(&mut world.includes);
3406        let include_names = mem::take(&mut world.include_names);
3407        for (((stability, include_world), span), names) in includes
3408            .into_iter()
3409            .zip(&spans.includes)
3410            .zip(&include_names)
3411        {
3412            if !resolve
3413                .include_stability(&stability, pkg_id, Some(*span))
3414                .with_context(|| {
3415                    format!(
3416                        "failed to process feature gate for included world [{}] in package [{}]",
3417                        resolve.worlds[include_world].name.as_str(),
3418                        resolve.packages[*pkg_id].name
3419                    )
3420                })?
3421            {
3422                continue;
3423            }
3424            self.resolve_include(world, include_world, names, *span, resolve)?;
3425        }
3426
3427        Ok(())
3428    }
3429
3430    fn update_world_key(&self, key: &mut WorldKey, span: Option<Span>) -> Result<()> {
3431        match key {
3432            WorldKey::Name(_) => {}
3433            WorldKey::Interface(id) => {
3434                *id = self.map_interface(*id, span)?;
3435            }
3436        }
3437        Ok(())
3438    }
3439
3440    fn resolve_include(
3441        &self,
3442        world: &mut World,
3443        include_world: WorldId,
3444        names: &[IncludeName],
3445        span: Span,
3446        resolve: &Resolve,
3447    ) -> Result<()> {
3448        let include_world_id = self.map_world(include_world, Some(span))?;
3449        let include_world = &resolve.worlds[include_world_id];
3450        let mut names_ = names.to_owned();
3451        let is_external_include = world.package != include_world.package;
3452
3453        // remove all imports and exports that match the names we're including
3454        for import in include_world.imports.iter() {
3455            self.remove_matching_name(import, &mut names_);
3456        }
3457        for export in include_world.exports.iter() {
3458            self.remove_matching_name(export, &mut names_);
3459        }
3460        if !names_.is_empty() {
3461            bail!(Error::new(
3462                span,
3463                format!("no import or export kebab-name `{}`. Note that an ID does not support renaming", names_[0].name),
3464            ));
3465        }
3466
3467        // copy the imports and exports from the included world into the current world
3468        for import in include_world.imports.iter() {
3469            self.resolve_include_item(
3470                names,
3471                &mut world.imports,
3472                import,
3473                span,
3474                "import",
3475                is_external_include,
3476            )?;
3477        }
3478
3479        for export in include_world.exports.iter() {
3480            self.resolve_include_item(
3481                names,
3482                &mut world.exports,
3483                export,
3484                span,
3485                "export",
3486                is_external_include,
3487            )?;
3488        }
3489        Ok(())
3490    }
3491
3492    fn resolve_include_item(
3493        &self,
3494        names: &[IncludeName],
3495        items: &mut IndexMap<WorldKey, WorldItem>,
3496        item: (&WorldKey, &WorldItem),
3497        span: Span,
3498        item_type: &str,
3499        is_external_include: bool,
3500    ) -> Result<()> {
3501        match item.0 {
3502            WorldKey::Name(n) => {
3503                let n = if let Some(found) = names
3504                    .into_iter()
3505                    .find(|include_name| include_name.name == n.clone())
3506                {
3507                    found.as_.clone()
3508                } else {
3509                    n.clone()
3510                };
3511
3512                let prev = items.insert(WorldKey::Name(n.clone()), item.1.clone());
3513                if prev.is_some() {
3514                    bail!(Error::new(
3515                        span,
3516                        format!("{item_type} of `{n}` shadows previously {item_type}ed items"),
3517                    ))
3518                }
3519            }
3520            key @ WorldKey::Interface(_) => {
3521                let prev = items.entry(key.clone()).or_insert(item.1.clone());
3522                match (&item.1, prev) {
3523                    (
3524                        WorldItem::Interface {
3525                            id: aid,
3526                            stability: astability,
3527                        },
3528                        WorldItem::Interface {
3529                            id: bid,
3530                            stability: bstability,
3531                        },
3532                    ) => {
3533                        assert_eq!(*aid, *bid);
3534                        merge_include_stability(astability, bstability, is_external_include)?;
3535                    }
3536                    (WorldItem::Interface { .. }, _) => unreachable!(),
3537                    (WorldItem::Function(_), _) => unreachable!(),
3538                    (WorldItem::Type(_), _) => unreachable!(),
3539                }
3540            }
3541        };
3542        Ok(())
3543    }
3544
3545    fn remove_matching_name(&self, item: (&WorldKey, &WorldItem), names: &mut Vec<IncludeName>) {
3546        match item.0 {
3547            WorldKey::Name(n) => {
3548                names.retain(|name| name.name != n.clone());
3549            }
3550            _ => {}
3551        }
3552    }
3553
3554    fn type_has_borrow(&mut self, resolve: &Resolve, ty: &Type) -> bool {
3555        let id = match ty {
3556            Type::Id(id) => *id,
3557            _ => return false,
3558        };
3559
3560        if let Some(Some(has_borrow)) = self.type_has_borrow.get(id.index()) {
3561            return *has_borrow;
3562        }
3563
3564        let result = self.typedef_has_borrow(resolve, &resolve.types[id]);
3565        if self.type_has_borrow.len() <= id.index() {
3566            self.type_has_borrow.resize(id.index() + 1, None);
3567        }
3568        self.type_has_borrow[id.index()] = Some(result);
3569        result
3570    }
3571
3572    fn typedef_has_borrow(&mut self, resolve: &Resolve, ty: &TypeDef) -> bool {
3573        match &ty.kind {
3574            TypeDefKind::Type(t) => self.type_has_borrow(resolve, t),
3575            TypeDefKind::Variant(v) => v
3576                .cases
3577                .iter()
3578                .filter_map(|case| case.ty.as_ref())
3579                .any(|ty| self.type_has_borrow(resolve, ty)),
3580            TypeDefKind::Handle(Handle::Borrow(_)) => true,
3581            TypeDefKind::Handle(Handle::Own(_)) => false,
3582            TypeDefKind::Resource => false,
3583            TypeDefKind::Record(r) => r
3584                .fields
3585                .iter()
3586                .any(|case| self.type_has_borrow(resolve, &case.ty)),
3587            TypeDefKind::Flags(_) => false,
3588            TypeDefKind::Tuple(t) => t.types.iter().any(|t| self.type_has_borrow(resolve, t)),
3589            TypeDefKind::Enum(_) => false,
3590            TypeDefKind::List(ty)
3591            | TypeDefKind::FixedSizeList(ty, ..)
3592            | TypeDefKind::Future(Some(ty))
3593            | TypeDefKind::Stream(Some(ty))
3594            | TypeDefKind::Option(ty) => self.type_has_borrow(resolve, ty),
3595            TypeDefKind::Result(r) => [&r.ok, &r.err]
3596                .iter()
3597                .filter_map(|t| t.as_ref())
3598                .any(|t| self.type_has_borrow(resolve, t)),
3599            TypeDefKind::Future(None) | TypeDefKind::Stream(None) => false,
3600            TypeDefKind::Unknown => unreachable!(),
3601        }
3602    }
3603}
3604
3605struct MergeMap<'a> {
3606    /// A map of package ids in `from` to those in `into` for those that are
3607    /// found to be equivalent.
3608    package_map: HashMap<PackageId, PackageId>,
3609
3610    /// A map of interface ids in `from` to those in `into` for those that are
3611    /// found to be equivalent.
3612    interface_map: HashMap<InterfaceId, InterfaceId>,
3613
3614    /// A map of type ids in `from` to those in `into` for those that are
3615    /// found to be equivalent.
3616    type_map: HashMap<TypeId, TypeId>,
3617
3618    /// A map of world ids in `from` to those in `into` for those that are
3619    /// found to be equivalent.
3620    world_map: HashMap<WorldId, WorldId>,
3621
3622    /// A list of documents that need to be added to packages in `into`.
3623    ///
3624    /// The elements here are:
3625    ///
3626    /// * The name of the interface/world
3627    /// * The ID within `into` of the package being added to
3628    /// * The ID within `from` of the item being added.
3629    interfaces_to_add: Vec<(String, PackageId, InterfaceId)>,
3630    worlds_to_add: Vec<(String, PackageId, WorldId)>,
3631
3632    /// Which `Resolve` is being merged from.
3633    from: &'a Resolve,
3634
3635    /// Which `Resolve` is being merged into.
3636    into: &'a Resolve,
3637}
3638
3639impl<'a> MergeMap<'a> {
3640    fn new(from: &'a Resolve, into: &'a Resolve) -> MergeMap<'a> {
3641        MergeMap {
3642            package_map: Default::default(),
3643            interface_map: Default::default(),
3644            type_map: Default::default(),
3645            world_map: Default::default(),
3646            interfaces_to_add: Default::default(),
3647            worlds_to_add: Default::default(),
3648            from,
3649            into,
3650        }
3651    }
3652
3653    fn build(&mut self) -> Result<()> {
3654        for from_id in self.from.topological_packages() {
3655            let from = &self.from.packages[from_id];
3656            let into_id = match self.into.package_names.get(&from.name) {
3657                Some(id) => *id,
3658
3659                // This package, according to its name and url, is not present
3660                // in `self` so it needs to get added below.
3661                None => {
3662                    log::trace!("adding unique package {}", from.name);
3663                    continue;
3664                }
3665            };
3666            log::trace!("merging duplicate package {}", from.name);
3667
3668            self.build_package(from_id, into_id).with_context(|| {
3669                format!("failed to merge package `{}` into existing copy", from.name)
3670            })?;
3671        }
3672
3673        Ok(())
3674    }
3675
3676    fn build_package(&mut self, from_id: PackageId, into_id: PackageId) -> Result<()> {
3677        let prev = self.package_map.insert(from_id, into_id);
3678        assert!(prev.is_none());
3679
3680        let from = &self.from.packages[from_id];
3681        let into = &self.into.packages[into_id];
3682
3683        // If an interface is present in `from_id` but not present in `into_id`
3684        // then it can be copied over wholesale. That copy is scheduled to
3685        // happen within the `self.interfaces_to_add` list.
3686        for (name, from_interface_id) in from.interfaces.iter() {
3687            let into_interface_id = match into.interfaces.get(name) {
3688                Some(id) => *id,
3689                None => {
3690                    log::trace!("adding unique interface {}", name);
3691                    self.interfaces_to_add
3692                        .push((name.clone(), into_id, *from_interface_id));
3693                    continue;
3694                }
3695            };
3696
3697            log::trace!("merging duplicate interfaces {}", name);
3698            self.build_interface(*from_interface_id, into_interface_id)
3699                .with_context(|| format!("failed to merge interface `{name}`"))?;
3700        }
3701
3702        for (name, from_world_id) in from.worlds.iter() {
3703            let into_world_id = match into.worlds.get(name) {
3704                Some(id) => *id,
3705                None => {
3706                    log::trace!("adding unique world {}", name);
3707                    self.worlds_to_add
3708                        .push((name.clone(), into_id, *from_world_id));
3709                    continue;
3710                }
3711            };
3712
3713            log::trace!("merging duplicate worlds {}", name);
3714            self.build_world(*from_world_id, into_world_id)
3715                .with_context(|| format!("failed to merge world `{name}`"))?;
3716        }
3717
3718        Ok(())
3719    }
3720
3721    fn build_interface(&mut self, from_id: InterfaceId, into_id: InterfaceId) -> Result<()> {
3722        let prev = self.interface_map.insert(from_id, into_id);
3723        assert!(prev.is_none());
3724
3725        let from_interface = &self.from.interfaces[from_id];
3726        let into_interface = &self.into.interfaces[into_id];
3727
3728        // Unlike documents/interfaces above if an interface in `from`
3729        // differs from the interface in `into` then that's considered an
3730        // error. Changing interfaces can reflect changes in imports/exports
3731        // which may not be expected so it's currently required that all
3732        // interfaces, when merged, exactly match.
3733        //
3734        // One case to consider here, for example, is that if a world in
3735        // `into` exports the interface `into_id` then if `from_id` were to
3736        // add more items into `into` then it would unexpectedly require more
3737        // items to be exported which may not work. In an import context this
3738        // might work since it's "just more items available for import", but
3739        // for now a conservative route of "interfaces must match" is taken.
3740
3741        for (name, from_type_id) in from_interface.types.iter() {
3742            let into_type_id = *into_interface
3743                .types
3744                .get(name)
3745                .ok_or_else(|| anyhow!("expected type `{name}` to be present"))?;
3746            let prev = self.type_map.insert(*from_type_id, into_type_id);
3747            assert!(prev.is_none());
3748
3749            self.build_type_id(*from_type_id, into_type_id)
3750                .with_context(|| format!("mismatch in type `{name}`"))?;
3751        }
3752
3753        for (name, from_func) in from_interface.functions.iter() {
3754            let into_func = match into_interface.functions.get(name) {
3755                Some(func) => func,
3756                None => bail!("expected function `{name}` to be present"),
3757            };
3758            self.build_function(from_func, into_func)
3759                .with_context(|| format!("mismatch in function `{name}`"))?;
3760        }
3761
3762        Ok(())
3763    }
3764
3765    fn build_type_id(&mut self, from_id: TypeId, into_id: TypeId) -> Result<()> {
3766        // FIXME: ideally the types should be "structurally
3767        // equal" but that's not trivial to do in the face of
3768        // resources.
3769        let _ = from_id;
3770        let _ = into_id;
3771        Ok(())
3772    }
3773
3774    fn build_type(&mut self, from_ty: &Type, into_ty: &Type) -> Result<()> {
3775        match (from_ty, into_ty) {
3776            (Type::Id(from), Type::Id(into)) => {
3777                self.build_type_id(*from, *into)?;
3778            }
3779            (from, into) if from != into => bail!("different kinds of types"),
3780            _ => {}
3781        }
3782        Ok(())
3783    }
3784
3785    fn build_function(&mut self, from_func: &Function, into_func: &Function) -> Result<()> {
3786        if from_func.name != into_func.name {
3787            bail!(
3788                "different function names `{}` and `{}`",
3789                from_func.name,
3790                into_func.name
3791            );
3792        }
3793        match (&from_func.kind, &into_func.kind) {
3794            (FunctionKind::Freestanding, FunctionKind::Freestanding) => {}
3795            (FunctionKind::AsyncFreestanding, FunctionKind::AsyncFreestanding) => {}
3796
3797            (FunctionKind::Method(from), FunctionKind::Method(into))
3798            | (FunctionKind::Static(from), FunctionKind::Static(into))
3799            | (FunctionKind::AsyncMethod(from), FunctionKind::AsyncMethod(into))
3800            | (FunctionKind::AsyncStatic(from), FunctionKind::AsyncStatic(into))
3801            | (FunctionKind::Constructor(from), FunctionKind::Constructor(into)) => {
3802                self.build_type_id(*from, *into)
3803                    .context("different function kind types")?;
3804            }
3805
3806            (FunctionKind::Method(_), _)
3807            | (FunctionKind::Constructor(_), _)
3808            | (FunctionKind::Static(_), _)
3809            | (FunctionKind::Freestanding, _)
3810            | (FunctionKind::AsyncFreestanding, _)
3811            | (FunctionKind::AsyncMethod(_), _)
3812            | (FunctionKind::AsyncStatic(_), _) => {
3813                bail!("different function kind types")
3814            }
3815        }
3816
3817        if from_func.params.len() != into_func.params.len() {
3818            bail!("different number of function parameters");
3819        }
3820        for ((from_name, from_ty), (into_name, into_ty)) in
3821            from_func.params.iter().zip(&into_func.params)
3822        {
3823            if from_name != into_name {
3824                bail!("different function parameter names: {from_name} != {into_name}");
3825            }
3826            self.build_type(from_ty, into_ty)
3827                .with_context(|| format!("different function parameter types for `{from_name}`"))?;
3828        }
3829        match (&from_func.result, &into_func.result) {
3830            (Some(from_ty), Some(into_ty)) => {
3831                self.build_type(from_ty, into_ty)
3832                    .context("different function result types")?;
3833            }
3834            (None, None) => {}
3835            (Some(_), None) | (None, Some(_)) => bail!("different number of function results"),
3836        }
3837        Ok(())
3838    }
3839
3840    fn build_world(&mut self, from_id: WorldId, into_id: WorldId) -> Result<()> {
3841        let prev = self.world_map.insert(from_id, into_id);
3842        assert!(prev.is_none());
3843
3844        let from_world = &self.from.worlds[from_id];
3845        let into_world = &self.into.worlds[into_id];
3846
3847        // Same as interfaces worlds are expected to exactly match to avoid
3848        // unexpectedly changing a particular component's view of imports and
3849        // exports.
3850        //
3851        // FIXME: this should probably share functionality with
3852        // `Resolve::merge_worlds` to support adding imports but not changing
3853        // exports.
3854
3855        if from_world.imports.len() != into_world.imports.len() {
3856            bail!("world contains different number of imports than expected");
3857        }
3858        if from_world.exports.len() != into_world.exports.len() {
3859            bail!("world contains different number of exports than expected");
3860        }
3861
3862        for (from_name, from) in from_world.imports.iter() {
3863            let into_name = MergeMap::map_name(from_name, &self.interface_map);
3864            let name_str = self.from.name_world_key(from_name);
3865            let into = into_world
3866                .imports
3867                .get(&into_name)
3868                .ok_or_else(|| anyhow!("import `{name_str}` not found in target world"))?;
3869            self.match_world_item(from, into)
3870                .with_context(|| format!("import `{name_str}` didn't match target world"))?;
3871        }
3872
3873        for (from_name, from) in from_world.exports.iter() {
3874            let into_name = MergeMap::map_name(from_name, &self.interface_map);
3875            let name_str = self.from.name_world_key(from_name);
3876            let into = into_world
3877                .exports
3878                .get(&into_name)
3879                .ok_or_else(|| anyhow!("export `{name_str}` not found in target world"))?;
3880            self.match_world_item(from, into)
3881                .with_context(|| format!("export `{name_str}` didn't match target world"))?;
3882        }
3883
3884        Ok(())
3885    }
3886
3887    fn map_name(
3888        from_name: &WorldKey,
3889        interface_map: &HashMap<InterfaceId, InterfaceId>,
3890    ) -> WorldKey {
3891        match from_name {
3892            WorldKey::Name(s) => WorldKey::Name(s.clone()),
3893            WorldKey::Interface(id) => {
3894                WorldKey::Interface(interface_map.get(id).copied().unwrap_or(*id))
3895            }
3896        }
3897    }
3898
3899    fn match_world_item(&mut self, from: &WorldItem, into: &WorldItem) -> Result<()> {
3900        match (from, into) {
3901            (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
3902                match (
3903                    &self.from.interfaces[*from].name,
3904                    &self.into.interfaces[*into].name,
3905                ) {
3906                    // If one interface is unnamed then they must both be
3907                    // unnamed and they must both have the same structure for
3908                    // now.
3909                    (None, None) => self.build_interface(*from, *into)?,
3910
3911                    // Otherwise both interfaces must be named and they must
3912                    // have been previously found to be equivalent. Note that
3913                    // if either is unnamed it won't be present in
3914                    // `interface_map` so this'll return an error.
3915                    _ => {
3916                        if self.interface_map.get(&from) != Some(&into) {
3917                            bail!("interfaces are not the same");
3918                        }
3919                    }
3920                }
3921            }
3922            (WorldItem::Function(from), WorldItem::Function(into)) => {
3923                let _ = (from, into);
3924                // FIXME: should assert an check that `from` structurally
3925                // matches `into`
3926            }
3927            (WorldItem::Type(from), WorldItem::Type(into)) => {
3928                // FIXME: should assert an check that `from` structurally
3929                // matches `into`
3930                let prev = self.type_map.insert(*from, *into);
3931                assert!(prev.is_none());
3932            }
3933
3934            (WorldItem::Interface { .. }, _)
3935            | (WorldItem::Function(_), _)
3936            | (WorldItem::Type(_), _) => {
3937                bail!("world items do not have the same type")
3938            }
3939        }
3940        Ok(())
3941    }
3942}
3943
3944/// Updates stability annotations when merging `from` into `into`.
3945///
3946/// This is done to keep up-to-date stability information if possible.
3947/// Components for example don't carry stability information but WIT does so
3948/// this tries to move from "unknown" to stable/unstable if possible.
3949fn update_stability(from: &Stability, into: &mut Stability) -> Result<()> {
3950    // If `from` is unknown or the two stability annotations are equal then
3951    // there's nothing to do here.
3952    if from == into || from.is_unknown() {
3953        return Ok(());
3954    }
3955    // Otherwise if `into` is unknown then inherit the stability listed in
3956    // `from`.
3957    if into.is_unknown() {
3958        *into = from.clone();
3959        return Ok(());
3960    }
3961
3962    // Failing all that this means that the two attributes are different so
3963    // generate an error.
3964    bail!("mismatch in stability from '{:?}' to '{:?}'", from, into)
3965}
3966
3967fn merge_include_stability(
3968    from: &Stability,
3969    into: &mut Stability,
3970    is_external_include: bool,
3971) -> Result<()> {
3972    if is_external_include && from.is_stable() {
3973        log::trace!("dropped stability from external package");
3974        *into = Stability::Unknown;
3975        return Ok(());
3976    }
3977
3978    return update_stability(from, into);
3979}
3980
3981/// An error that can be returned during "world elaboration" during various
3982/// [`Resolve`] operations.
3983///
3984/// Methods on [`Resolve`] which mutate its internals, such as
3985/// [`Resolve::push_dir`] or [`Resolve::importize`] can fail if `world` imports
3986/// in WIT packages are invalid. This error indicates one of these situations
3987/// where an invalid dependency graph between imports and exports are detected.
3988///
3989/// Note that at this time this error is subtle and not easy to understand, and
3990/// work needs to be done to explain this better and additionally provide a
3991/// better error message. For now though this type enables callers to test for
3992/// the exact kind of error emitted.
3993#[derive(Debug, Clone)]
3994pub struct InvalidTransitiveDependency(String);
3995
3996impl fmt::Display for InvalidTransitiveDependency {
3997    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3998        write!(
3999            f,
4000            "interface `{}` transitively depends on an interface in \
4001             incompatible ways",
4002            self.0
4003        )
4004    }
4005}
4006
4007impl std::error::Error for InvalidTransitiveDependency {}
4008
4009#[cfg(test)]
4010mod tests {
4011    use crate::Resolve;
4012    use anyhow::Result;
4013
4014    #[test]
4015    fn select_world() -> Result<()> {
4016        let mut resolve = Resolve::default();
4017        resolve.push_str(
4018            "test.wit",
4019            r#"
4020                package foo:bar@0.1.0;
4021
4022                world foo {}
4023            "#,
4024        )?;
4025        resolve.push_str(
4026            "test.wit",
4027            r#"
4028                package foo:baz@0.1.0;
4029
4030                world foo {}
4031            "#,
4032        )?;
4033        resolve.push_str(
4034            "test.wit",
4035            r#"
4036                package foo:baz@0.2.0;
4037
4038                world foo {}
4039            "#,
4040        )?;
4041
4042        let dummy = resolve.push_str(
4043            "test.wit",
4044            r#"
4045                package foo:dummy;
4046
4047                world foo {}
4048            "#,
4049        )?;
4050
4051        assert!(resolve.select_world(dummy, None).is_ok());
4052        assert!(resolve.select_world(dummy, Some("xx")).is_err());
4053        assert!(resolve.select_world(dummy, Some("")).is_err());
4054        assert!(resolve.select_world(dummy, Some("foo:bar/foo")).is_ok());
4055        assert!(resolve
4056            .select_world(dummy, Some("foo:bar/foo@0.1.0"))
4057            .is_ok());
4058        assert!(resolve.select_world(dummy, Some("foo:baz/foo")).is_err());
4059        assert!(resolve
4060            .select_world(dummy, Some("foo:baz/foo@0.1.0"))
4061            .is_ok());
4062        assert!(resolve
4063            .select_world(dummy, Some("foo:baz/foo@0.2.0"))
4064            .is_ok());
4065        Ok(())
4066    }
4067}