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