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