1use alloc::borrow::ToOwned;
2use alloc::collections::BTreeMap;
3use alloc::string::{String, ToString};
4use alloc::vec::Vec;
5use alloc::{format, vec};
6use core::cmp::Ordering;
7use core::fmt;
8use core::mem;
9
10use crate::*;
11use anyhow::{Context, Result, anyhow, bail};
12#[cfg(not(feature = "std"))]
13use hashbrown::hash_map::Entry;
14use id_arena::{Arena, Id};
15use semver::Version;
16#[cfg(feature = "serde")]
17use serde_derive::Serialize;
18#[cfg(feature = "std")]
19use std::collections::hash_map::Entry;
20
21use crate::ast::lex::Span;
22use crate::ast::{ParsedUsePath, parse_use_path};
23#[cfg(feature = "serde")]
24use crate::serde_::{serialize_arena, serialize_id_map};
25use crate::{
26 AstItem, Docs, Error, Function, FunctionKind, Handle, IncludeName, Interface, InterfaceId,
27 LiftLowerAbi, ManglingAndAbi, PackageName, PackageNotFoundError, SourceMap, Stability, Type,
28 TypeDef, TypeDefKind, TypeId, TypeIdVisitor, TypeOwner, UnresolvedPackage,
29 UnresolvedPackageGroup, World, WorldId, WorldItem, WorldKey,
30};
31
32pub use clone::CloneMaps;
33
34mod clone;
35
36#[cfg(feature = "std")]
37mod fs;
38#[cfg(feature = "std")]
39pub use fs::PackageSourceMap;
40
41#[derive(Default, Clone, Debug)]
55#[cfg_attr(feature = "serde", derive(Serialize))]
56pub struct Resolve {
57 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
62 pub worlds: Arena<World>,
63
64 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
69 pub interfaces: Arena<Interface>,
70
71 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
77 pub types: Arena<TypeDef>,
78
79 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
84 pub packages: Arena<Package>,
85
86 #[cfg_attr(feature = "serde", serde(skip))]
88 pub package_names: IndexMap<PackageName, PackageId>,
89
90 #[cfg_attr(feature = "serde", serde(skip))]
97 pub features: IndexSet<String>,
98
99 #[cfg_attr(feature = "serde", serde(skip))]
101 pub all_features: bool,
102
103 #[cfg_attr(feature = "serde", serde(skip))]
105 pub source_map: SourceMap,
106}
107
108#[derive(Clone, Debug)]
114#[cfg_attr(feature = "serde", derive(Serialize))]
115pub struct Package {
116 pub name: PackageName,
118
119 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
121 pub docs: Docs,
122
123 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
126 pub interfaces: IndexMap<String, InterfaceId>,
127
128 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
130 pub worlds: IndexMap<String, WorldId>,
131}
132
133pub type PackageId = Id<Package>;
134
135#[derive(Clone, Debug)]
137pub struct PackageSources {
138 sources: Vec<Vec<String>>,
139 package_id_to_source_map_idx: BTreeMap<PackageId, usize>,
140}
141
142impl PackageSources {
143 pub fn from_single_source(package_id: PackageId, source: &str) -> Self {
144 Self {
145 sources: vec![vec![source.to_owned()]],
146 package_id_to_source_map_idx: BTreeMap::from([(package_id, 0)]),
147 }
148 }
149
150 pub fn from_source_maps(
151 source_maps: Vec<SourceMap>,
152 package_id_to_source_map_idx: BTreeMap<PackageId, usize>,
153 ) -> PackageSources {
154 for (package_id, idx) in &package_id_to_source_map_idx {
155 if *idx >= source_maps.len() {
156 panic!(
157 "Invalid source map index: {}, package id: {:?}, source maps size: {}",
158 idx,
159 package_id,
160 source_maps.len()
161 )
162 }
163 }
164
165 Self {
166 sources: source_maps
167 .into_iter()
168 .map(|source_map| source_map.source_names().map(|s| s.to_owned()).collect())
169 .collect(),
170 package_id_to_source_map_idx,
171 }
172 }
173
174 pub fn source_names(&self) -> impl Iterator<Item = &str> {
176 self.sources
177 .iter()
178 .flatten()
179 .map(|s| s.as_str())
180 .collect::<IndexSet<&str>>()
181 .into_iter()
182 }
183
184 pub fn package_source_names(&self, id: PackageId) -> Option<impl Iterator<Item = &str>> {
186 self.package_id_to_source_map_idx
187 .get(&id)
188 .map(|&idx| self.sources[idx].iter().map(|s| s.as_str()))
189 }
190}
191
192fn visit<'a>(
194 pkg: &'a UnresolvedPackage,
195 pkg_details_map: &'a BTreeMap<PackageName, (UnresolvedPackage, usize)>,
196 order: &mut IndexSet<PackageName>,
197 visiting: &mut HashSet<&'a PackageName>,
198 source_maps: &[SourceMap],
199) -> Result<()> {
200 if order.contains(&pkg.name) {
201 return Ok(());
202 }
203
204 match pkg_details_map.get(&pkg.name) {
205 Some(pkg_details) => {
206 let (_, source_maps_index) = pkg_details;
207 source_maps[*source_maps_index].rewrite_error(|| {
208 for (i, (dep, _)) in pkg.foreign_deps.iter().enumerate() {
209 let span = pkg.foreign_dep_spans[i];
210 if !visiting.insert(dep) {
211 bail!(Error::new(span, "package depends on itself"));
212 }
213 if let Some(dep) = pkg_details_map.get(dep) {
214 let (dep_pkg, _) = dep;
215 visit(dep_pkg, pkg_details_map, order, visiting, source_maps)?;
216 }
217 assert!(visiting.remove(dep));
218 }
219 assert!(order.insert(pkg.name.clone()));
220 Ok(())
221 })
222 }
223 None => panic!("No pkg_details found for package when doing topological sort"),
224 }
225}
226
227impl Resolve {
228 pub fn new() -> Resolve {
230 Resolve::default()
231 }
232
233 fn sort_unresolved_packages(
254 &mut self,
255 main: UnresolvedPackageGroup,
256 deps: Vec<UnresolvedPackageGroup>,
257 ) -> Result<(PackageId, PackageSources)> {
258 let mut pkg_details_map = BTreeMap::new();
259 let mut source_maps = Vec::new();
260
261 let mut insert = |group: UnresolvedPackageGroup| {
262 let UnresolvedPackageGroup {
263 main,
264 nested,
265 source_map,
266 } = group;
267 let i = source_maps.len();
268 source_maps.push(source_map);
269
270 for pkg in nested.into_iter().chain([main]) {
271 let name = pkg.name.clone();
272 let my_span = pkg.package_name_span;
273 let (prev_pkg, prev_i) = match pkg_details_map.insert(name.clone(), (pkg, i)) {
274 Some(pair) => pair,
275 None => continue,
276 };
277 let loc1 = source_maps[i].render_location(my_span);
278 let loc2 = source_maps[prev_i].render_location(prev_pkg.package_name_span);
279 bail!(
280 "\
281package {name} is defined in two different locations:\n\
282 * {loc1}\n\
283 * {loc2}\n\
284 "
285 )
286 }
287 Ok(())
288 };
289
290 let main_name = main.main.name.clone();
291 insert(main)?;
292 for dep in deps {
293 insert(dep)?;
294 }
295
296 let mut order = IndexSet::default();
300 {
301 let mut visiting = HashSet::new();
302 for pkg_details in pkg_details_map.values() {
303 let (pkg, _) = pkg_details;
304 visit(
305 pkg,
306 &pkg_details_map,
307 &mut order,
308 &mut visiting,
309 &source_maps,
310 )?;
311 }
312 }
313
314 let mut package_id_to_source_map_idx = BTreeMap::new();
317 let mut main_pkg_id = None;
318 let mut source_map_offsets: HashMap<usize, u32> = HashMap::new();
319 for name in order {
320 let (pkg, source_map_index) = pkg_details_map.remove(&name).unwrap();
321 let source_map = &source_maps[source_map_index];
322 let is_main = pkg.name == main_name;
323
324 let span_offset = *source_map_offsets
326 .entry(source_map_index)
327 .or_insert_with(|| self.push_source_map(source_map.clone()));
328
329 let id = self.push(pkg, span_offset)?;
330 if is_main {
331 assert!(main_pkg_id.is_none());
332 main_pkg_id = Some(id);
333 }
334 package_id_to_source_map_idx.insert(id, source_map_index);
335 }
336
337 Ok((
338 main_pkg_id.unwrap(),
339 PackageSources::from_source_maps(source_maps, package_id_to_source_map_idx),
340 ))
341 }
342
343 pub fn push_source_map(&mut self, source_map: SourceMap) -> u32 {
350 self.source_map.append(source_map)
351 }
352
353 pub fn push(
368 &mut self,
369 mut unresolved: UnresolvedPackage,
370 span_offset: u32,
371 ) -> Result<PackageId> {
372 unresolved.adjust_spans(span_offset);
373 let ret = Remap::default().append(self, unresolved);
374 if ret.is_ok() {
375 #[cfg(debug_assertions)]
376 self.assert_valid();
377 }
378 self.source_map.rewrite_error(|| ret)
379 }
380
381 pub fn push_group(&mut self, unresolved_group: UnresolvedPackageGroup) -> Result<PackageId> {
390 let (pkg_id, _) = self.sort_unresolved_packages(unresolved_group, Vec::new())?;
391 Ok(pkg_id)
392 }
393
394 pub fn push_source(&mut self, path: &str, contents: &str) -> Result<PackageId> {
400 let mut map = SourceMap::default();
401 map.push_str(path, contents);
402 self.push_group(
403 map.parse()
404 .map_err(|(map, e)| anyhow::anyhow!("{}", e.highlight(&map)))?,
405 )
406 }
407
408 pub fn render_location(&self, span: Span) -> String {
410 self.source_map.render_location(span)
411 }
412
413 pub fn all_bits_valid(&self, ty: &Type) -> bool {
414 match ty {
415 Type::U8
416 | Type::S8
417 | Type::U16
418 | Type::S16
419 | Type::U32
420 | Type::S32
421 | Type::U64
422 | Type::S64
423 | Type::F32
424 | Type::F64 => true,
425
426 Type::Bool | Type::Char | Type::String | Type::ErrorContext => false,
427
428 Type::Id(id) => match &self.types[*id].kind {
429 TypeDefKind::List(_)
430 | TypeDefKind::Map(_, _)
431 | TypeDefKind::Variant(_)
432 | TypeDefKind::Enum(_)
433 | TypeDefKind::Option(_)
434 | TypeDefKind::Result(_)
435 | TypeDefKind::Future(_)
436 | TypeDefKind::Stream(_) => false,
437 TypeDefKind::Type(t) | TypeDefKind::FixedLengthList(t, ..) => {
438 self.all_bits_valid(t)
439 }
440
441 TypeDefKind::Handle(h) => match h {
442 crate::Handle::Own(_) => true,
443 crate::Handle::Borrow(_) => true,
444 },
445
446 TypeDefKind::Resource => false,
447 TypeDefKind::Record(r) => r.fields.iter().all(|f| self.all_bits_valid(&f.ty)),
448 TypeDefKind::Tuple(t) => t.types.iter().all(|t| self.all_bits_valid(t)),
449
450 TypeDefKind::Flags(_) => false,
454
455 TypeDefKind::Unknown => unreachable!(),
456 },
457 }
458 }
459
460 pub fn merge(&mut self, resolve: Resolve) -> Result<Remap> {
472 log::trace!(
473 "merging {} packages into {} packages",
474 resolve.packages.len(),
475 self.packages.len()
476 );
477
478 let mut map = MergeMap::new(&resolve, &self);
479 map.build()?;
480 let MergeMap {
481 package_map,
482 interface_map,
483 type_map,
484 world_map,
485 interfaces_to_add,
486 worlds_to_add,
487 ..
488 } = map;
489
490 let mut remap = Remap::default();
509 let Resolve {
510 types,
511 worlds,
512 interfaces,
513 packages,
514 package_names,
515 features: _,
516 source_map,
517 ..
518 } = resolve;
519
520 let span_offset = self.source_map.append(source_map);
521
522 let mut moved_types = Vec::new();
523 for (id, mut ty) in types {
524 let new_id = match type_map.get(&id).copied() {
525 Some(id) => {
526 update_stability(&ty.stability, &mut self.types[id].stability)?;
527 id
528 }
529 None => {
530 log::debug!("moving type {:?}", ty.name);
531 moved_types.push(id);
532 remap.update_typedef(self, &mut ty, Default::default())?;
533 ty.adjust_spans(span_offset);
534 self.types.alloc(ty)
535 }
536 };
537 assert_eq!(remap.types.len(), id.index());
538 remap.types.push(Some(new_id));
539 }
540
541 let mut moved_interfaces = Vec::new();
542 for (id, mut iface) in interfaces {
543 let new_id = match interface_map.get(&id).copied() {
544 Some(into_id) => {
545 update_stability(&iface.stability, &mut self.interfaces[into_id].stability)?;
546
547 for (name, from_type_id) in iface.types.iter() {
553 if self.interfaces[into_id].types.contains_key(name) {
554 continue;
555 }
556 let new_type_id = remap.map_type(*from_type_id, Default::default())?;
557 self.interfaces[into_id]
558 .types
559 .insert(name.clone(), new_type_id);
560 }
561
562 let extra_funcs: Vec<_> = iface
566 .functions
567 .into_iter()
568 .filter(|(name, _)| {
569 !self.interfaces[into_id]
570 .functions
571 .contains_key(name.as_str())
572 })
573 .collect();
574 for (name, mut func) in extra_funcs {
575 remap.update_function(self, &mut func, Default::default())?;
576 func.adjust_spans(span_offset);
577 self.interfaces[into_id].functions.insert(name, func);
578 }
579
580 into_id
581 }
582 None => {
583 log::debug!("moving interface {:?}", iface.name);
584 moved_interfaces.push(id);
585 remap.update_interface(self, &mut iface)?;
586 iface.adjust_spans(span_offset);
587 self.interfaces.alloc(iface)
588 }
589 };
590 assert_eq!(remap.interfaces.len(), id.index());
591 remap.interfaces.push(Some(new_id));
592 }
593
594 let mut moved_worlds = Vec::new();
595 for (id, mut world) in worlds {
596 let new_id = match world_map.get(&id).copied() {
597 Some(world_id) => {
598 update_stability(&world.stability, &mut self.worlds[world_id].stability)?;
599 for from_import in world.imports.iter() {
600 Resolve::update_world_imports_stability(
601 from_import,
602 &mut self.worlds[world_id].imports,
603 &interface_map,
604 )?;
605 }
606 for from_export in world.exports.iter() {
607 Resolve::update_world_imports_stability(
608 from_export,
609 &mut self.worlds[world_id].exports,
610 &interface_map,
611 )?;
612 }
613 world_id
614 }
615 None => {
616 log::debug!("moving world {}", world.name);
617 moved_worlds.push(id);
618 let mut update = |map: &mut IndexMap<WorldKey, WorldItem>| -> Result<_> {
619 for (mut name, mut item) in mem::take(map) {
620 remap.update_world_key(&mut name, Default::default())?;
621 match &mut item {
622 WorldItem::Function(f) => {
623 remap.update_function(self, f, Default::default())?
624 }
625 WorldItem::Interface { id, .. } => {
626 *id = remap.map_interface(*id, Default::default())?
627 }
628 WorldItem::Type { id, .. } => {
629 *id = remap.map_type(*id, Default::default())?
630 }
631 }
632 map.insert(name, item);
633 }
634 Ok(())
635 };
636 update(&mut world.imports)?;
637 update(&mut world.exports)?;
638 world.adjust_spans(span_offset);
639 self.worlds.alloc(world)
640 }
641 };
642 assert_eq!(remap.worlds.len(), id.index());
643 remap.worlds.push(Some(new_id));
644 }
645
646 for (id, mut pkg) in packages {
647 let new_id = match package_map.get(&id).copied() {
648 Some(id) => id,
649 None => {
650 for (_, id) in pkg.interfaces.iter_mut() {
651 *id = remap.map_interface(*id, Default::default())?;
652 }
653 for (_, id) in pkg.worlds.iter_mut() {
654 *id = remap.map_world(*id, Default::default())?;
655 }
656 self.packages.alloc(pkg)
657 }
658 };
659 assert_eq!(remap.packages.len(), id.index());
660 remap.packages.push(new_id);
661 }
662
663 for (name, id) in package_names {
664 let id = remap.packages[id.index()];
665 if let Some(prev) = self.package_names.insert(name, id) {
666 assert_eq!(prev, id);
667 }
668 }
669
670 for id in moved_worlds {
678 let id = remap.map_world(id, Default::default())?;
679 if let Some(pkg) = self.worlds[id].package.as_mut() {
680 *pkg = remap.packages[pkg.index()];
681 }
682 }
683 for id in moved_interfaces {
684 let id = remap.map_interface(id, Default::default())?;
685 if let Some(pkg) = self.interfaces[id].package.as_mut() {
686 *pkg = remap.packages[pkg.index()];
687 }
688 }
689 for id in moved_types {
690 let id = remap.map_type(id, Default::default())?;
691 match &mut self.types[id].owner {
692 TypeOwner::Interface(id) => *id = remap.map_interface(*id, Default::default())?,
693 TypeOwner::World(id) => *id = remap.map_world(*id, Default::default())?,
694 TypeOwner::None => {}
695 }
696 }
697
698 for (name, pkg, iface) in interfaces_to_add {
703 let prev = self.packages[pkg]
704 .interfaces
705 .insert(name, remap.map_interface(iface, Default::default())?);
706 assert!(prev.is_none());
707 }
708 for (name, pkg, world) in worlds_to_add {
709 let prev = self.packages[pkg]
710 .worlds
711 .insert(name, remap.map_world(world, Default::default())?);
712 assert!(prev.is_none());
713 }
714
715 log::trace!("now have {} packages", self.packages.len());
716
717 let world_ids: Vec<_> = self.worlds.iter().map(|(id, _)| id).collect();
721 for world_id in world_ids {
722 self.elaborate_world(world_id)?;
723 }
724
725 #[cfg(debug_assertions)]
726 self.assert_valid();
727 Ok(remap)
728 }
729
730 fn update_world_imports_stability(
731 from_item: (&WorldKey, &WorldItem),
732 into_items: &mut IndexMap<WorldKey, WorldItem>,
733 interface_map: &HashMap<Id<Interface>, Id<Interface>>,
734 ) -> Result<()> {
735 match from_item.0 {
736 WorldKey::Name(_) => {
737 Ok(())
739 }
740 key @ WorldKey::Interface(_) => {
741 let new_key = MergeMap::map_name(key, interface_map);
742 if let Some(into) = into_items.get_mut(&new_key) {
743 match (from_item.1, into) {
744 (
745 WorldItem::Interface {
746 id: aid,
747 stability: astability,
748 ..
749 },
750 WorldItem::Interface {
751 id: bid,
752 stability: bstability,
753 ..
754 },
755 ) => {
756 let aid = interface_map.get(aid).copied().unwrap_or(*aid);
757 assert_eq!(aid, *bid);
758 update_stability(astability, bstability)?;
759 Ok(())
760 }
761 _ => unreachable!(),
762 }
763 } else {
764 unreachable!()
767 }
768 }
769 }
770 }
771
772 pub fn merge_worlds(
787 &mut self,
788 from: WorldId,
789 into: WorldId,
790 clone_maps: &mut CloneMaps,
791 ) -> Result<()> {
792 let mut new_imports = Vec::new();
793 let mut new_exports = Vec::new();
794
795 let from_world = &self.worlds[from];
796 let into_world = &self.worlds[into];
797
798 log::trace!("merging {} into {}", from_world.name, into_world.name);
799
800 for (name, from_import) in from_world.imports.iter() {
808 let name_str = self.name_world_key(name);
809 match into_world.imports.get(name) {
810 Some(into_import) => {
811 log::trace!("info/from shared import on `{name_str}`");
812 self.merge_world_item(from_import, into_import)
813 .with_context(|| format!("failed to merge world import {name_str}"))?;
814 }
815 None => {
816 log::trace!("new import: `{name_str}`");
817 new_imports.push((name.clone(), from_import.clone()));
818 }
819 }
820 }
821
822 let mut must_be_imported = HashMap::new();
829 for (key, export) in into_world.exports.iter() {
830 for dep in self.world_item_direct_deps(export) {
831 if into_world.exports.contains_key(&WorldKey::Interface(dep)) {
832 continue;
833 }
834 self.foreach_interface_dep(dep, &mut |id| {
835 must_be_imported.insert(id, key.clone());
836 });
837 }
838 }
839
840 for (name, from_export) in from_world.exports.iter() {
843 let name_str = self.name_world_key(name);
844 match into_world.exports.get(name) {
845 Some(into_export) => {
846 log::trace!("info/from shared export on `{name_str}`");
847 self.merge_world_item(from_export, into_export)
848 .with_context(|| format!("failed to merge world export {name_str}"))?;
849 }
850 None => {
851 log::trace!("new export `{name_str}`");
852 self.ensure_can_add_world_export(
855 into_world,
856 name,
857 from_export,
858 &must_be_imported,
859 )
860 .with_context(|| {
861 format!("failed to add export `{}`", self.name_world_key(name))
862 })?;
863 new_exports.push((name.clone(), from_export.clone()));
864 }
865 }
866 }
867
868 let mut cloner = clone::Cloner::new(
882 self,
883 clone_maps,
884 TypeOwner::World(from),
885 TypeOwner::World(into),
886 );
887 cloner.register_world_type_overlap(from, into);
888 for (name, item) in new_imports.iter_mut().chain(&mut new_exports) {
889 cloner.world_item(name, item);
890 }
891
892 let into_world = &mut self.worlds[into];
894 for (name, import) in new_imports {
895 let prev = into_world.imports.insert(name, import);
896 assert!(prev.is_none());
897 }
898 for (name, export) in new_exports {
899 let prev = into_world.exports.insert(name, export);
900 assert!(prev.is_none());
901 }
902
903 #[cfg(debug_assertions)]
904 self.assert_valid();
905 Ok(())
906 }
907
908 fn merge_world_item(&self, from: &WorldItem, into: &WorldItem) -> Result<()> {
909 let mut map = MergeMap::new(self, self);
910 match (from, into) {
911 (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
912 if from == into {
917 return Ok(());
918 }
919
920 map.build_interface(*from, *into)
930 .context("failed to merge interfaces")?;
931 }
932
933 (WorldItem::Function(from), WorldItem::Function(into)) => {
936 map.build_function(from, into)
937 .context("failed to merge functions")?;
938 }
939 (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
940 map.build_type_id(*from, *into)
941 .context("failed to merge types")?;
942 }
943
944 (WorldItem::Interface { .. }, _)
946 | (WorldItem::Function { .. }, _)
947 | (WorldItem::Type { .. }, _) => {
948 bail!("different kinds of items");
949 }
950 }
951 assert!(map.interfaces_to_add.is_empty());
952 assert!(map.worlds_to_add.is_empty());
953 Ok(())
954 }
955
956 fn ensure_can_add_world_export(
968 &self,
969 into: &World,
970 name: &WorldKey,
971 item: &WorldItem,
972 must_be_imported: &HashMap<InterfaceId, WorldKey>,
973 ) -> Result<()> {
974 assert!(!into.exports.contains_key(name));
975 let name = self.name_world_key(name);
976
977 for dep in self.world_item_direct_deps(item) {
981 if into.exports.contains_key(&WorldKey::Interface(dep)) {
982 continue;
983 }
984 self.ensure_not_exported(into, dep)
985 .with_context(|| format!("failed validating export of `{name}`"))?;
986 }
987
988 if let WorldItem::Interface { id, .. } = item {
992 if let Some(export) = must_be_imported.get(id) {
993 let export_name = self.name_world_key(export);
994 bail!(
995 "export `{export_name}` depends on `{name}` \
996 previously as an import which will change meaning \
997 if `{name}` is added as an export"
998 );
999 }
1000 }
1001
1002 Ok(())
1003 }
1004
1005 fn ensure_not_exported(&self, world: &World, id: InterfaceId) -> Result<()> {
1006 let key = WorldKey::Interface(id);
1007 let name = self.name_world_key(&key);
1008 if world.exports.contains_key(&key) {
1009 bail!(
1010 "world exports `{name}` but it's also transitively used by an \
1011 import \
1012 which means that this is not valid"
1013 )
1014 }
1015 for dep in self.interface_direct_deps(id) {
1016 self.ensure_not_exported(world, dep)
1017 .with_context(|| format!("failed validating transitive import dep `{name}`"))?;
1018 }
1019 Ok(())
1020 }
1021
1022 fn world_item_direct_deps(&self, item: &WorldItem) -> impl Iterator<Item = InterfaceId> + '_ {
1028 let mut interface = None;
1029 let mut ty = None;
1030 match item {
1031 WorldItem::Function(_) => {}
1032 WorldItem::Type { id, .. } => ty = Some(*id),
1033 WorldItem::Interface { id, .. } => interface = Some(*id),
1034 }
1035
1036 interface
1037 .into_iter()
1038 .flat_map(move |id| self.interface_direct_deps(id))
1039 .chain(ty.and_then(|t| self.type_interface_dep(t)))
1040 }
1041
1042 fn foreach_interface_dep(&self, id: InterfaceId, f: &mut dyn FnMut(InterfaceId)) {
1046 self._foreach_interface_dep(id, f, &mut HashSet::new())
1047 }
1048
1049 fn _foreach_interface_dep(
1053 &self,
1054 id: InterfaceId,
1055 f: &mut dyn FnMut(InterfaceId),
1056 visited: &mut HashSet<InterfaceId>,
1057 ) {
1058 if !visited.insert(id) {
1059 return;
1060 }
1061 f(id);
1062 for dep in self.interface_direct_deps(id) {
1063 self._foreach_interface_dep(dep, f, visited);
1064 }
1065 }
1066
1067 pub fn id_of(&self, interface: InterfaceId) -> Option<String> {
1071 let interface = &self.interfaces[interface];
1072 Some(self.id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1073 }
1074
1075 pub fn canonicalized_id_of(&self, interface: InterfaceId) -> Option<String> {
1080 let interface = &self.interfaces[interface];
1081 Some(self.canonicalized_id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1082 }
1083
1084 fn rename_world(
1089 &mut self,
1090 world_id: WorldId,
1091 out_world_name: Option<String>,
1092 default_suffix: &str,
1093 ) {
1094 let world = &mut self.worlds[world_id];
1095 let pkg = &mut self.packages[world.package.unwrap()];
1096 pkg.worlds.shift_remove(&world.name);
1097 if let Some(name) = out_world_name {
1098 world.name = name.clone();
1099 pkg.worlds.insert(name, world_id);
1100 } else {
1101 world.name.push_str(default_suffix);
1102 pkg.worlds.insert(world.name.clone(), world_id);
1103 }
1104 }
1105
1106 pub fn importize(&mut self, world_id: WorldId, out_world_name: Option<String>) -> Result<()> {
1122 self.rename_world(world_id, out_world_name, "-importized");
1123
1124 let world = &mut self.worlds[world_id];
1127 world.imports.retain(|_, item| match item {
1128 WorldItem::Type { .. } => true,
1129 _ => false,
1130 });
1131
1132 for (name, export) in mem::take(&mut world.exports) {
1133 match (name.clone(), world.imports.insert(name, export)) {
1134 (_, None) => {}
1136
1137 (WorldKey::Name(name), Some(_)) => {
1139 bail!("world export `{name}` conflicts with import of same name");
1140 }
1141
1142 (WorldKey::Interface(_), _) => unreachable!(),
1145 }
1146 }
1147
1148 self.elaborate_world(world_id)?;
1151
1152 #[cfg(debug_assertions)]
1153 self.assert_valid();
1154 Ok(())
1155 }
1156
1157 pub fn exportize(
1176 &mut self,
1177 world_id: WorldId,
1178 out_world_name: Option<String>,
1179 filter: Option<&dyn Fn(&WorldKey, &WorldItem) -> bool>,
1180 ) -> Result<()> {
1181 self.rename_world(world_id, out_world_name, "-exportized");
1182
1183 let world = &mut self.worlds[world_id];
1184 world.exports.clear();
1185
1186 let old_imports = mem::take(&mut world.imports);
1187 for (name, import) in old_imports {
1188 let should_move = match &filter {
1189 Some(f) => f(&name, &import),
1190 None => true,
1191 };
1192 if should_move {
1193 world.exports.insert(name, import);
1194 } else {
1195 world.imports.insert(name, import);
1196 }
1197 }
1198
1199 self.elaborate_world(world_id)?;
1202
1203 #[cfg(debug_assertions)]
1204 self.assert_valid();
1205 Ok(())
1206 }
1207
1208 pub fn id_of_name(&self, pkg: PackageId, name: &str) -> String {
1210 let package = &self.packages[pkg];
1211 let mut base = String::new();
1212 base.push_str(&package.name.namespace);
1213 base.push_str(":");
1214 base.push_str(&package.name.name);
1215 base.push_str("/");
1216 base.push_str(name);
1217 if let Some(version) = &package.name.version {
1218 base.push_str(&format!("@{version}"));
1219 }
1220 base
1221 }
1222
1223 pub fn canonicalized_id_of_name(&self, pkg: PackageId, name: &str) -> String {
1229 let package = &self.packages[pkg];
1230 let mut base = String::new();
1231 base.push_str(&package.name.namespace);
1232 base.push_str(":");
1233 base.push_str(&package.name.name);
1234 base.push_str("/");
1235 base.push_str(name);
1236 if let Some(version) = &package.name.version {
1237 base.push_str("@");
1238 let string = PackageName::version_compat_track_string(version);
1239 base.push_str(&string);
1240 }
1241 base
1242 }
1243
1244 pub fn select_world(
1359 &self,
1360 main_packages: &[PackageId],
1361 world: Option<&str>,
1362 ) -> Result<WorldId> {
1363 let world_path = match world {
1365 Some(world) => Some(
1366 parse_use_path(world)
1367 .with_context(|| format!("failed to parse world specifier `{world}`"))?,
1368 ),
1369 None => None,
1370 };
1371
1372 match world_path {
1373 Some(world_path) => {
1375 let (pkg, world_name) = match (main_packages, world_path) {
1376 ([], _) => bail!("No main packages defined"),
1378
1379 ([main_package], ParsedUsePath::Name(name)) => (*main_package, name),
1381
1382 (_, ParsedUsePath::Name(_name)) => {
1384 bail!(
1385 "There are multiple main packages; a world must be explicitly chosen:{}",
1386 self.worlds
1387 .iter()
1388 .map(|world| format!(
1389 "\n {}",
1390 self.id_of_name(world.1.package.unwrap(), &world.1.name)
1391 ))
1392 .collect::<String>()
1393 )
1394 }
1395
1396 (_, ParsedUsePath::Package(pkg, world_name)) => {
1398 let pkg = match self.package_names.get(&pkg) {
1399 Some(pkg) => *pkg,
1400 None => {
1401 let mut candidates =
1402 self.package_names.iter().filter(|(name, _)| {
1403 pkg.version.is_none()
1404 && pkg.name == name.name
1405 && pkg.namespace == name.namespace
1406 && name.version.is_some()
1407 });
1408 let candidate = candidates.next();
1409 if let Some((c2, _)) = candidates.next() {
1410 let (c1, _) = candidate.unwrap();
1411 bail!(
1412 "package name `{pkg}` is available at both \
1413 versions {} and {} but which is not specified",
1414 c1.version.as_ref().unwrap(),
1415 c2.version.as_ref().unwrap(),
1416 );
1417 }
1418 match candidate {
1419 Some((_, id)) => *id,
1420 None => bail!("unknown package `{pkg}`"),
1421 }
1422 }
1423 };
1424 (pkg, world_name.to_string())
1425 }
1426 };
1427
1428 let pkg = &self.packages[pkg];
1430 pkg.worlds.get(&world_name).copied().ok_or_else(|| {
1431 anyhow!("World `{world_name}` not found in package `{}`", pkg.name)
1432 })
1433 }
1434
1435 None => match main_packages {
1437 [] => bail!("No main packages defined"),
1438
1439 [main_package] => {
1441 let pkg = &self.packages[*main_package];
1442 match pkg.worlds.len() {
1443 0 => bail!("The main package `{}` contains no worlds", pkg.name),
1444 1 => Ok(pkg.worlds[0]),
1445 _ => bail!(
1446 "There are multiple worlds in `{}`; one must be explicitly chosen:{}",
1447 pkg.name,
1448 pkg.worlds
1449 .values()
1450 .map(|world| format!(
1451 "\n {}",
1452 self.id_of_name(*main_package, &self.worlds[*world].name)
1453 ))
1454 .collect::<String>()
1455 ),
1456 }
1457 }
1458
1459 _ => {
1461 bail!(
1462 "There are multiple main packages; a world must be explicitly chosen:{}",
1463 self.worlds
1464 .iter()
1465 .map(|world| format!(
1466 "\n {}",
1467 self.id_of_name(world.1.package.unwrap(), &world.1.name)
1468 ))
1469 .collect::<String>()
1470 )
1471 }
1472 },
1473 }
1474 }
1475
1476 pub fn name_world_key(&self, key: &WorldKey) -> String {
1478 match key {
1479 WorldKey::Name(s) => s.to_string(),
1480 WorldKey::Interface(i) => self.id_of(*i).expect("unexpected anonymous interface"),
1481 }
1482 }
1483
1484 pub fn name_canonicalized_world_key(&self, key: &WorldKey) -> String {
1487 match key {
1488 WorldKey::Name(s) => s.to_string(),
1489 WorldKey::Interface(i) => self
1490 .canonicalized_id_of(*i)
1491 .expect("unexpected anonymous interface"),
1492 }
1493 }
1494
1495 pub fn type_interface_dep(&self, id: TypeId) -> Option<InterfaceId> {
1501 let ty = &self.types[id];
1502 let dep = match ty.kind {
1503 TypeDefKind::Type(Type::Id(id)) => id,
1504 _ => return None,
1505 };
1506 let other = &self.types[dep];
1507 if ty.owner == other.owner {
1508 None
1509 } else {
1510 match other.owner {
1511 TypeOwner::Interface(id) => Some(id),
1512 _ => unreachable!(),
1513 }
1514 }
1515 }
1516
1517 pub fn interface_direct_deps(&self, id: InterfaceId) -> impl Iterator<Item = InterfaceId> + '_ {
1527 self.interfaces[id]
1528 .types
1529 .iter()
1530 .filter_map(move |(_name, ty)| self.type_interface_dep(*ty))
1531 }
1532
1533 pub fn package_direct_deps(&self, id: PackageId) -> impl Iterator<Item = PackageId> + '_ {
1543 let pkg = &self.packages[id];
1544
1545 pkg.interfaces
1546 .iter()
1547 .flat_map(move |(_name, id)| self.interface_direct_deps(*id))
1548 .chain(pkg.worlds.iter().flat_map(move |(_name, id)| {
1549 let world = &self.worlds[*id];
1550 world
1551 .imports
1552 .iter()
1553 .chain(world.exports.iter())
1554 .filter_map(move |(_name, item)| match item {
1555 WorldItem::Interface { id, .. } => Some(*id),
1556 WorldItem::Function(_) => None,
1557 WorldItem::Type { id, .. } => self.type_interface_dep(*id),
1558 })
1559 }))
1560 .filter_map(move |iface_id| {
1561 let pkg = self.interfaces[iface_id].package?;
1562 if pkg == id { None } else { Some(pkg) }
1563 })
1564 }
1565
1566 pub fn topological_packages(&self) -> Vec<PackageId> {
1572 let mut pushed = vec![false; self.packages.len()];
1573 let mut order = Vec::new();
1574 for (id, _) in self.packages.iter() {
1575 self.build_topological_package_ordering(id, &mut pushed, &mut order);
1576 }
1577 order
1578 }
1579
1580 fn build_topological_package_ordering(
1581 &self,
1582 id: PackageId,
1583 pushed: &mut Vec<bool>,
1584 order: &mut Vec<PackageId>,
1585 ) {
1586 if pushed[id.index()] {
1587 return;
1588 }
1589 for dep in self.package_direct_deps(id) {
1590 self.build_topological_package_ordering(dep, pushed, order);
1591 }
1592 order.push(id);
1593 pushed[id.index()] = true;
1594 }
1595
1596 #[doc(hidden)]
1597 pub fn assert_valid(&self) {
1598 let mut package_interfaces = Vec::new();
1599 let mut package_worlds = Vec::new();
1600 for (id, pkg) in self.packages.iter() {
1601 let mut interfaces = HashSet::new();
1602 for (name, iface) in pkg.interfaces.iter() {
1603 assert!(interfaces.insert(*iface));
1604 let iface = &self.interfaces[*iface];
1605 assert_eq!(name, iface.name.as_ref().unwrap());
1606 assert_eq!(iface.package.unwrap(), id);
1607 }
1608 package_interfaces.push(pkg.interfaces.values().copied().collect::<HashSet<_>>());
1609 let mut worlds = HashSet::new();
1610 for (name, world) in pkg.worlds.iter() {
1611 assert!(worlds.insert(*world));
1612 assert_eq!(
1613 pkg.worlds.get_key_value(name),
1614 Some((name, world)),
1615 "`MutableKeys` impl may have been used to change a key's hash or equality"
1616 );
1617 let world = &self.worlds[*world];
1618 assert_eq!(*name, world.name);
1619 assert_eq!(world.package.unwrap(), id);
1620 }
1621 package_worlds.push(pkg.worlds.values().copied().collect::<HashSet<_>>());
1622 }
1623
1624 let mut interface_types = Vec::new();
1625 for (id, iface) in self.interfaces.iter() {
1626 assert!(self.packages.get(iface.package.unwrap()).is_some());
1627 if iface.name.is_some() {
1628 match iface.clone_of {
1629 Some(other) => {
1630 assert_eq!(iface.name, self.interfaces[other].name);
1631 }
1632 None => {
1633 assert!(package_interfaces[iface.package.unwrap().index()].contains(&id));
1634 }
1635 }
1636 }
1637
1638 for (name, ty) in iface.types.iter() {
1639 let ty = &self.types[*ty];
1640 assert_eq!(ty.name.as_ref(), Some(name));
1641 assert_eq!(ty.owner, TypeOwner::Interface(id));
1642 }
1643 interface_types.push(iface.types.values().copied().collect::<HashSet<_>>());
1644 for (name, f) in iface.functions.iter() {
1645 assert_eq!(*name, f.name);
1646 }
1647 }
1648
1649 let mut world_types = Vec::new();
1650 for (id, world) in self.worlds.iter() {
1651 log::debug!("validating world {}", &world.name);
1652 if let Some(package) = world.package {
1653 assert!(self.packages.get(package).is_some());
1654 assert!(package_worlds[package.index()].contains(&id));
1655 }
1656 assert!(world.includes.is_empty());
1657
1658 let mut types = HashSet::new();
1659 for (name, item) in world.imports.iter().chain(world.exports.iter()) {
1660 log::debug!("validating world item: {}", self.name_world_key(name));
1661 match item {
1662 WorldItem::Interface { id, .. } => {
1663 if matches!(name, WorldKey::Name(_)) {
1666 assert_eq!(self.interfaces[*id].package, world.package);
1667 }
1668 }
1669 WorldItem::Function(f) => {
1670 assert!(!matches!(name, WorldKey::Interface(_)));
1671 assert_eq!(f.name, name.clone().unwrap_name());
1672 }
1673 WorldItem::Type { id: ty, .. } => {
1674 assert!(!matches!(name, WorldKey::Interface(_)));
1675 assert!(types.insert(*ty));
1676 let ty = &self.types[*ty];
1677 assert_eq!(ty.name, Some(name.clone().unwrap_name()));
1678 assert_eq!(ty.owner, TypeOwner::World(id));
1679 }
1680 }
1681 }
1682 self.assert_world_elaborated(world);
1683 world_types.push(types);
1684 }
1685
1686 for (ty_id, ty) in self.types.iter() {
1687 match ty.owner {
1688 TypeOwner::Interface(id) => {
1689 assert!(self.interfaces.get(id).is_some());
1690 assert!(interface_types[id.index()].contains(&ty_id));
1691 }
1692 TypeOwner::World(id) => {
1693 assert!(self.worlds.get(id).is_some());
1694 assert!(world_types[id.index()].contains(&ty_id));
1695 }
1696 TypeOwner::None => {}
1697 }
1698 }
1699
1700 self.assert_topologically_sorted();
1701 }
1702
1703 fn assert_topologically_sorted(&self) {
1704 let mut positions = IndexMap::default();
1705 for id in self.topological_packages() {
1706 let pkg = &self.packages[id];
1707 log::debug!("pkg {}", pkg.name);
1708 let prev = positions.insert(Some(id), IndexSet::default());
1709 assert!(prev.is_none());
1710 }
1711 positions.insert(None, IndexSet::default());
1712
1713 for (id, iface) in self.interfaces.iter() {
1714 log::debug!("iface {:?}", iface.name);
1715 let ok = positions.get_mut(&iface.package).unwrap().insert(id);
1716 assert!(ok);
1717 }
1718
1719 for (_, world) in self.worlds.iter() {
1720 log::debug!("world {:?}", world.name);
1721
1722 let my_package = world.package;
1723 let my_package_pos = positions.get_index_of(&my_package).unwrap();
1724
1725 for (_, item) in world.imports.iter().chain(&world.exports) {
1726 let id = match item {
1727 WorldItem::Interface { id, .. } => *id,
1728 _ => continue,
1729 };
1730 let other_package = self.interfaces[id].package;
1731 let other_package_pos = positions.get_index_of(&other_package).unwrap();
1732
1733 assert!(other_package_pos <= my_package_pos);
1734 }
1735 }
1736
1737 for (_id, ty) in self.types.iter() {
1738 log::debug!("type {:?} {:?}", ty.name, ty.owner);
1739 let other_id = match ty.kind {
1740 TypeDefKind::Type(Type::Id(ty)) => ty,
1741 _ => continue,
1742 };
1743 let other = &self.types[other_id];
1744 if ty.kind == other.kind {
1745 continue;
1746 }
1747 let my_interface = match ty.owner {
1748 TypeOwner::Interface(id) => id,
1749 _ => continue,
1750 };
1751 let other_interface = match other.owner {
1752 TypeOwner::Interface(id) => id,
1753 _ => continue,
1754 };
1755
1756 let my_package = self.interfaces[my_interface].package;
1757 let other_package = self.interfaces[other_interface].package;
1758 let my_package_pos = positions.get_index_of(&my_package).unwrap();
1759 let other_package_pos = positions.get_index_of(&other_package).unwrap();
1760
1761 assert!(other_package_pos <= my_package_pos);
1762 }
1763 }
1764
1765 fn assert_world_elaborated(&self, world: &World) {
1766 for (key, item) in world.imports.iter() {
1767 log::debug!(
1768 "asserting elaborated world import {}",
1769 self.name_world_key(key)
1770 );
1771 match item {
1772 WorldItem::Type { id, .. } => self.assert_world_imports_type_deps(world, key, *id),
1773
1774 WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1776
1777 WorldItem::Interface { id, .. } => {
1779 for dep in self.interface_direct_deps(*id) {
1780 assert!(
1781 world.imports.contains_key(&WorldKey::Interface(dep)),
1782 "world import of {} is missing transitive dep of {}",
1783 self.name_world_key(key),
1784 self.id_of(dep).unwrap(),
1785 );
1786 }
1787 }
1788 }
1789 }
1790 for (key, item) in world.exports.iter() {
1791 log::debug!(
1792 "asserting elaborated world export {}",
1793 self.name_world_key(key)
1794 );
1795 match item {
1796 WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1798
1799 WorldItem::Interface { id, .. } => {
1803 for dep in self.interface_direct_deps(*id) {
1804 let dep_key = WorldKey::Interface(dep);
1805 if world.exports.contains_key(&dep_key) {
1806 continue;
1807 }
1808 self.foreach_interface_dep(dep, &mut |dep| {
1809 let dep_key = WorldKey::Interface(dep);
1810 assert!(
1811 world.imports.contains_key(&dep_key),
1812 "world should import {} (required by {})",
1813 self.name_world_key(&dep_key),
1814 self.name_world_key(key),
1815 );
1816 assert!(
1817 !world.exports.contains_key(&dep_key),
1818 "world should not export {} (required by {})",
1819 self.name_world_key(&dep_key),
1820 self.name_world_key(key),
1821 );
1822 });
1823 }
1824 }
1825
1826 WorldItem::Type { .. } => unreachable!(),
1828 }
1829 }
1830 }
1831
1832 fn assert_world_imports_type_deps(&self, world: &World, key: &WorldKey, ty: TypeId) {
1833 let ty = &self.types[ty];
1836 if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
1837 if let TypeOwner::Interface(id) = self.types[other].owner {
1838 let key = WorldKey::Interface(id);
1839 assert!(world.imports.contains_key(&key));
1840 return;
1841 }
1842 }
1843
1844 let mut visitor = MyVisit(self, Vec::new());
1848 visitor.visit_type_def(self, ty);
1849 for ty in visitor.1 {
1850 let ty = &self.types[ty];
1851 let Some(name) = ty.name.clone() else {
1852 continue;
1853 };
1854 let dep_key = WorldKey::Name(name);
1855 assert!(
1856 world.imports.contains_key(&dep_key),
1857 "world import `{}` should also force an import of `{}`",
1858 self.name_world_key(key),
1859 self.name_world_key(&dep_key),
1860 );
1861 }
1862
1863 struct MyVisit<'a>(&'a Resolve, Vec<TypeId>);
1864
1865 impl TypeIdVisitor for MyVisit<'_> {
1866 fn before_visit_type_id(&mut self, id: TypeId) -> bool {
1867 self.1.push(id);
1868 self.0.types[id].name.is_none()
1870 }
1871 }
1872 }
1873
1874 fn assert_world_function_imports_types(&self, world: &World, key: &WorldKey, func: &Function) {
1878 for ty in func
1879 .parameter_and_result_types()
1880 .chain(func.kind.resource().map(Type::Id))
1881 {
1882 let Type::Id(id) = ty else {
1883 continue;
1884 };
1885 self.assert_world_imports_type_deps(world, key, id);
1886 }
1887 }
1888
1889 fn include_stability(
1905 &self,
1906 stability: &Stability,
1907 pkg_id: &PackageId,
1908 span: Span,
1909 ) -> Result<bool> {
1910 let err = |msg: String| -> anyhow::Error { Error::new(span, msg).into() };
1911 Ok(match stability {
1912 Stability::Unknown => true,
1913 Stability::Stable { since, .. } => {
1916 let Some(p) = self.packages.get(*pkg_id) else {
1917 return Ok(true);
1925 };
1926
1927 let package_version = p.name.version.as_ref().ok_or_else(|| {
1930 err(format!(
1931 "package [{}] contains a feature gate with a version \
1932 specifier, so it must have a version",
1933 p.name
1934 ))
1935 })?;
1936
1937 if since > package_version {
1941 return Err(err(format!(
1942 "feature gate cannot reference unreleased version \
1943 {since} of package [{}] (current version {package_version})",
1944 p.name
1945 )));
1946 }
1947
1948 true
1949 }
1950 Stability::Unstable { feature, .. } => {
1951 self.features.contains(feature) || self.all_features
1952 }
1953 })
1954 }
1955
1956 fn include_type(&self, ty: &TypeDef, pkgid: PackageId, span: Span) -> Result<bool> {
1959 self.include_stability(&ty.stability, &pkgid, span)
1960 .with_context(|| {
1961 format!(
1962 "failed to process feature gate for type [{}] in package [{}]",
1963 ty.name.as_ref().map(String::as_str).unwrap_or("<unknown>"),
1964 self.packages[pkgid].name,
1965 )
1966 })
1967 }
1968
1969 fn elaborate_world(&mut self, world_id: WorldId) -> Result<()> {
1981 let mut new_imports = IndexMap::default();
1985 let world = &self.worlds[world_id];
1986
1987 let sort_key = |resolve: &Resolve, item: &WorldItem| match item {
2010 WorldItem::Interface { .. } => 0,
2011 WorldItem::Type { id, .. } => {
2012 let ty = &resolve.types[*id];
2013 match ty.kind {
2014 TypeDefKind::Type(Type::Id(t)) if resolve.types[t].owner != ty.owner => 1,
2015 _ => 2,
2016 }
2017 }
2018 WorldItem::Function(f) => {
2019 if f.kind.resource().is_none() {
2020 3
2021 } else {
2022 4
2023 }
2024 }
2025 };
2026
2027 let mut world_imports = world.imports.iter().collect::<Vec<_>>();
2030 world_imports.sort_by_key(|(_name, import)| sort_key(self, import));
2031 for (name, item) in world_imports {
2032 match item {
2033 WorldItem::Interface { id, stability, .. } => {
2036 self.elaborate_world_import(&mut new_imports, name.clone(), *id, &stability);
2037 }
2038
2039 WorldItem::Function(_) => {
2042 let prev = new_imports.insert(name.clone(), item.clone());
2043 assert!(prev.is_none());
2044 }
2045
2046 WorldItem::Type { id, .. } => {
2050 if let Some(dep) = self.type_interface_dep(*id) {
2051 self.elaborate_world_import(
2052 &mut new_imports,
2053 WorldKey::Interface(dep),
2054 dep,
2055 &self.types[*id].stability,
2056 );
2057 }
2058 let prev = new_imports.insert(name.clone(), item.clone());
2059 assert!(prev.is_none());
2060 }
2061 }
2062 }
2063
2064 let mut new_exports = IndexMap::default();
2070 let mut export_interfaces = IndexMap::default();
2071 for (name, item) in world.exports.iter() {
2072 match item {
2073 WorldItem::Interface { id, stability, .. } => {
2074 let prev = export_interfaces.insert(*id, (name.clone(), stability));
2075 assert!(prev.is_none());
2076 }
2077 WorldItem::Function(_) => {
2078 let prev = new_exports.insert(name.clone(), item.clone());
2079 assert!(prev.is_none());
2080 }
2081 WorldItem::Type { .. } => unreachable!(),
2082 }
2083 }
2084
2085 self.elaborate_world_exports(&export_interfaces, &mut new_imports, &mut new_exports)?;
2086
2087 new_imports.sort_by_cached_key(|_name, import| sort_key(self, import));
2091
2092 log::trace!("imports = {new_imports:?}");
2095 log::trace!("exports = {new_exports:?}");
2096 let world = &mut self.worlds[world_id];
2097 world.imports = new_imports;
2098 world.exports = new_exports;
2099
2100 Ok(())
2101 }
2102
2103 fn elaborate_world_import(
2104 &self,
2105 imports: &mut IndexMap<WorldKey, WorldItem>,
2106 key: WorldKey,
2107 id: InterfaceId,
2108 stability: &Stability,
2109 ) {
2110 if imports.contains_key(&key) {
2111 return;
2112 }
2113 for dep in self.interface_direct_deps(id) {
2114 self.elaborate_world_import(imports, WorldKey::Interface(dep), dep, stability);
2115 }
2116 let prev = imports.insert(
2117 key,
2118 WorldItem::Interface {
2119 id,
2120 stability: stability.clone(),
2121 span: Default::default(),
2122 },
2123 );
2124 assert!(prev.is_none());
2125 }
2126
2127 fn elaborate_world_exports(
2174 &self,
2175 export_interfaces: &IndexMap<InterfaceId, (WorldKey, &Stability)>,
2176 imports: &mut IndexMap<WorldKey, WorldItem>,
2177 exports: &mut IndexMap<WorldKey, WorldItem>,
2178 ) -> Result<()> {
2179 let mut required_imports = HashSet::new();
2180 for (id, (key, stability)) in export_interfaces.iter() {
2181 let name = self.name_world_key(&key);
2182 let ok = add_world_export(
2183 self,
2184 imports,
2185 exports,
2186 export_interfaces,
2187 &mut required_imports,
2188 *id,
2189 key,
2190 true,
2191 stability,
2192 );
2193 if !ok {
2194 bail!(
2195 InvalidTransitiveDependency(name),
2213 );
2214 }
2215 }
2216 return Ok(());
2217
2218 fn add_world_export(
2219 resolve: &Resolve,
2220 imports: &mut IndexMap<WorldKey, WorldItem>,
2221 exports: &mut IndexMap<WorldKey, WorldItem>,
2222 export_interfaces: &IndexMap<InterfaceId, (WorldKey, &Stability)>,
2223 required_imports: &mut HashSet<InterfaceId>,
2224 id: InterfaceId,
2225 key: &WorldKey,
2226 add_export: bool,
2227 stability: &Stability,
2228 ) -> bool {
2229 if exports.contains_key(key) {
2230 if add_export {
2231 return true;
2232 } else {
2233 return false;
2234 }
2235 }
2236 if !add_export && required_imports.contains(&id) {
2239 return true;
2240 }
2241 let ok = resolve.interface_direct_deps(id).all(|dep| {
2242 let key = WorldKey::Interface(dep);
2243 let add_export = add_export && export_interfaces.contains_key(&dep);
2244 add_world_export(
2245 resolve,
2246 imports,
2247 exports,
2248 export_interfaces,
2249 required_imports,
2250 dep,
2251 &key,
2252 add_export,
2253 stability,
2254 )
2255 });
2256 if !ok {
2257 return false;
2258 }
2259 let item = WorldItem::Interface {
2260 id,
2261 stability: stability.clone(),
2262 span: Default::default(),
2263 };
2264 if add_export {
2265 if required_imports.contains(&id) {
2266 return false;
2267 }
2268 exports.insert(key.clone(), item);
2269 } else {
2270 required_imports.insert(id);
2271 imports.insert(key.clone(), item);
2272 }
2273 true
2274 }
2275 }
2276
2277 pub fn merge_world_imports_based_on_semver(&mut self, world_id: WorldId) -> Result<()> {
2289 let world = &self.worlds[world_id];
2290
2291 let mut semver_tracks = HashMap::new();
2300 let mut to_remove = HashSet::new();
2301 for (key, _) in world.imports.iter() {
2302 let iface_id = match key {
2303 WorldKey::Interface(id) => *id,
2304 WorldKey::Name(_) => continue,
2305 };
2306 let (track, version) = match self.semver_track(iface_id) {
2307 Some(track) => track,
2308 None => continue,
2309 };
2310 log::debug!(
2311 "{} is on track {}/{}",
2312 self.id_of(iface_id).unwrap(),
2313 track.0,
2314 track.1,
2315 );
2316 match semver_tracks.entry(track.clone()) {
2317 Entry::Vacant(e) => {
2318 e.insert((version, iface_id));
2319 }
2320 Entry::Occupied(mut e) => match version.cmp(&e.get().0) {
2321 Ordering::Greater => {
2322 to_remove.insert(e.get().1);
2323 e.insert((version, iface_id));
2324 }
2325 Ordering::Equal => {}
2326 Ordering::Less => {
2327 to_remove.insert(iface_id);
2328 }
2329 },
2330 }
2331 }
2332
2333 let mut replacements = HashMap::new();
2336 for id in to_remove {
2337 let (track, _) = self.semver_track(id).unwrap();
2338 let (_, latest) = semver_tracks[&track];
2339 let prev = replacements.insert(id, latest);
2340 assert!(prev.is_none());
2341 }
2342 drop(semver_tracks);
2345
2346 for (to_replace, replace_with) in replacements.iter() {
2351 self.merge_world_item(
2352 &WorldItem::Interface {
2353 id: *to_replace,
2354 stability: Default::default(),
2355 span: Default::default(),
2356 },
2357 &WorldItem::Interface {
2358 id: *replace_with,
2359 stability: Default::default(),
2360 span: Default::default(),
2361 },
2362 )
2363 .with_context(|| {
2364 let old_name = self.id_of(*to_replace).unwrap();
2365 let new_name = self.id_of(*replace_with).unwrap();
2366 format!(
2367 "failed to upgrade `{old_name}` to `{new_name}`, was \
2368 this semver-compatible update not semver compatible?"
2369 )
2370 })?;
2371 }
2372
2373 for (to_replace, replace_with) in replacements.iter() {
2374 log::debug!(
2375 "REPLACE {} => {}",
2376 self.id_of(*to_replace).unwrap(),
2377 self.id_of(*replace_with).unwrap(),
2378 );
2379 }
2380
2381 for (key, item) in mem::take(&mut self.worlds[world_id].imports) {
2390 if let WorldItem::Interface { id, .. } = item {
2391 if replacements.contains_key(&id) {
2392 continue;
2393 }
2394 }
2395
2396 self.update_interface_deps_of_world_item(&item, &replacements);
2397
2398 let prev = self.worlds[world_id].imports.insert(key, item);
2399 assert!(prev.is_none());
2400 }
2401 for (key, item) in mem::take(&mut self.worlds[world_id].exports) {
2402 self.update_interface_deps_of_world_item(&item, &replacements);
2403 let prev = self.worlds[world_id].exports.insert(key, item);
2404 assert!(prev.is_none());
2405 }
2406
2407 let ids = self.worlds.iter().map(|(id, _)| id).collect::<Vec<_>>();
2413 for world_id in ids {
2414 self.elaborate_world(world_id).with_context(|| {
2415 let name = &self.worlds[world_id].name;
2416 format!(
2417 "failed to elaborate world `{name}` after deduplicating imports \
2418 based on semver"
2419 )
2420 })?;
2421 }
2422
2423 #[cfg(debug_assertions)]
2424 self.assert_valid();
2425
2426 Ok(())
2427 }
2428
2429 fn update_interface_deps_of_world_item(
2430 &mut self,
2431 item: &WorldItem,
2432 replacements: &HashMap<InterfaceId, InterfaceId>,
2433 ) {
2434 match *item {
2435 WorldItem::Type { id, .. } => self.update_interface_dep_of_type(id, &replacements),
2436 WorldItem::Interface { id, .. } => {
2437 let types = self.interfaces[id]
2438 .types
2439 .values()
2440 .copied()
2441 .collect::<Vec<_>>();
2442 for ty in types {
2443 self.update_interface_dep_of_type(ty, &replacements);
2444 }
2445 }
2446 WorldItem::Function(_) => {}
2447 }
2448 }
2449
2450 fn semver_track(&self, id: InterfaceId) -> Option<((PackageName, String), &Version)> {
2461 let iface = &self.interfaces[id];
2462 let pkg = &self.packages[iface.package?];
2463 let version = pkg.name.version.as_ref()?;
2464 let mut name = pkg.name.clone();
2465 name.version = Some(PackageName::version_compat_track(version));
2466 Some(((name, iface.name.clone()?), version))
2467 }
2468
2469 fn update_interface_dep_of_type(
2473 &mut self,
2474 ty: TypeId,
2475 replacements: &HashMap<InterfaceId, InterfaceId>,
2476 ) {
2477 let to_replace = match self.type_interface_dep(ty) {
2478 Some(id) => id,
2479 None => return,
2480 };
2481 let replace_with = match replacements.get(&to_replace) {
2482 Some(id) => id,
2483 None => return,
2484 };
2485 let dep = match self.types[ty].kind {
2486 TypeDefKind::Type(Type::Id(id)) => id,
2487 _ => return,
2488 };
2489 let name = self.types[dep].name.as_ref().unwrap();
2490 let replacement_id = self.interfaces[*replace_with].types[name];
2493 self.types[ty].kind = TypeDefKind::Type(Type::Id(replacement_id));
2494 }
2495
2496 pub fn wasm_import_name(
2503 &self,
2504 mangling: ManglingAndAbi,
2505 import: WasmImport<'_>,
2506 ) -> (String, String) {
2507 match mangling {
2508 ManglingAndAbi::Standard32 => match import {
2509 WasmImport::Func { interface, func } => {
2510 let module = match interface {
2511 Some(key) => format!("cm32p2|{}", self.name_canonicalized_world_key(key)),
2512 None => format!("cm32p2"),
2513 };
2514 (module, func.name.clone())
2515 }
2516 WasmImport::ResourceIntrinsic {
2517 interface,
2518 resource,
2519 intrinsic,
2520 } => {
2521 let name = self.types[resource].name.as_ref().unwrap();
2522 let (prefix, name) = match intrinsic {
2523 ResourceIntrinsic::ImportedDrop => ("", format!("{name}_drop")),
2524 ResourceIntrinsic::ExportedDrop => ("_ex_", format!("{name}_drop")),
2525 ResourceIntrinsic::ExportedNew => ("_ex_", format!("{name}_new")),
2526 ResourceIntrinsic::ExportedRep => ("_ex_", format!("{name}_rep")),
2527 };
2528 let module = match interface {
2529 Some(key) => {
2530 format!("cm32p2|{prefix}{}", self.name_canonicalized_world_key(key))
2531 }
2532 None => {
2533 assert_eq!(prefix, "");
2534 format!("cm32p2")
2535 }
2536 };
2537 (module, name)
2538 }
2539 WasmImport::FutureIntrinsic { .. } | WasmImport::StreamIntrinsic { .. } => {
2540 panic!(
2541 "at the time of writing, standard32 name mangling only supports the \
2542 synchronous ABI and does not define future/stream intrinsic imports; \
2543 use legacy mangling for these imports"
2544 )
2545 }
2546 },
2547 ManglingAndAbi::Legacy(abi) => match import {
2548 WasmImport::Func { interface, func } => {
2549 let module = match interface {
2550 Some(key) => self.name_world_key(key),
2551 None => format!("$root"),
2552 };
2553 (module, format!("{}{}", abi.import_prefix(), func.name))
2554 }
2555 WasmImport::ResourceIntrinsic {
2556 interface,
2557 resource,
2558 intrinsic,
2559 } => {
2560 let name = self.types[resource].name.as_ref().unwrap();
2561 let (prefix, name) = match intrinsic {
2562 ResourceIntrinsic::ImportedDrop => ("", format!("[resource-drop]{name}")),
2563 ResourceIntrinsic::ExportedDrop => {
2564 ("[export]", format!("[resource-drop]{name}"))
2565 }
2566 ResourceIntrinsic::ExportedNew => {
2567 ("[export]", format!("[resource-new]{name}"))
2568 }
2569 ResourceIntrinsic::ExportedRep => {
2570 ("[export]", format!("[resource-rep]{name}"))
2571 }
2572 };
2573 let module = match interface {
2574 Some(key) => format!("{prefix}{}", self.name_world_key(key)),
2575 None => {
2576 assert_eq!(prefix, "");
2577 format!("$root")
2578 }
2579 };
2580 (module, format!("{}{name}", abi.import_prefix()))
2581 }
2582 WasmImport::FutureIntrinsic {
2583 interface,
2584 func,
2585 ty,
2586 intrinsic,
2587 exported,
2588 async_,
2589 } => {
2590 let module_prefix = if exported { "[export]" } else { "" };
2591 let module = match interface {
2592 Some(key) => format!("{module_prefix}{}", self.name_world_key(key)),
2593 None => format!("{module_prefix}$root"),
2594 };
2595 let type_index = match ty {
2596 Some(ty) => func
2597 .find_futures_and_streams(self)
2598 .into_iter()
2599 .position(|candidate| candidate == ty)
2600 .unwrap_or_else(|| {
2601 panic!(
2602 "future type {ty:?} not found in `find_futures_and_streams` for `{}`",
2603 func.name
2604 )
2605 })
2606 .to_string(),
2607 None => "unit".to_string(),
2608 };
2609 let (async_prefix, name) = match intrinsic {
2610 FutureIntrinsic::New => {
2611 assert!(!async_, "future.new cannot be async-lowered");
2612 ("", "new")
2613 }
2614 FutureIntrinsic::Read => {
2615 (if async_ { "[async-lower]" } else { "" }, "read")
2616 }
2617 FutureIntrinsic::Write => {
2618 (if async_ { "[async-lower]" } else { "" }, "write")
2619 }
2620 FutureIntrinsic::CancelRead => {
2621 (if async_ { "[async-lower]" } else { "" }, "cancel-read")
2622 }
2623 FutureIntrinsic::CancelWrite => {
2624 (if async_ { "[async-lower]" } else { "" }, "cancel-write")
2625 }
2626 FutureIntrinsic::DropReadable => {
2627 assert!(!async_, "future.drop-readable cannot be async-lowered");
2628 ("", "drop-readable")
2629 }
2630 FutureIntrinsic::DropWritable => {
2631 assert!(!async_, "future.drop-writable cannot be async-lowered");
2632 ("", "drop-writable")
2633 }
2634 };
2635 (
2636 module,
2637 format!("{async_prefix}[future-{name}-{type_index}]{}", func.name),
2638 )
2639 }
2640 WasmImport::StreamIntrinsic {
2641 interface,
2642 func,
2643 ty,
2644 intrinsic,
2645 exported,
2646 async_,
2647 } => {
2648 let module_prefix = if exported { "[export]" } else { "" };
2649 let module = match interface {
2650 Some(key) => format!("{module_prefix}{}", self.name_world_key(key)),
2651 None => format!("{module_prefix}$root"),
2652 };
2653 let type_index = match ty {
2654 Some(ty) => func
2655 .find_futures_and_streams(self)
2656 .into_iter()
2657 .position(|candidate| candidate == ty)
2658 .unwrap_or_else(|| {
2659 panic!(
2660 "stream type {ty:?} not found in `find_futures_and_streams` for `{}`",
2661 func.name
2662 )
2663 })
2664 .to_string(),
2665 None => "unit".to_string(),
2666 };
2667 let (async_prefix, name) = match intrinsic {
2668 StreamIntrinsic::New => {
2669 assert!(!async_, "stream.new cannot be async-lowered");
2670 ("", "new")
2671 }
2672 StreamIntrinsic::Read => {
2673 (if async_ { "[async-lower]" } else { "" }, "read")
2674 }
2675 StreamIntrinsic::Write => {
2676 (if async_ { "[async-lower]" } else { "" }, "write")
2677 }
2678 StreamIntrinsic::CancelRead => {
2679 (if async_ { "[async-lower]" } else { "" }, "cancel-read")
2680 }
2681 StreamIntrinsic::CancelWrite => {
2682 (if async_ { "[async-lower]" } else { "" }, "cancel-write")
2683 }
2684 StreamIntrinsic::DropReadable => {
2685 assert!(!async_, "stream.drop-readable cannot be async-lowered");
2686 ("", "drop-readable")
2687 }
2688 StreamIntrinsic::DropWritable => {
2689 assert!(!async_, "stream.drop-writable cannot be async-lowered");
2690 ("", "drop-writable")
2691 }
2692 };
2693 (
2694 module,
2695 format!("{async_prefix}[stream-{name}-{type_index}]{}", func.name),
2696 )
2697 }
2698 },
2699 }
2700 }
2701
2702 pub fn wasm_export_name(&self, mangling: ManglingAndAbi, export: WasmExport<'_>) -> String {
2706 match mangling {
2707 ManglingAndAbi::Standard32 => match export {
2708 WasmExport::Func {
2709 interface,
2710 func,
2711 kind,
2712 } => {
2713 let mut name = String::from("cm32p2|");
2714 if let Some(interface) = interface {
2715 let s = self.name_canonicalized_world_key(interface);
2716 name.push_str(&s);
2717 }
2718 name.push_str("|");
2719 name.push_str(&func.name);
2720 match kind {
2721 WasmExportKind::Normal => {}
2722 WasmExportKind::PostReturn => name.push_str("_post"),
2723 WasmExportKind::Callback => todo!(
2724 "not yet supported: \
2725 async callback functions using standard name mangling"
2726 ),
2727 }
2728 name
2729 }
2730 WasmExport::ResourceDtor {
2731 interface,
2732 resource,
2733 } => {
2734 let name = self.types[resource].name.as_ref().unwrap();
2735 let interface = self.name_canonicalized_world_key(interface);
2736 format!("cm32p2|{interface}|{name}_dtor")
2737 }
2738 WasmExport::Memory => "cm32p2_memory".to_string(),
2739 WasmExport::Initialize => "cm32p2_initialize".to_string(),
2740 WasmExport::Realloc => "cm32p2_realloc".to_string(),
2741 },
2742 ManglingAndAbi::Legacy(abi) => match export {
2743 WasmExport::Func {
2744 interface,
2745 func,
2746 kind,
2747 } => {
2748 let mut name = abi.export_prefix().to_string();
2749 match kind {
2750 WasmExportKind::Normal => {}
2751 WasmExportKind::PostReturn => name.push_str("cabi_post_"),
2752 WasmExportKind::Callback => {
2753 assert!(matches!(abi, LiftLowerAbi::AsyncCallback));
2754 name = format!("[callback]{name}")
2755 }
2756 }
2757 if let Some(interface) = interface {
2758 let s = self.name_world_key(interface);
2759 name.push_str(&s);
2760 name.push_str("#");
2761 }
2762 name.push_str(&func.name);
2763 name
2764 }
2765 WasmExport::ResourceDtor {
2766 interface,
2767 resource,
2768 } => {
2769 let name = self.types[resource].name.as_ref().unwrap();
2770 let interface = self.name_world_key(interface);
2771 format!("{}{interface}#[dtor]{name}", abi.export_prefix())
2772 }
2773 WasmExport::Memory => "memory".to_string(),
2774 WasmExport::Initialize => "_initialize".to_string(),
2775 WasmExport::Realloc => "cabi_realloc".to_string(),
2776 },
2777 }
2778 }
2779
2780 pub fn generate_nominal_type_ids(&mut self, world: WorldId) {
2820 let mut imports = HashSet::new();
2821
2822 for import in self.worlds[world].imports.values() {
2825 if let WorldItem::Interface { id, .. } = import {
2826 imports.insert(*id);
2827 }
2828 }
2829
2830 let mut to_clone = IndexMap::default();
2831 for (i, export) in self.worlds[world].exports.values().enumerate() {
2832 let id = match export {
2833 WorldItem::Interface { id, .. } => *id,
2834
2835 WorldItem::Function(_) => continue,
2838
2839 WorldItem::Type { .. } => unreachable!(),
2840 };
2841
2842 let imported_and_exported = imports.contains(&id);
2846 let any_dep_rewritten = self
2847 .interface_direct_deps(id)
2848 .any(|dep| to_clone.contains_key(&dep));
2849 if !(imported_and_exported || any_dep_rewritten) {
2850 continue;
2851 }
2852
2853 to_clone.insert(id, i);
2854 }
2855
2856 let mut maps = CloneMaps::default();
2857 let mut cloner = clone::Cloner::new(
2858 self,
2859 &mut maps,
2860 TypeOwner::World(world),
2861 TypeOwner::World(world),
2862 );
2863 for (id, i) in to_clone {
2864 let mut new_id = id;
2870 cloner.new_package = cloner.resolve.interfaces[new_id].package;
2871 cloner.interface(&mut new_id);
2872
2873 let exports = &mut cloner.resolve.worlds[world].exports;
2877 let (key, prev) = exports.get_index_mut(i).unwrap();
2878 match prev {
2879 WorldItem::Interface { id, .. } => *id = new_id,
2880 _ => unreachable!(),
2881 }
2882
2883 match key {
2884 WorldKey::Interface(_) => {
2890 exports
2891 .replace_index(i, WorldKey::Interface(new_id))
2892 .unwrap();
2893 }
2894
2895 WorldKey::Name(_) => {}
2898 }
2899 }
2900
2901 #[cfg(debug_assertions)]
2902 self.assert_valid();
2903 }
2904}
2905
2906#[derive(Debug)]
2908pub enum WasmImport<'a> {
2909 Func {
2911 interface: Option<&'a WorldKey>,
2916
2917 func: &'a Function,
2919 },
2920
2921 ResourceIntrinsic {
2923 interface: Option<&'a WorldKey>,
2925
2926 resource: TypeId,
2928
2929 intrinsic: ResourceIntrinsic,
2931 },
2932
2933 FutureIntrinsic {
2935 interface: Option<&'a WorldKey>,
2937
2938 func: &'a Function,
2940
2941 ty: Option<TypeId>,
2945
2946 intrinsic: FutureIntrinsic,
2948
2949 exported: bool,
2953
2954 async_: bool,
2958 },
2959
2960 StreamIntrinsic {
2962 interface: Option<&'a WorldKey>,
2964
2965 func: &'a Function,
2967
2968 ty: Option<TypeId>,
2972
2973 intrinsic: StreamIntrinsic,
2975
2976 exported: bool,
2980
2981 async_: bool,
2985 },
2986}
2987
2988#[derive(Debug)]
2991pub enum ResourceIntrinsic {
2992 ImportedDrop,
2993 ExportedDrop,
2994 ExportedNew,
2995 ExportedRep,
2996}
2997
2998#[derive(Debug)]
3001pub enum FutureIntrinsic {
3002 New,
3003 Read,
3004 Write,
3005 CancelRead,
3006 CancelWrite,
3007 DropReadable,
3008 DropWritable,
3009}
3010
3011#[derive(Debug)]
3014pub enum StreamIntrinsic {
3015 New,
3016 Read,
3017 Write,
3018 CancelRead,
3019 CancelWrite,
3020 DropReadable,
3021 DropWritable,
3022}
3023
3024#[derive(Debug)]
3027pub enum WasmExportKind {
3028 Normal,
3030
3031 PostReturn,
3033
3034 Callback,
3036}
3037
3038#[derive(Debug)]
3041pub enum WasmExport<'a> {
3042 Func {
3044 interface: Option<&'a WorldKey>,
3047
3048 func: &'a Function,
3050
3051 kind: WasmExportKind,
3053 },
3054
3055 ResourceDtor {
3057 interface: &'a WorldKey,
3059 resource: TypeId,
3061 },
3062
3063 Memory,
3065
3066 Initialize,
3068
3069 Realloc,
3071}
3072
3073#[derive(Default)]
3076pub struct Remap {
3077 pub types: Vec<Option<TypeId>>,
3078 pub interfaces: Vec<Option<InterfaceId>>,
3079 pub worlds: Vec<Option<WorldId>>,
3080 pub packages: Vec<PackageId>,
3081
3082 own_handles: HashMap<TypeId, TypeId>,
3092
3093 type_has_borrow: Vec<Option<bool>>,
3094}
3095
3096fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Span) -> Result<Id<T>> {
3097 match map.get(id.index()) {
3098 Some(Some(id)) => Ok(*id),
3099 Some(None) => {
3100 let msg = format!(
3101 "found a reference to a {desc} which is excluded \
3102 due to its feature not being activated"
3103 );
3104 Err(Error::new(span, msg).into())
3105 }
3106 None => panic!("request to remap a {desc} that has not yet been registered"),
3107 }
3108}
3109
3110fn rename(original_name: &str, include_name: &IncludeName) -> Option<String> {
3111 if original_name == include_name.name {
3112 return Some(include_name.as_.to_string());
3113 }
3114 let (kind, rest) = original_name.split_once(']')?;
3115 match rest.split_once('.') {
3116 Some((name, rest)) if name == include_name.name => {
3117 Some(format!("{kind}]{}.{rest}", include_name.as_))
3118 }
3119 _ if rest == include_name.name => Some(format!("{kind}]{}", include_name.as_)),
3120 _ => None,
3121 }
3122}
3123
3124impl Remap {
3125 pub fn map_type(&self, id: TypeId, span: Span) -> Result<TypeId> {
3126 apply_map(&self.types, id, "type", span)
3127 }
3128
3129 pub fn map_interface(&self, id: InterfaceId, span: Span) -> Result<InterfaceId> {
3130 apply_map(&self.interfaces, id, "interface", span)
3131 }
3132
3133 pub fn map_world(&self, id: WorldId, span: Span) -> Result<WorldId> {
3134 apply_map(&self.worlds, id, "world", span)
3135 }
3136
3137 fn append(
3138 &mut self,
3139 resolve: &mut Resolve,
3140 unresolved: UnresolvedPackage,
3141 ) -> Result<PackageId> {
3142 let pkgid = resolve.packages.alloc(Package {
3143 name: unresolved.name.clone(),
3144 docs: unresolved.docs.clone(),
3145 interfaces: Default::default(),
3146 worlds: Default::default(),
3147 });
3148 let prev = resolve.package_names.insert(unresolved.name.clone(), pkgid);
3149 if let Some(prev) = prev {
3150 resolve.package_names.insert(unresolved.name.clone(), prev);
3151 bail!(
3152 "attempting to re-add package `{}` when it's already present in this `Resolve`",
3153 unresolved.name,
3154 );
3155 }
3156
3157 self.process_foreign_deps(resolve, pkgid, &unresolved)?;
3158
3159 let foreign_types = self.types.len();
3160 let foreign_interfaces = self.interfaces.len();
3161 let foreign_worlds = self.worlds.len();
3162
3163 for (id, mut ty) in unresolved.types.into_iter().skip(foreign_types) {
3169 let span = ty.span;
3170 if !resolve.include_type(&ty, pkgid, span)? {
3171 self.types.push(None);
3172 continue;
3173 }
3174
3175 self.update_typedef(resolve, &mut ty, span)?;
3176 let new_id = resolve.types.alloc(ty);
3177 assert_eq!(self.types.len(), id.index());
3178
3179 let new_id = match resolve.types[new_id] {
3180 TypeDef {
3185 name: None,
3186 owner: TypeOwner::None,
3187 kind: TypeDefKind::Handle(Handle::Own(id)),
3188 docs: _,
3189 stability: _,
3190 span: _,
3191 } => *self.own_handles.entry(id).or_insert(new_id),
3192
3193 _ => new_id,
3196 };
3197 self.types.push(Some(new_id));
3198 }
3199
3200 for (id, mut iface) in unresolved.interfaces.into_iter().skip(foreign_interfaces) {
3203 let span = iface.span;
3204 if !resolve
3205 .include_stability(&iface.stability, &pkgid, span)
3206 .with_context(|| {
3207 format!(
3208 "failed to process feature gate for interface [{}] in package [{}]",
3209 iface
3210 .name
3211 .as_ref()
3212 .map(String::as_str)
3213 .unwrap_or("<unknown>"),
3214 resolve.packages[pkgid].name,
3215 )
3216 })?
3217 {
3218 self.interfaces.push(None);
3219 continue;
3220 }
3221 assert!(iface.package.is_none());
3222 iface.package = Some(pkgid);
3223 self.update_interface(resolve, &mut iface)?;
3224 let new_id = resolve.interfaces.alloc(iface);
3225 assert_eq!(self.interfaces.len(), id.index());
3226 self.interfaces.push(Some(new_id));
3227 }
3228
3229 for id in self.types.iter().skip(foreign_types) {
3232 let id = match id {
3233 Some(id) => *id,
3234 None => continue,
3235 };
3236 let span = resolve.types[id].span;
3237 match &mut resolve.types[id].owner {
3238 TypeOwner::Interface(iface_id) => {
3239 *iface_id = self.map_interface(*iface_id, span)
3240 .with_context(|| {
3241 "this type is not gated by a feature but its interface is gated by a feature"
3242 })?;
3243 }
3244 TypeOwner::World(_) | TypeOwner::None => {}
3245 }
3246 }
3247
3248 for (id, mut world) in unresolved.worlds.into_iter().skip(foreign_worlds) {
3256 let world_span = world.span;
3257 if !resolve
3258 .include_stability(&world.stability, &pkgid, world_span)
3259 .with_context(|| {
3260 format!(
3261 "failed to process feature gate for world [{}] in package [{}]",
3262 world.name, resolve.packages[pkgid].name,
3263 )
3264 })?
3265 {
3266 self.worlds.push(None);
3267 continue;
3268 }
3269 self.update_world(&mut world, resolve, &pkgid)?;
3270
3271 let new_id = resolve.worlds.alloc(world);
3272 assert_eq!(self.worlds.len(), id.index());
3273 self.worlds.push(Some(new_id));
3274 }
3275
3276 for id in self.types.iter().skip(foreign_types) {
3278 let id = match id {
3279 Some(id) => *id,
3280 None => continue,
3281 };
3282 let span = resolve.types[id].span;
3283 match &mut resolve.types[id].owner {
3284 TypeOwner::World(world_id) => {
3285 *world_id = self.map_world(*world_id, span)
3286 .with_context(|| {
3287 "this type is not gated by a feature but its interface is gated by a feature"
3288 })?;
3289 }
3290 TypeOwner::Interface(_) | TypeOwner::None => {}
3291 }
3292 }
3293
3294 for id in self.worlds.iter().skip(foreign_worlds) {
3311 let Some(id) = *id else {
3312 continue;
3313 };
3314 self.process_world_includes(id, resolve, &pkgid)?;
3315
3316 let world_span = resolve.worlds[id].span;
3317 resolve.elaborate_world(id).with_context(|| {
3318 Error::new(
3319 world_span,
3320 format!(
3321 "failed to elaborate world imports/exports of `{}`",
3322 resolve.worlds[id].name
3323 ),
3324 )
3325 })?;
3326 }
3327
3328 for id in self.interfaces.iter().skip(foreign_interfaces) {
3330 let id = match id {
3331 Some(id) => *id,
3332 None => continue,
3333 };
3334 let iface = &mut resolve.interfaces[id];
3335 iface.package = Some(pkgid);
3336 if let Some(name) = &iface.name {
3337 let prev = resolve.packages[pkgid].interfaces.insert(name.clone(), id);
3338 assert!(prev.is_none());
3339 }
3340 }
3341 for id in self.worlds.iter().skip(foreign_worlds) {
3342 let id = match id {
3343 Some(id) => *id,
3344 None => continue,
3345 };
3346 let world = &mut resolve.worlds[id];
3347 world.package = Some(pkgid);
3348 let prev = resolve.packages[pkgid]
3349 .worlds
3350 .insert(world.name.clone(), id);
3351 assert!(prev.is_none());
3352 }
3353 Ok(pkgid)
3354 }
3355
3356 fn process_foreign_deps(
3357 &mut self,
3358 resolve: &mut Resolve,
3359 pkgid: PackageId,
3360 unresolved: &UnresolvedPackage,
3361 ) -> Result<()> {
3362 let mut world_to_package = HashMap::new();
3365 let mut interface_to_package = HashMap::new();
3366 for (i, (pkg_name, worlds_or_ifaces)) in unresolved.foreign_deps.iter().enumerate() {
3367 for (name, (item, stabilities)) in worlds_or_ifaces {
3368 match item {
3369 AstItem::Interface(unresolved_interface_id) => {
3370 let prev = interface_to_package.insert(
3371 *unresolved_interface_id,
3372 (pkg_name, name, unresolved.foreign_dep_spans[i], stabilities),
3373 );
3374 assert!(prev.is_none());
3375 }
3376 AstItem::World(unresolved_world_id) => {
3377 let prev = world_to_package.insert(
3378 *unresolved_world_id,
3379 (pkg_name, name, unresolved.foreign_dep_spans[i], stabilities),
3380 );
3381 assert!(prev.is_none());
3382 }
3383 }
3384 }
3385 }
3386
3387 self.process_foreign_interfaces(unresolved, &interface_to_package, resolve, &pkgid)?;
3391
3392 self.process_foreign_worlds(unresolved, &world_to_package, resolve, &pkgid)?;
3396
3397 self.process_foreign_types(unresolved, pkgid, resolve)?;
3400
3401 for (id, span) in unresolved.required_resource_types.iter() {
3402 let Ok(mut id) = self.map_type(*id, *span) else {
3407 continue;
3408 };
3409 loop {
3410 match resolve.types[id].kind {
3411 TypeDefKind::Type(Type::Id(i)) => id = i,
3412 TypeDefKind::Resource => break,
3413 _ => bail!(Error::new(
3414 *span,
3415 format!("type used in a handle must be a resource"),
3416 )),
3417 }
3418 }
3419 }
3420
3421 #[cfg(debug_assertions)]
3422 resolve.assert_valid();
3423
3424 Ok(())
3425 }
3426
3427 fn process_foreign_interfaces(
3428 &mut self,
3429 unresolved: &UnresolvedPackage,
3430 interface_to_package: &HashMap<InterfaceId, (&PackageName, &String, Span, &Vec<Stability>)>,
3431 resolve: &mut Resolve,
3432 parent_pkg_id: &PackageId,
3433 ) -> Result<(), anyhow::Error> {
3434 for (unresolved_iface_id, unresolved_iface) in unresolved.interfaces.iter() {
3435 let (pkg_name, interface, span, stabilities) =
3436 match interface_to_package.get(&unresolved_iface_id) {
3437 Some(items) => *items,
3438 None => break,
3442 };
3443
3444 let pkgid = resolve
3445 .package_names
3446 .get(pkg_name)
3447 .copied()
3448 .ok_or_else(|| {
3449 PackageNotFoundError::new(
3450 span,
3451 pkg_name.clone(),
3452 resolve.package_names.keys().cloned().collect(),
3453 )
3454 })?;
3455
3456 assert!(unresolved_iface.functions.is_empty());
3458
3459 let pkg = &resolve.packages[pkgid];
3460 let iface_span = unresolved_iface.span;
3461
3462 let mut enabled = false;
3463 for stability in stabilities {
3464 if resolve.include_stability(stability, parent_pkg_id, iface_span)? {
3465 enabled = true;
3466 break;
3467 }
3468 }
3469
3470 if !enabled {
3471 self.interfaces.push(None);
3472 continue;
3473 }
3474
3475 let iface_id = pkg
3476 .interfaces
3477 .get(interface)
3478 .copied()
3479 .ok_or_else(|| Error::new(iface_span, "interface not found in package"))?;
3480 assert_eq!(self.interfaces.len(), unresolved_iface_id.index());
3481 self.interfaces.push(Some(iface_id));
3482 }
3483 for (id, _) in unresolved.interfaces.iter().skip(self.interfaces.len()) {
3484 assert!(
3485 interface_to_package.get(&id).is_none(),
3486 "found foreign interface after local interface"
3487 );
3488 }
3489 Ok(())
3490 }
3491
3492 fn process_foreign_worlds(
3493 &mut self,
3494 unresolved: &UnresolvedPackage,
3495 world_to_package: &HashMap<WorldId, (&PackageName, &String, Span, &Vec<Stability>)>,
3496 resolve: &mut Resolve,
3497 parent_pkg_id: &PackageId,
3498 ) -> Result<(), anyhow::Error> {
3499 for (unresolved_world_id, unresolved_world) in unresolved.worlds.iter() {
3500 let (pkg_name, world, span, stabilities) =
3501 match world_to_package.get(&unresolved_world_id) {
3502 Some(items) => *items,
3503 None => break,
3506 };
3507
3508 let pkgid = resolve
3509 .package_names
3510 .get(pkg_name)
3511 .copied()
3512 .ok_or_else(|| Error::new(span, "package not found"))?;
3513 let pkg = &resolve.packages[pkgid];
3514 let world_span = unresolved_world.span;
3515
3516 let mut enabled = false;
3517 for stability in stabilities {
3518 if resolve.include_stability(stability, parent_pkg_id, world_span)? {
3519 enabled = true;
3520 break;
3521 }
3522 }
3523
3524 if !enabled {
3525 self.worlds.push(None);
3526 continue;
3527 }
3528
3529 let world_id = pkg
3530 .worlds
3531 .get(world)
3532 .copied()
3533 .ok_or_else(|| Error::new(world_span, "world not found in package"))?;
3534 assert_eq!(self.worlds.len(), unresolved_world_id.index());
3535 self.worlds.push(Some(world_id));
3536 }
3537 for (id, _) in unresolved.worlds.iter().skip(self.worlds.len()) {
3538 assert!(
3539 world_to_package.get(&id).is_none(),
3540 "found foreign world after local world"
3541 );
3542 }
3543 Ok(())
3544 }
3545
3546 fn process_foreign_types(
3547 &mut self,
3548 unresolved: &UnresolvedPackage,
3549 pkgid: PackageId,
3550 resolve: &mut Resolve,
3551 ) -> Result<(), anyhow::Error> {
3552 for (unresolved_type_id, unresolved_ty) in unresolved.types.iter() {
3553 match unresolved_ty.kind {
3557 TypeDefKind::Unknown => {}
3558 _ => break,
3559 }
3560
3561 let span = unresolved_ty.span;
3562 if !resolve.include_type(unresolved_ty, pkgid, span)? {
3563 self.types.push(None);
3564 continue;
3565 }
3566
3567 let unresolved_iface_id = match unresolved_ty.owner {
3568 TypeOwner::Interface(id) => id,
3569 _ => unreachable!(),
3570 };
3571 let iface_id = self.map_interface(unresolved_iface_id, Default::default())?;
3572 let name = unresolved_ty.name.as_ref().unwrap();
3573 let span = unresolved.unknown_type_spans[unresolved_type_id.index()];
3574 let type_id = *resolve.interfaces[iface_id]
3575 .types
3576 .get(name)
3577 .ok_or_else(|| {
3578 Error::new(span, format!("type `{name}` not defined in interface"))
3579 })?;
3580 assert_eq!(self.types.len(), unresolved_type_id.index());
3581 self.types.push(Some(type_id));
3582 }
3583 for (_, ty) in unresolved.types.iter().skip(self.types.len()) {
3584 if let TypeDefKind::Unknown = ty.kind {
3585 panic!("unknown type after defined type");
3586 }
3587 }
3588 Ok(())
3589 }
3590
3591 fn update_typedef(
3592 &mut self,
3593 resolve: &mut Resolve,
3594 ty: &mut TypeDef,
3595 span: Span,
3596 ) -> Result<()> {
3597 use crate::TypeDefKind::*;
3600 match &mut ty.kind {
3601 Handle(handle) => match handle {
3602 crate::Handle::Own(ty) | crate::Handle::Borrow(ty) => {
3603 self.update_type_id(ty, span)?
3604 }
3605 },
3606 Resource => {}
3607 Record(r) => {
3608 for field in r.fields.iter_mut() {
3609 self.update_ty(resolve, &mut field.ty, span)
3610 .with_context(|| format!("failed to update field `{}`", field.name))?;
3611 }
3612 }
3613 Tuple(t) => {
3614 for ty in t.types.iter_mut() {
3615 self.update_ty(resolve, ty, span)?;
3616 }
3617 }
3618 Variant(v) => {
3619 for case in v.cases.iter_mut() {
3620 if let Some(t) = &mut case.ty {
3621 self.update_ty(resolve, t, span)?;
3622 }
3623 }
3624 }
3625 Option(t)
3626 | List(t, ..)
3627 | FixedLengthList(t, ..)
3628 | Future(Some(t))
3629 | Stream(Some(t)) => self.update_ty(resolve, t, span)?,
3630 Map(k, v) => {
3631 self.update_ty(resolve, k, span)?;
3632 self.update_ty(resolve, v, span)?;
3633 }
3634 Result(r) => {
3635 if let Some(ty) = &mut r.ok {
3636 self.update_ty(resolve, ty, span)?;
3637 }
3638 if let Some(ty) = &mut r.err {
3639 self.update_ty(resolve, ty, span)?;
3640 }
3641 }
3642
3643 Type(crate::Type::Id(id)) => self.update_type_id(id, span)?,
3648 Type(_) => {}
3649
3650 Flags(_) | Enum(_) | Future(None) | Stream(None) => {}
3652
3653 Unknown => unreachable!(),
3654 }
3655
3656 Ok(())
3657 }
3658
3659 fn update_ty(&mut self, resolve: &mut Resolve, ty: &mut Type, span: Span) -> Result<()> {
3660 let id = match ty {
3661 Type::Id(id) => id,
3662 _ => return Ok(()),
3663 };
3664 self.update_type_id(id, span)?;
3665
3666 let mut cur = *id;
3671 let points_to_resource = loop {
3672 match resolve.types[cur].kind {
3673 TypeDefKind::Type(Type::Id(id)) => cur = id,
3674 TypeDefKind::Resource => break true,
3675 _ => break false,
3676 }
3677 };
3678
3679 if points_to_resource {
3680 *id = *self.own_handles.entry(*id).or_insert_with(|| {
3681 resolve.types.alloc(TypeDef {
3682 name: None,
3683 owner: TypeOwner::None,
3684 kind: TypeDefKind::Handle(Handle::Own(*id)),
3685 docs: Default::default(),
3686 stability: Default::default(),
3687 span: Default::default(),
3688 })
3689 });
3690 }
3691 Ok(())
3692 }
3693
3694 fn update_type_id(&self, id: &mut TypeId, span: Span) -> Result<()> {
3695 *id = self.map_type(*id, span)?;
3696 Ok(())
3697 }
3698
3699 fn update_interface(&mut self, resolve: &mut Resolve, iface: &mut Interface) -> Result<()> {
3700 iface.types.retain(|_, ty| self.types[ty.index()].is_some());
3701 let iface_pkg_id = iface.package.as_ref().unwrap_or_else(|| {
3702 panic!(
3703 "unexpectedly missing package on interface [{}]",
3704 iface
3705 .name
3706 .as_ref()
3707 .map(String::as_str)
3708 .unwrap_or("<unknown>"),
3709 )
3710 });
3711
3712 for (_name, ty) in iface.types.iter_mut() {
3715 self.update_type_id(ty, iface.span)?;
3716 }
3717 for (func_name, func) in iface.functions.iter_mut() {
3718 let span = func.span;
3719 if !resolve
3720 .include_stability(&func.stability, iface_pkg_id, span)
3721 .with_context(|| {
3722 format!(
3723 "failed to process feature gate for function [{func_name}] in package [{}]",
3724 resolve.packages[*iface_pkg_id].name,
3725 )
3726 })?
3727 {
3728 continue;
3729 }
3730 self.update_function(resolve, func, span)
3731 .with_context(|| format!("failed to update function `{}`", func.name))?;
3732 }
3733
3734 for (name, func) in mem::take(&mut iface.functions) {
3737 if resolve.include_stability(&func.stability, iface_pkg_id, func.span)? {
3738 iface.functions.insert(name, func);
3739 }
3740 }
3741
3742 Ok(())
3743 }
3744
3745 fn update_function(
3746 &mut self,
3747 resolve: &mut Resolve,
3748 func: &mut Function,
3749 span: Span,
3750 ) -> Result<()> {
3751 if let Some(id) = func.kind.resource_mut() {
3752 self.update_type_id(id, span)?;
3753 }
3754 for param in func.params.iter_mut() {
3755 self.update_ty(resolve, &mut param.ty, span)?;
3756 }
3757 if let Some(ty) = &mut func.result {
3758 self.update_ty(resolve, ty, span)?;
3759 }
3760
3761 if let Some(ty) = &func.result {
3762 if self.type_has_borrow(resolve, ty) {
3763 bail!(Error::new(
3764 span,
3765 format!(
3766 "function returns a type which contains \
3767 a `borrow<T>` which is not supported"
3768 )
3769 ))
3770 }
3771 }
3772
3773 Ok(())
3774 }
3775
3776 fn update_world(
3777 &mut self,
3778 world: &mut World,
3779 resolve: &mut Resolve,
3780 pkg_id: &PackageId,
3781 ) -> Result<()> {
3782 let imports = mem::take(&mut world.imports).into_iter().map(|p| (p, true));
3786 let exports = mem::take(&mut world.exports)
3787 .into_iter()
3788 .map(|p| (p, false));
3789 for ((mut name, mut item), import) in imports.chain(exports) {
3790 let span = item.span();
3791 if let WorldItem::Type { id, .. } = &mut item {
3794 *id = self.map_type(*id, span)?;
3795 }
3796 let stability = item.stability(resolve);
3797 if !resolve
3798 .include_stability(stability, pkg_id, span)
3799 .with_context(|| format!("failed to process world item in `{}`", world.name))?
3800 {
3801 continue;
3802 }
3803 self.update_world_key(&mut name, span)?;
3804 match &mut item {
3805 WorldItem::Interface { id, .. } => {
3806 *id = self.map_interface(*id, span)?;
3807 }
3808 WorldItem::Function(f) => {
3809 self.update_function(resolve, f, span)?;
3810 }
3811 WorldItem::Type { .. } => {
3812 }
3814 }
3815
3816 let dst = if import {
3817 &mut world.imports
3818 } else {
3819 &mut world.exports
3820 };
3821 let prev = dst.insert(name, item);
3822 assert!(prev.is_none());
3823 }
3824
3825 Ok(())
3826 }
3827
3828 fn process_world_includes(
3829 &self,
3830 id: WorldId,
3831 resolve: &mut Resolve,
3832 pkg_id: &PackageId,
3833 ) -> Result<()> {
3834 let world = &mut resolve.worlds[id];
3835 let includes = mem::take(&mut world.includes);
3838 for include in includes {
3839 if !resolve
3840 .include_stability(&include.stability, pkg_id, include.span)
3841 .with_context(|| {
3842 format!(
3843 "failed to process feature gate for included world [{}] in package [{}]",
3844 resolve.worlds[include.id].name.as_str(),
3845 resolve.packages[*pkg_id].name
3846 )
3847 })?
3848 {
3849 continue;
3850 }
3851 self.resolve_include(
3852 id,
3853 include.id,
3854 &include.names,
3855 include.span,
3856 pkg_id,
3857 resolve,
3858 )?;
3859 }
3860
3861 Self::validate_world_case_insensitive_names(resolve, id)?;
3863
3864 Ok(())
3865 }
3866
3867 fn validate_world_case_insensitive_names(resolve: &Resolve, world_id: WorldId) -> Result<()> {
3871 let world = &resolve.worlds[world_id];
3872
3873 let validate_names = |items: &IndexMap<WorldKey, WorldItem>,
3875 item_type: &str|
3876 -> Result<()> {
3877 let mut seen_lowercase: HashMap<String, String> = HashMap::new();
3878
3879 for key in items.keys() {
3880 if let WorldKey::Name(name) = key {
3882 let lowercase_name = name.to_lowercase();
3883
3884 if let Some(existing_name) = seen_lowercase.get(&lowercase_name) {
3885 if existing_name != name {
3888 bail!(
3889 "{item_type} `{name}` conflicts with {item_type} `{existing_name}` \
3890 (kebab-case identifiers are case-insensitive)"
3891 );
3892 }
3893 }
3894
3895 seen_lowercase.insert(lowercase_name, name.clone());
3896 }
3897 }
3898
3899 Ok(())
3900 };
3901
3902 validate_names(&world.imports, "import")
3903 .with_context(|| format!("failed to validate imports in world `{}`", world.name))?;
3904 validate_names(&world.exports, "export")
3905 .with_context(|| format!("failed to validate exports in world `{}`", world.name))?;
3906
3907 Ok(())
3908 }
3909
3910 fn update_world_key(&self, key: &mut WorldKey, span: Span) -> Result<()> {
3911 match key {
3912 WorldKey::Name(_) => {}
3913 WorldKey::Interface(id) => {
3914 *id = self.map_interface(*id, span)?;
3915 }
3916 }
3917 Ok(())
3918 }
3919
3920 fn resolve_include(
3921 &self,
3922 id: WorldId,
3923 include_world_id_orig: WorldId,
3924 names: &[IncludeName],
3925 span: Span,
3926 pkg_id: &PackageId,
3927 resolve: &mut Resolve,
3928 ) -> Result<()> {
3929 let world = &resolve.worlds[id];
3930 let include_world_id = self.map_world(include_world_id_orig, span)?;
3931 let include_world = resolve.worlds[include_world_id].clone();
3932 let mut names_ = names.to_owned();
3933 let is_external_include = world.package != include_world.package;
3934
3935 for import in include_world.imports.iter() {
3937 self.remove_matching_name(import, &mut names_);
3938 }
3939 for export in include_world.exports.iter() {
3940 self.remove_matching_name(export, &mut names_);
3941 }
3942 if !names_.is_empty() {
3943 bail!(Error::new(
3944 span,
3945 format!(
3946 "no import or export kebab-name `{}`. Note that an ID does not support renaming",
3947 names_[0].name
3948 ),
3949 ));
3950 }
3951
3952 let mut maps = Default::default();
3953 let mut cloner = clone::Cloner::new(
3954 resolve,
3955 &mut maps,
3956 TypeOwner::World(if is_external_include {
3957 include_world_id
3958 } else {
3959 include_world_id
3960 }),
3962 TypeOwner::World(id),
3963 );
3964 cloner.new_package = Some(*pkg_id);
3965
3966 for import in include_world.imports.iter() {
3968 self.resolve_include_item(
3969 &mut cloner,
3970 names,
3971 |resolve| &mut resolve.worlds[id].imports,
3972 import,
3973 span,
3974 "import",
3975 is_external_include,
3976 )?;
3977 }
3978
3979 for export in include_world.exports.iter() {
3980 self.resolve_include_item(
3981 &mut cloner,
3982 names,
3983 |resolve| &mut resolve.worlds[id].exports,
3984 export,
3985 span,
3986 "export",
3987 is_external_include,
3988 )?;
3989 }
3990 Ok(())
3991 }
3992
3993 fn resolve_include_item(
3994 &self,
3995 cloner: &mut clone::Cloner<'_>,
3996 names: &[IncludeName],
3997 get_items: impl Fn(&mut Resolve) -> &mut IndexMap<WorldKey, WorldItem>,
3998 item: (&WorldKey, &WorldItem),
3999 span: Span,
4000 item_type: &str,
4001 is_external_include: bool,
4002 ) -> Result<()> {
4003 match item.0 {
4004 WorldKey::Name(n) => {
4005 let n = names
4006 .into_iter()
4007 .find_map(|include_name| rename(n, include_name))
4008 .unwrap_or(n.clone());
4009
4010 let mut new_item = item.1.clone();
4016 let key = WorldKey::Name(n.clone());
4017 cloner.world_item(&key, &mut new_item);
4018 match &mut new_item {
4019 WorldItem::Function(f) => f.name = n.clone(),
4020 WorldItem::Type { id, .. } => cloner.resolve.types[*id].name = Some(n.clone()),
4021 WorldItem::Interface { .. } => {}
4022 }
4023
4024 let prev = get_items(cloner.resolve).insert(key, new_item);
4025 if prev.is_some() {
4026 bail!(Error::new(
4027 span,
4028 format!("{item_type} of `{n}` shadows previously {item_type}ed items"),
4029 ))
4030 }
4031 }
4032 key @ WorldKey::Interface(_) => {
4033 let prev = get_items(cloner.resolve)
4034 .entry(key.clone())
4035 .or_insert(item.1.clone());
4036 match (&item.1, prev) {
4037 (
4038 WorldItem::Interface {
4039 id: aid,
4040 stability: astability,
4041 ..
4042 },
4043 WorldItem::Interface {
4044 id: bid,
4045 stability: bstability,
4046 ..
4047 },
4048 ) => {
4049 assert_eq!(*aid, *bid);
4050 merge_include_stability(astability, bstability, is_external_include)?;
4051 }
4052 (WorldItem::Interface { .. }, _) => unreachable!(),
4053 (WorldItem::Function(_), _) => unreachable!(),
4054 (WorldItem::Type { .. }, _) => unreachable!(),
4055 }
4056 }
4057 };
4058
4059 Ok(())
4060 }
4061
4062 fn remove_matching_name(&self, item: (&WorldKey, &WorldItem), names: &mut Vec<IncludeName>) {
4063 match item.0 {
4064 WorldKey::Name(n) => {
4065 names.retain(|name| rename(n, name).is_none());
4066 }
4067 _ => {}
4068 }
4069 }
4070
4071 fn type_has_borrow(&mut self, resolve: &Resolve, ty: &Type) -> bool {
4072 let id = match ty {
4073 Type::Id(id) => *id,
4074 _ => return false,
4075 };
4076
4077 if let Some(Some(has_borrow)) = self.type_has_borrow.get(id.index()) {
4078 return *has_borrow;
4079 }
4080
4081 let result = self.typedef_has_borrow(resolve, &resolve.types[id]);
4082 if self.type_has_borrow.len() <= id.index() {
4083 self.type_has_borrow.resize(id.index() + 1, None);
4084 }
4085 self.type_has_borrow[id.index()] = Some(result);
4086 result
4087 }
4088
4089 fn typedef_has_borrow(&mut self, resolve: &Resolve, ty: &TypeDef) -> bool {
4090 match &ty.kind {
4091 TypeDefKind::Type(t) => self.type_has_borrow(resolve, t),
4092 TypeDefKind::Variant(v) => v
4093 .cases
4094 .iter()
4095 .filter_map(|case| case.ty.as_ref())
4096 .any(|ty| self.type_has_borrow(resolve, ty)),
4097 TypeDefKind::Handle(Handle::Borrow(_)) => true,
4098 TypeDefKind::Handle(Handle::Own(_)) => false,
4099 TypeDefKind::Resource => false,
4100 TypeDefKind::Record(r) => r
4101 .fields
4102 .iter()
4103 .any(|case| self.type_has_borrow(resolve, &case.ty)),
4104 TypeDefKind::Flags(_) => false,
4105 TypeDefKind::Tuple(t) => t.types.iter().any(|t| self.type_has_borrow(resolve, t)),
4106 TypeDefKind::Enum(_) => false,
4107 TypeDefKind::List(ty)
4108 | TypeDefKind::FixedLengthList(ty, ..)
4109 | TypeDefKind::Future(Some(ty))
4110 | TypeDefKind::Stream(Some(ty))
4111 | TypeDefKind::Option(ty) => self.type_has_borrow(resolve, ty),
4112 TypeDefKind::Map(k, v) => {
4113 self.type_has_borrow(resolve, k) || self.type_has_borrow(resolve, v)
4114 }
4115 TypeDefKind::Result(r) => [&r.ok, &r.err]
4116 .iter()
4117 .filter_map(|t| t.as_ref())
4118 .any(|t| self.type_has_borrow(resolve, t)),
4119 TypeDefKind::Future(None) | TypeDefKind::Stream(None) => false,
4120 TypeDefKind::Unknown => unreachable!(),
4121 }
4122 }
4123}
4124
4125struct MergeMap<'a> {
4126 package_map: HashMap<PackageId, PackageId>,
4129
4130 interface_map: HashMap<InterfaceId, InterfaceId>,
4133
4134 type_map: HashMap<TypeId, TypeId>,
4137
4138 world_map: HashMap<WorldId, WorldId>,
4141
4142 interfaces_to_add: Vec<(String, PackageId, InterfaceId)>,
4150 worlds_to_add: Vec<(String, PackageId, WorldId)>,
4151
4152 from: &'a Resolve,
4154
4155 into: &'a Resolve,
4157}
4158
4159impl<'a> MergeMap<'a> {
4160 fn new(from: &'a Resolve, into: &'a Resolve) -> MergeMap<'a> {
4161 MergeMap {
4162 package_map: Default::default(),
4163 interface_map: Default::default(),
4164 type_map: Default::default(),
4165 world_map: Default::default(),
4166 interfaces_to_add: Default::default(),
4167 worlds_to_add: Default::default(),
4168 from,
4169 into,
4170 }
4171 }
4172
4173 fn build(&mut self) -> Result<()> {
4174 for from_id in self.from.topological_packages() {
4175 let from = &self.from.packages[from_id];
4176 let into_id = match self.into.package_names.get(&from.name) {
4177 Some(id) => *id,
4178
4179 None => {
4182 log::trace!("adding unique package {}", from.name);
4183 continue;
4184 }
4185 };
4186 log::trace!("merging duplicate package {}", from.name);
4187
4188 self.build_package(from_id, into_id).with_context(|| {
4189 format!("failed to merge package `{}` into existing copy", from.name)
4190 })?;
4191 }
4192
4193 Ok(())
4194 }
4195
4196 fn build_package(&mut self, from_id: PackageId, into_id: PackageId) -> Result<()> {
4197 let prev = self.package_map.insert(from_id, into_id);
4198 assert!(prev.is_none());
4199
4200 let from = &self.from.packages[from_id];
4201 let into = &self.into.packages[into_id];
4202
4203 for (name, from_interface_id) in from.interfaces.iter() {
4207 let into_interface_id = match into.interfaces.get(name) {
4208 Some(id) => *id,
4209 None => {
4210 log::trace!("adding unique interface {name}");
4211 self.interfaces_to_add
4212 .push((name.clone(), into_id, *from_interface_id));
4213 continue;
4214 }
4215 };
4216
4217 log::trace!("merging duplicate interfaces {name}");
4218 self.build_interface(*from_interface_id, into_interface_id)
4219 .with_context(|| format!("failed to merge interface `{name}`"))?;
4220 }
4221
4222 for (name, from_world_id) in from.worlds.iter() {
4223 let into_world_id = match into.worlds.get(name) {
4224 Some(id) => *id,
4225 None => {
4226 log::trace!("adding unique world {name}");
4227 self.worlds_to_add
4228 .push((name.clone(), into_id, *from_world_id));
4229 continue;
4230 }
4231 };
4232
4233 log::trace!("merging duplicate worlds {name}");
4234 self.build_world(*from_world_id, into_world_id)
4235 .with_context(|| format!("failed to merge world `{name}`"))?;
4236 }
4237
4238 Ok(())
4239 }
4240
4241 fn build_interface(&mut self, from_id: InterfaceId, into_id: InterfaceId) -> Result<()> {
4242 let prev = self.interface_map.insert(from_id, into_id);
4243 assert!(prev.is_none());
4244
4245 let from_interface = &self.from.interfaces[from_id];
4246 let into_interface = &self.into.interfaces[into_id];
4247
4248 for (name, from_type_id) in from_interface.types.iter() {
4256 let into_type_id = match into_interface.types.get(name) {
4257 Some(id) => *id,
4258 None => continue,
4261 };
4262 let prev = self.type_map.insert(*from_type_id, into_type_id);
4263 assert!(prev.is_none());
4264
4265 self.build_type_id(*from_type_id, into_type_id)
4266 .with_context(|| format!("mismatch in type `{name}`"))?;
4267 }
4268
4269 for (name, from_func) in from_interface.functions.iter() {
4270 let into_func = match into_interface.functions.get(name) {
4271 Some(func) => func,
4272 None => continue,
4275 };
4276 self.build_function(from_func, into_func)
4277 .with_context(|| format!("mismatch in function `{name}`"))?;
4278 }
4279
4280 Ok(())
4281 }
4282
4283 fn build_type_id(&mut self, from_id: TypeId, into_id: TypeId) -> Result<()> {
4284 let _ = from_id;
4288 let _ = into_id;
4289 Ok(())
4290 }
4291
4292 fn build_type(&mut self, from_ty: &Type, into_ty: &Type) -> Result<()> {
4293 match (from_ty, into_ty) {
4294 (Type::Id(from), Type::Id(into)) => {
4295 self.build_type_id(*from, *into)?;
4296 }
4297 (from, into) if from != into => bail!("different kinds of types"),
4298 _ => {}
4299 }
4300 Ok(())
4301 }
4302
4303 fn build_function(&mut self, from_func: &Function, into_func: &Function) -> Result<()> {
4304 if from_func.name != into_func.name {
4305 bail!(
4306 "different function names `{}` and `{}`",
4307 from_func.name,
4308 into_func.name
4309 );
4310 }
4311 match (&from_func.kind, &into_func.kind) {
4312 (FunctionKind::Freestanding, FunctionKind::Freestanding) => {}
4313 (FunctionKind::AsyncFreestanding, FunctionKind::AsyncFreestanding) => {}
4314
4315 (FunctionKind::Method(from), FunctionKind::Method(into))
4316 | (FunctionKind::Static(from), FunctionKind::Static(into))
4317 | (FunctionKind::AsyncMethod(from), FunctionKind::AsyncMethod(into))
4318 | (FunctionKind::AsyncStatic(from), FunctionKind::AsyncStatic(into))
4319 | (FunctionKind::Constructor(from), FunctionKind::Constructor(into)) => {
4320 self.build_type_id(*from, *into)
4321 .context("different function kind types")?;
4322 }
4323
4324 (FunctionKind::Method(_), _)
4325 | (FunctionKind::Constructor(_), _)
4326 | (FunctionKind::Static(_), _)
4327 | (FunctionKind::Freestanding, _)
4328 | (FunctionKind::AsyncFreestanding, _)
4329 | (FunctionKind::AsyncMethod(_), _)
4330 | (FunctionKind::AsyncStatic(_), _) => {
4331 bail!("different function kind types")
4332 }
4333 }
4334
4335 if from_func.params.len() != into_func.params.len() {
4336 bail!("different number of function parameters");
4337 }
4338 for (from_param, into_param) in from_func.params.iter().zip(&into_func.params) {
4339 if from_param.name != into_param.name {
4340 bail!(
4341 "different function parameter names: {} != {}",
4342 from_param.name,
4343 into_param.name
4344 );
4345 }
4346 self.build_type(&from_param.ty, &into_param.ty)
4347 .with_context(|| {
4348 format!(
4349 "different function parameter types for `{}`",
4350 from_param.name
4351 )
4352 })?;
4353 }
4354 match (&from_func.result, &into_func.result) {
4355 (Some(from_ty), Some(into_ty)) => {
4356 self.build_type(from_ty, into_ty)
4357 .context("different function result types")?;
4358 }
4359 (None, None) => {}
4360 (Some(_), None) | (None, Some(_)) => bail!("different number of function results"),
4361 }
4362 Ok(())
4363 }
4364
4365 fn build_world(&mut self, from_id: WorldId, into_id: WorldId) -> Result<()> {
4366 let prev = self.world_map.insert(from_id, into_id);
4367 assert!(prev.is_none());
4368
4369 let from_world = &self.from.worlds[from_id];
4370 let into_world = &self.into.worlds[into_id];
4371
4372 if from_world.imports.len() != into_world.imports.len() {
4381 bail!("world contains different number of imports than expected");
4382 }
4383 if from_world.exports.len() != into_world.exports.len() {
4384 bail!("world contains different number of exports than expected");
4385 }
4386
4387 for (from_name, from) in from_world.imports.iter() {
4388 let into_name = MergeMap::map_name(from_name, &self.interface_map);
4389 let name_str = self.from.name_world_key(from_name);
4390 let into = into_world
4391 .imports
4392 .get(&into_name)
4393 .ok_or_else(|| anyhow!("import `{name_str}` not found in target world"))?;
4394 self.match_world_item(from, into)
4395 .with_context(|| format!("import `{name_str}` didn't match target world"))?;
4396 }
4397
4398 for (from_name, from) in from_world.exports.iter() {
4399 let into_name = MergeMap::map_name(from_name, &self.interface_map);
4400 let name_str = self.from.name_world_key(from_name);
4401 let into = into_world
4402 .exports
4403 .get(&into_name)
4404 .ok_or_else(|| anyhow!("export `{name_str}` not found in target world"))?;
4405 self.match_world_item(from, into)
4406 .with_context(|| format!("export `{name_str}` didn't match target world"))?;
4407 }
4408
4409 Ok(())
4410 }
4411
4412 fn map_name(
4413 from_name: &WorldKey,
4414 interface_map: &HashMap<InterfaceId, InterfaceId>,
4415 ) -> WorldKey {
4416 match from_name {
4417 WorldKey::Name(s) => WorldKey::Name(s.clone()),
4418 WorldKey::Interface(id) => {
4419 WorldKey::Interface(interface_map.get(id).copied().unwrap_or(*id))
4420 }
4421 }
4422 }
4423
4424 fn match_world_item(&mut self, from: &WorldItem, into: &WorldItem) -> Result<()> {
4425 match (from, into) {
4426 (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
4427 match (
4428 &self.from.interfaces[*from].name,
4429 &self.into.interfaces[*into].name,
4430 ) {
4431 (None, None) => self.build_interface(*from, *into)?,
4435
4436 _ => {
4441 if self.interface_map.get(from) != Some(into) {
4442 bail!("interfaces are not the same");
4443 }
4444 }
4445 }
4446 }
4447 (WorldItem::Function(from), WorldItem::Function(into)) => {
4448 let _ = (from, into);
4449 }
4452 (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
4453 let prev = self.type_map.insert(*from, *into);
4456 assert!(prev.is_none());
4457 }
4458
4459 (WorldItem::Interface { .. }, _)
4460 | (WorldItem::Function(_), _)
4461 | (WorldItem::Type { .. }, _) => {
4462 bail!("world items do not have the same type")
4463 }
4464 }
4465 Ok(())
4466 }
4467}
4468
4469fn update_stability(from: &Stability, into: &mut Stability) -> Result<()> {
4475 if from == into || from.is_unknown() {
4478 return Ok(());
4479 }
4480 if into.is_unknown() {
4483 *into = from.clone();
4484 return Ok(());
4485 }
4486
4487 bail!("mismatch in stability from '{from:?}' to '{into:?}'")
4490}
4491
4492fn merge_include_stability(
4493 from: &Stability,
4494 into: &mut Stability,
4495 is_external_include: bool,
4496) -> Result<()> {
4497 if is_external_include && from.is_stable() {
4498 log::trace!("dropped stability from external package");
4499 *into = Stability::Unknown;
4500 return Ok(());
4501 }
4502
4503 return update_stability(from, into);
4504}
4505
4506#[derive(Debug, Clone)]
4519pub struct InvalidTransitiveDependency(String);
4520
4521impl fmt::Display for InvalidTransitiveDependency {
4522 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4523 write!(
4524 f,
4525 "interface `{}` transitively depends on an interface in \
4526 incompatible ways",
4527 self.0
4528 )
4529 }
4530}
4531
4532impl core::error::Error for InvalidTransitiveDependency {}
4533
4534#[cfg(test)]
4535mod tests {
4536 use crate::alloc::format;
4537 use crate::alloc::string::{String, ToString};
4538 use crate::alloc::vec::Vec;
4539 use crate::{Resolve, WorldItem, WorldKey};
4540 use anyhow::Result;
4541
4542 #[test]
4543 fn select_world() -> Result<()> {
4544 let mut resolve = Resolve::default();
4545 resolve.push_str(
4546 "test.wit",
4547 r#"
4548 package foo:bar@0.1.0;
4549
4550 world foo {}
4551 "#,
4552 )?;
4553 resolve.push_str(
4554 "test.wit",
4555 r#"
4556 package foo:baz@0.1.0;
4557
4558 world foo {}
4559 "#,
4560 )?;
4561 resolve.push_str(
4562 "test.wit",
4563 r#"
4564 package foo:baz@0.2.0;
4565
4566 world foo {}
4567 "#,
4568 )?;
4569
4570 let dummy = resolve.push_str(
4571 "test.wit",
4572 r#"
4573 package foo:dummy;
4574
4575 world foo {}
4576 "#,
4577 )?;
4578
4579 assert!(resolve.select_world(&[dummy], None).is_ok());
4580 assert!(resolve.select_world(&[dummy], Some("xx")).is_err());
4581 assert!(resolve.select_world(&[dummy], Some("")).is_err());
4582 assert!(resolve.select_world(&[dummy], Some("foo:bar/foo")).is_ok());
4583 assert!(
4584 resolve
4585 .select_world(&[dummy], Some("foo:bar/foo@0.1.0"))
4586 .is_ok()
4587 );
4588 assert!(resolve.select_world(&[dummy], Some("foo:baz/foo")).is_err());
4589 assert!(
4590 resolve
4591 .select_world(&[dummy], Some("foo:baz/foo@0.1.0"))
4592 .is_ok()
4593 );
4594 assert!(
4595 resolve
4596 .select_world(&[dummy], Some("foo:baz/foo@0.2.0"))
4597 .is_ok()
4598 );
4599 Ok(())
4600 }
4601
4602 #[test]
4603 fn wasm_import_name_future_and_stream_intrinsics() -> Result<()> {
4604 use crate::{FutureIntrinsic, LiftLowerAbi, ManglingAndAbi, StreamIntrinsic, WasmImport};
4605
4606 let mut resolve = Resolve::default();
4607 let pkg = resolve.push_str(
4608 "test.wit",
4609 r#"
4610 package foo:bar;
4611
4612 interface iface {
4613 iface-func: func(x: future<u32>) -> stream<u32>;
4614 }
4615
4616 world w {
4617 import import-func: func(x: future<future<u32>>, y: u32) -> stream<string>;
4618 export export-func: func(x: future, y: stream);
4619 import iface;
4620 export iface;
4621 }
4622 "#,
4623 )?;
4624 let world = resolve.packages[pkg].worlds["w"];
4625 let world = &resolve.worlds[world];
4626 let mangling = ManglingAndAbi::Legacy(LiftLowerAbi::AsyncStackful);
4627
4628 let WorldItem::Function(import_func) =
4629 &world.imports[&WorldKey::Name("import-func".to_string())]
4630 else {
4631 panic!("expected `import-func` to be a top-level world import");
4632 };
4633 let WorldItem::Function(export_func) =
4634 &world.exports[&WorldKey::Name("export-func".to_string())]
4635 else {
4636 panic!("expected `export-func` to be a top-level world export");
4637 };
4638 let import_types = import_func.find_futures_and_streams(&resolve);
4639 assert_eq!(import_types.len(), 3);
4640
4641 let (interface_key, interface_func) = world
4642 .imports
4643 .iter()
4644 .find_map(|(key, item)| match item {
4645 WorldItem::Interface { id, .. } => Some((
4646 key.clone(),
4647 &resolve.interfaces[*id].functions["iface-func"],
4648 )),
4649 _ => None,
4650 })
4651 .expect("expected interface import");
4652 let interface_types = interface_func.find_futures_and_streams(&resolve);
4653 assert_eq!(interface_types.len(), 2);
4654
4655 let (module, name) = resolve.wasm_import_name(
4656 mangling,
4657 WasmImport::FutureIntrinsic {
4658 interface: None,
4659 func: import_func,
4660 ty: Some(import_types[0]),
4661 intrinsic: FutureIntrinsic::New,
4662 exported: false,
4663 async_: false,
4664 },
4665 );
4666 assert_eq!(module, "$root");
4667 assert_eq!(name, "[future-new-0]import-func");
4668
4669 let (module, name) = resolve.wasm_import_name(
4670 mangling,
4671 WasmImport::FutureIntrinsic {
4672 interface: None,
4673 func: import_func,
4674 ty: Some(import_types[1]),
4675 intrinsic: FutureIntrinsic::Read,
4676 exported: false,
4677 async_: true,
4678 },
4679 );
4680 assert_eq!(module, "$root");
4681 assert_eq!(name, "[async-lower][future-read-1]import-func");
4682
4683 let (module, name) = resolve.wasm_import_name(
4684 mangling,
4685 WasmImport::StreamIntrinsic {
4686 interface: None,
4687 func: import_func,
4688 ty: Some(import_types[2]),
4689 intrinsic: StreamIntrinsic::CancelRead,
4690 exported: false,
4691 async_: true,
4692 },
4693 );
4694 assert_eq!(module, "$root");
4695 assert_eq!(name, "[async-lower][stream-cancel-read-2]import-func");
4696
4697 let (module, name) = resolve.wasm_import_name(
4698 mangling,
4699 WasmImport::FutureIntrinsic {
4700 interface: None,
4701 func: export_func,
4702 ty: None,
4703 intrinsic: FutureIntrinsic::DropReadable,
4704 exported: true,
4705 async_: false,
4706 },
4707 );
4708 assert_eq!(module, "[export]$root");
4709 assert_eq!(name, "[future-drop-readable-unit]export-func");
4710
4711 let (module, name) = resolve.wasm_import_name(
4712 mangling,
4713 WasmImport::StreamIntrinsic {
4714 interface: None,
4715 func: export_func,
4716 ty: None,
4717 intrinsic: StreamIntrinsic::Write,
4718 exported: true,
4719 async_: true,
4720 },
4721 );
4722 assert_eq!(module, "[export]$root");
4723 assert_eq!(name, "[async-lower][stream-write-unit]export-func");
4724
4725 let (module, name) = resolve.wasm_import_name(
4726 mangling,
4727 WasmImport::StreamIntrinsic {
4728 interface: Some(&interface_key),
4729 func: interface_func,
4730 ty: Some(interface_types[1]),
4731 intrinsic: StreamIntrinsic::Read,
4732 exported: true,
4733 async_: false,
4734 },
4735 );
4736 assert_eq!(
4737 module,
4738 format!("[export]{}", resolve.name_world_key(&interface_key))
4739 );
4740 assert_eq!(name, "[stream-read-1]iface-func");
4741
4742 Ok(())
4743 }
4744
4745 #[test]
4748 fn select_world_multiple_packages() -> Result<()> {
4749 use wit_parser::Resolve;
4750
4751 let mut resolve = Resolve::default();
4752
4753 let stuff = resolve.push_str(
4755 "./my-test.wit",
4756 r#"
4757 package test:stuff;
4758
4759 world foo {
4760 // ...
4761 }
4762 "#,
4763 )?;
4764 assert!(resolve.select_world(&[stuff], None).is_ok());
4765 assert!(resolve.select_world(&[stuff], Some("foo")).is_ok());
4766
4767 let empty = resolve.push_str(
4770 "./my-test.wit",
4771 r#"
4772 package test:empty;
4773 "#,
4774 )?;
4775 assert!(resolve.select_world(&[stuff, empty], None).is_err());
4776 assert!(resolve.select_world(&[stuff, empty], Some("foo")).is_err());
4777 assert!(resolve.select_world(&[empty], None).is_err());
4778 assert!(resolve.select_world(&[empty], Some("foo")).is_err());
4779
4780 Ok(())
4781 }
4782
4783 #[test]
4785 fn select_world_versions() -> Result<()> {
4786 use wit_parser::Resolve;
4787
4788 let mut resolve = Resolve::default();
4789
4790 let _id = resolve.push_str(
4791 "./my-test.wit",
4792 r#"
4793 package example:distraction;
4794 "#,
4795 )?;
4796
4797 let versions_1 = resolve.push_str(
4800 "./my-test.wit",
4801 r#"
4802 package example:versions@1.0.0;
4803
4804 world foo { /* ... */ }
4805 "#,
4806 )?;
4807 assert!(resolve.select_world(&[versions_1], Some("foo")).is_ok());
4808 assert!(
4809 resolve
4810 .select_world(&[versions_1], Some("foo@1.0.0"))
4811 .is_err()
4812 );
4813 assert!(
4814 resolve
4815 .select_world(&[versions_1], Some("example:versions/foo"))
4816 .is_ok()
4817 );
4818 assert!(
4819 resolve
4820 .select_world(&[versions_1], Some("example:versions/foo@1.0.0"))
4821 .is_ok()
4822 );
4823
4824 let versions_2 = resolve.push_str(
4827 "./my-test.wit",
4828 r#"
4829 package example:versions@2.0.0;
4830
4831 world foo { /* ... */ }
4832 "#,
4833 )?;
4834 assert!(
4835 resolve
4836 .select_world(&[versions_1, versions_2], Some("foo"))
4837 .is_err()
4838 );
4839 assert!(
4840 resolve
4841 .select_world(&[versions_1, versions_2], Some("foo@1.0.0"))
4842 .is_err()
4843 );
4844 assert!(
4845 resolve
4846 .select_world(&[versions_1, versions_2], Some("foo@2.0.0"))
4847 .is_err()
4848 );
4849 assert!(
4850 resolve
4851 .select_world(&[versions_1, versions_2], Some("example:versions/foo"))
4852 .is_err()
4853 );
4854 assert!(
4855 resolve
4856 .select_world(
4857 &[versions_1, versions_2],
4858 Some("example:versions/foo@1.0.0")
4859 )
4860 .is_ok()
4861 );
4862 assert!(
4863 resolve
4864 .select_world(
4865 &[versions_1, versions_2],
4866 Some("example:versions/foo@2.0.0")
4867 )
4868 .is_ok()
4869 );
4870
4871 Ok(())
4872 }
4873
4874 #[test]
4876 fn select_world_override_qualification() -> Result<()> {
4877 use wit_parser::Resolve;
4878
4879 let mut resolve = Resolve::default();
4880
4881 let other = resolve.push_str(
4882 "./my-test.wit",
4883 r#"
4884 package example:other;
4885
4886 world foo { }
4887 "#,
4888 )?;
4889
4890 let fq = resolve.push_str(
4892 "./my-test.wit",
4893 r#"
4894 package example:fq;
4895
4896 world bar { }
4897 "#,
4898 )?;
4899 assert!(resolve.select_world(&[other, fq], Some("foo")).is_err());
4900 assert!(resolve.select_world(&[other, fq], Some("bar")).is_err());
4901 assert!(
4902 resolve
4903 .select_world(&[other, fq], Some("example:other/foo"))
4904 .is_ok()
4905 );
4906 assert!(
4907 resolve
4908 .select_world(&[other, fq], Some("example:fq/bar"))
4909 .is_ok()
4910 );
4911 assert!(
4912 resolve
4913 .select_world(&[other, fq], Some("example:other/bar"))
4914 .is_err()
4915 );
4916 assert!(
4917 resolve
4918 .select_world(&[other, fq], Some("example:fq/foo"))
4919 .is_err()
4920 );
4921
4922 Ok(())
4923 }
4924
4925 #[test]
4927 fn select_world_fully_qualified() -> Result<()> {
4928 use wit_parser::Resolve;
4929
4930 let mut resolve = Resolve::default();
4931
4932 let distraction = resolve.push_str(
4933 "./my-test.wit",
4934 r#"
4935 package example:distraction;
4936 "#,
4937 )?;
4938
4939 let multiworld = resolve.push_str(
4942 "./my-test.wit",
4943 r#"
4944 package example:multiworld;
4945
4946 world foo { /* ... */ }
4947
4948 world bar { /* ... */ }
4949 "#,
4950 )?;
4951 assert!(
4952 resolve
4953 .select_world(&[distraction, multiworld], None)
4954 .is_err()
4955 );
4956 assert!(
4957 resolve
4958 .select_world(&[distraction, multiworld], Some("foo"))
4959 .is_err()
4960 );
4961 assert!(
4962 resolve
4963 .select_world(&[distraction, multiworld], Some("example:multiworld/foo"))
4964 .is_ok()
4965 );
4966 assert!(
4967 resolve
4968 .select_world(&[distraction, multiworld], Some("bar"))
4969 .is_err()
4970 );
4971 assert!(
4972 resolve
4973 .select_world(&[distraction, multiworld], Some("example:multiworld/bar"))
4974 .is_ok()
4975 );
4976
4977 Ok(())
4978 }
4979
4980 #[test]
4982 fn select_world_packages() -> Result<()> {
4983 use wit_parser::Resolve;
4984
4985 let mut resolve = Resolve::default();
4986
4987 let wit1 = resolve.push_str(
4990 "./my-test.wit",
4991 r#"
4992 package example:wit1;
4993
4994 world foo {
4995 // ...
4996 }
4997 "#,
4998 )?;
4999 assert!(resolve.select_world(&[wit1], None).is_ok());
5000 assert!(resolve.select_world(&[wit1], Some("foo")).is_ok());
5001 assert!(
5002 resolve
5003 .select_world(&[wit1], Some("example:wit1/foo"))
5004 .is_ok()
5005 );
5006 assert!(resolve.select_world(&[wit1], Some("bar")).is_err());
5007 assert!(
5008 resolve
5009 .select_world(&[wit1], Some("example:wit2/foo"))
5010 .is_err()
5011 );
5012
5013 let wit2 = resolve.push_str(
5016 "./my-test.wit",
5017 r#"
5018 package example:wit2;
5019
5020 world foo { /* ... */ }
5021 "#,
5022 )?;
5023 assert!(resolve.select_world(&[wit1, wit2], None).is_err());
5024 assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
5025 assert!(
5026 resolve
5027 .select_world(&[wit1, wit2], Some("example:wit1/foo"))
5028 .is_ok()
5029 );
5030 assert!(resolve.select_world(&[wit2], None).is_ok());
5031 assert!(resolve.select_world(&[wit2], Some("foo")).is_ok());
5032 assert!(
5033 resolve
5034 .select_world(&[wit2], Some("example:wit1/foo"))
5035 .is_ok()
5036 );
5037 assert!(resolve.select_world(&[wit1, wit2], Some("bar")).is_err());
5038 assert!(
5039 resolve
5040 .select_world(&[wit1, wit2], Some("example:wit2/foo"))
5041 .is_ok()
5042 );
5043 assert!(resolve.select_world(&[wit2], Some("bar")).is_err());
5044 assert!(
5045 resolve
5046 .select_world(&[wit2], Some("example:wit2/foo"))
5047 .is_ok()
5048 );
5049
5050 Ok(())
5051 }
5052
5053 #[test]
5054 fn span_preservation() -> Result<()> {
5055 let mut resolve = Resolve::default();
5056 let pkg = resolve.push_str(
5057 "test.wit",
5058 r#"
5059 package foo:bar;
5060
5061 interface my-iface {
5062 type my-type = u32;
5063 my-func: func();
5064 }
5065
5066 world my-world {
5067 export my-export: func();
5068 }
5069 "#,
5070 )?;
5071
5072 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5073 assert!(resolve.interfaces[iface_id].span.is_known());
5074
5075 let type_id = resolve.interfaces[iface_id].types["my-type"];
5076 assert!(resolve.types[type_id].span.is_known());
5077
5078 assert!(
5079 resolve.interfaces[iface_id].functions["my-func"]
5080 .span
5081 .is_known()
5082 );
5083
5084 let world_id = resolve.packages[pkg].worlds["my-world"];
5085 assert!(resolve.worlds[world_id].span.is_known());
5086
5087 let WorldItem::Function(f) =
5088 &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5089 else {
5090 panic!("expected function");
5091 };
5092 assert!(f.span.is_known());
5093
5094 Ok(())
5095 }
5096
5097 #[test]
5098 fn span_preservation_through_merge() -> Result<()> {
5099 let mut resolve1 = Resolve::default();
5100 resolve1.push_str(
5101 "test1.wit",
5102 r#"
5103 package foo:bar;
5104
5105 interface iface1 {
5106 type type1 = u32;
5107 func1: func();
5108 }
5109 "#,
5110 )?;
5111
5112 let mut resolve2 = Resolve::default();
5113 let pkg2 = resolve2.push_str(
5114 "test2.wit",
5115 r#"
5116 package foo:baz;
5117
5118 interface iface2 {
5119 type type2 = string;
5120 func2: func();
5121 }
5122 "#,
5123 )?;
5124
5125 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5126 let remap = resolve1.merge(resolve2)?;
5127 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5128
5129 assert!(resolve1.interfaces[iface2_id].span.is_known());
5130
5131 let type2_id = resolve1.interfaces[iface2_id].types["type2"];
5132 assert!(resolve1.types[type2_id].span.is_known());
5133
5134 assert!(
5135 resolve1.interfaces[iface2_id].functions["func2"]
5136 .span
5137 .is_known()
5138 );
5139
5140 Ok(())
5141 }
5142
5143 #[test]
5144 fn span_preservation_through_include() -> Result<()> {
5145 let mut resolve = Resolve::default();
5146 let pkg = resolve.push_str(
5147 "test.wit",
5148 r#"
5149 package foo:bar;
5150
5151 world base {
5152 export my-func: func();
5153 }
5154
5155 world extended {
5156 include base;
5157 }
5158 "#,
5159 )?;
5160
5161 let base_id = resolve.packages[pkg].worlds["base"];
5162 let extended_id = resolve.packages[pkg].worlds["extended"];
5163
5164 let WorldItem::Function(base_func) =
5165 &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5166 else {
5167 panic!("expected function");
5168 };
5169 assert!(base_func.span.is_known());
5170
5171 let WorldItem::Function(extended_func) =
5172 &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5173 else {
5174 panic!("expected function");
5175 };
5176 assert!(extended_func.span.is_known());
5177
5178 Ok(())
5179 }
5180
5181 #[test]
5182 fn span_preservation_through_include_with_rename() -> Result<()> {
5183 let mut resolve = Resolve::default();
5184 let pkg = resolve.push_str(
5185 "test.wit",
5186 r#"
5187 package foo:bar;
5188
5189 world base {
5190 export original-name: func();
5191 }
5192
5193 world extended {
5194 include base with { original-name as renamed-func }
5195 }
5196 "#,
5197 )?;
5198
5199 let extended_id = resolve.packages[pkg].worlds["extended"];
5200
5201 let WorldItem::Function(f) =
5202 &resolve.worlds[extended_id].exports[&WorldKey::Name("renamed-func".to_string())]
5203 else {
5204 panic!("expected function");
5205 };
5206 assert!(f.span.is_known());
5207
5208 assert!(
5209 !resolve.worlds[extended_id]
5210 .exports
5211 .contains_key(&WorldKey::Name("original-name".to_string()))
5212 );
5213
5214 Ok(())
5215 }
5216
5217 #[test]
5219 fn span_preservation_through_include_reverse_order() -> Result<()> {
5220 let mut resolve = Resolve::default();
5221 let pkg = resolve.push_str(
5222 "test.wit",
5223 r#"
5224 package foo:bar;
5225
5226 world extended {
5227 include base;
5228 }
5229
5230 world base {
5231 export my-func: func();
5232 }
5233 "#,
5234 )?;
5235
5236 let base_id = resolve.packages[pkg].worlds["base"];
5237 let extended_id = resolve.packages[pkg].worlds["extended"];
5238
5239 let WorldItem::Function(base_func) =
5240 &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5241 else {
5242 panic!("expected function");
5243 };
5244 assert!(base_func.span.is_known());
5245
5246 let WorldItem::Function(extended_func) =
5247 &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5248 else {
5249 panic!("expected function");
5250 };
5251 assert!(extended_func.span.is_known());
5252
5253 Ok(())
5254 }
5255
5256 #[test]
5257 fn span_line_numbers() -> Result<()> {
5258 let mut resolve = Resolve::default();
5259 let pkg = resolve.push_source(
5260 "test.wit",
5261 "package foo:bar;
5262
5263interface my-iface {
5264 type my-type = u32;
5265 my-func: func();
5266}
5267
5268world my-world {
5269 export my-export: func();
5270}
5271",
5272 )?;
5273
5274 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5275 let iface_span = resolve.interfaces[iface_id].span;
5276 let iface_loc = resolve.render_location(iface_span);
5277 assert!(
5278 iface_loc.contains(":3:"),
5279 "interface location was {iface_loc}"
5280 );
5281
5282 let type_id = resolve.interfaces[iface_id].types["my-type"];
5283 let type_span = resolve.types[type_id].span;
5284 let type_loc = resolve.render_location(type_span);
5285 assert!(type_loc.contains(":4:"), "type location was {type_loc}");
5286
5287 let func_span = resolve.interfaces[iface_id].functions["my-func"].span;
5288 let func_loc = resolve.render_location(func_span);
5289 assert!(func_loc.contains(":5:"), "function location was {func_loc}");
5290
5291 let world_id = resolve.packages[pkg].worlds["my-world"];
5292 let world_span = resolve.worlds[world_id].span;
5293 let world_loc = resolve.render_location(world_span);
5294 assert!(world_loc.contains(":8:"), "world location was {world_loc}");
5295
5296 let WorldItem::Function(export_func) =
5297 &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5298 else {
5299 panic!("expected function");
5300 };
5301 let export_loc = resolve.render_location(export_func.span);
5302 assert!(
5303 export_loc.contains(":9:"),
5304 "export location was {export_loc}"
5305 );
5306
5307 Ok(())
5308 }
5309
5310 #[test]
5311 fn span_line_numbers_through_merge() -> Result<()> {
5312 let mut resolve1 = Resolve::default();
5313 resolve1.push_source(
5314 "first.wit",
5315 "package foo:first;
5316
5317interface iface1 {
5318 func1: func();
5319}
5320",
5321 )?;
5322
5323 let mut resolve2 = Resolve::default();
5324 let pkg2 = resolve2.push_source(
5325 "second.wit",
5326 "package foo:second;
5327
5328interface iface2 {
5329 func2: func();
5330}
5331",
5332 )?;
5333
5334 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5335 let remap = resolve1.merge(resolve2)?;
5336 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5337
5338 let iface2_span = resolve1.interfaces[iface2_id].span;
5339 let iface2_loc = resolve1.render_location(iface2_span);
5340 assert!(
5341 iface2_loc.contains("second.wit"),
5342 "should reference second.wit, got {iface2_loc}"
5343 );
5344 assert!(
5345 iface2_loc.contains(":3:"),
5346 "interface should be on line 3, got {iface2_loc}"
5347 );
5348
5349 let func2_span = resolve1.interfaces[iface2_id].functions["func2"].span;
5350 let func2_loc = resolve1.render_location(func2_span);
5351 assert!(
5352 func2_loc.contains("second.wit"),
5353 "should reference second.wit, got {func2_loc}"
5354 );
5355 assert!(
5356 func2_loc.contains(":4:"),
5357 "function should be on line 4, got {func2_loc}"
5358 );
5359
5360 Ok(())
5361 }
5362
5363 #[test]
5364 fn span_line_numbers_multiple_sources() -> Result<()> {
5365 let mut resolve = Resolve::default();
5366
5367 let pkg1 = resolve.push_source(
5368 "first.wit",
5369 "package test:first;
5370
5371interface first-iface {
5372 first-func: func();
5373}
5374",
5375 )?;
5376
5377 let pkg2 = resolve.push_source(
5378 "second.wit",
5379 "package test:second;
5380
5381interface second-iface {
5382 second-func: func();
5383}
5384",
5385 )?;
5386
5387 let iface1_id = resolve.packages[pkg1].interfaces["first-iface"];
5388 let iface1_span = resolve.interfaces[iface1_id].span;
5389 let iface1_loc = resolve.render_location(iface1_span);
5390 assert!(
5391 iface1_loc.contains("first.wit"),
5392 "should reference first.wit, got {iface1_loc}"
5393 );
5394 assert!(
5395 iface1_loc.contains(":3:"),
5396 "interface should be on line 3, got {iface1_loc}"
5397 );
5398
5399 let func1_span = resolve.interfaces[iface1_id].functions["first-func"].span;
5400 let func1_loc = resolve.render_location(func1_span);
5401 assert!(
5402 func1_loc.contains("first.wit"),
5403 "should reference first.wit, got {func1_loc}"
5404 );
5405 assert!(
5406 func1_loc.contains(":4:"),
5407 "function should be on line 4, got {func1_loc}"
5408 );
5409
5410 let iface2_id = resolve.packages[pkg2].interfaces["second-iface"];
5411 let iface2_span = resolve.interfaces[iface2_id].span;
5412 let iface2_loc = resolve.render_location(iface2_span);
5413 assert!(
5414 iface2_loc.contains("second.wit"),
5415 "should reference second.wit, got {iface2_loc}"
5416 );
5417 assert!(
5418 iface2_loc.contains(":3:"),
5419 "interface should be on line 3, got {iface2_loc}"
5420 );
5421
5422 let func2_span = resolve.interfaces[iface2_id].functions["second-func"].span;
5423 let func2_loc = resolve.render_location(func2_span);
5424 assert!(
5425 func2_loc.contains("second.wit"),
5426 "should reference second.wit, got {func2_loc}"
5427 );
5428 assert!(
5429 func2_loc.contains(":4:"),
5430 "function should be on line 4, got {func2_loc}"
5431 );
5432
5433 Ok(())
5434 }
5435
5436 #[test]
5437 fn span_preservation_for_fields_and_cases() -> Result<()> {
5438 use crate::TypeDefKind;
5439
5440 let mut resolve = Resolve::default();
5441 let pkg = resolve.push_str(
5442 "test.wit",
5443 r#"
5444 package foo:bar;
5445
5446 interface my-iface {
5447 record my-record {
5448 field1: u32,
5449 field2: string,
5450 }
5451
5452 flags my-flags {
5453 flag1,
5454 flag2,
5455 }
5456
5457 variant my-variant {
5458 case1,
5459 case2(u32),
5460 }
5461
5462 enum my-enum {
5463 val1,
5464 val2,
5465 }
5466 }
5467 "#,
5468 )?;
5469
5470 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5471
5472 let record_id = resolve.interfaces[iface_id].types["my-record"];
5474 let TypeDefKind::Record(record) = &resolve.types[record_id].kind else {
5475 panic!("expected record");
5476 };
5477 assert!(record.fields[0].span.is_known(), "field1 should have span");
5478 assert!(record.fields[1].span.is_known(), "field2 should have span");
5479
5480 let flags_id = resolve.interfaces[iface_id].types["my-flags"];
5482 let TypeDefKind::Flags(flags) = &resolve.types[flags_id].kind else {
5483 panic!("expected flags");
5484 };
5485 assert!(flags.flags[0].span.is_known(), "flag1 should have span");
5486 assert!(flags.flags[1].span.is_known(), "flag2 should have span");
5487
5488 let variant_id = resolve.interfaces[iface_id].types["my-variant"];
5490 let TypeDefKind::Variant(variant) = &resolve.types[variant_id].kind else {
5491 panic!("expected variant");
5492 };
5493 assert!(variant.cases[0].span.is_known(), "case1 should have span");
5494 assert!(variant.cases[1].span.is_known(), "case2 should have span");
5495
5496 let enum_id = resolve.interfaces[iface_id].types["my-enum"];
5498 let TypeDefKind::Enum(e) = &resolve.types[enum_id].kind else {
5499 panic!("expected enum");
5500 };
5501 assert!(e.cases[0].span.is_known(), "val1 should have span");
5502 assert!(e.cases[1].span.is_known(), "val2 should have span");
5503
5504 Ok(())
5505 }
5506
5507 #[test]
5508 fn span_preservation_for_fields_through_merge() -> Result<()> {
5509 use crate::TypeDefKind;
5510
5511 let mut resolve1 = Resolve::default();
5512 resolve1.push_str(
5513 "test1.wit",
5514 r#"
5515 package foo:bar;
5516
5517 interface iface1 {
5518 record rec1 {
5519 f1: u32,
5520 }
5521 }
5522 "#,
5523 )?;
5524
5525 let mut resolve2 = Resolve::default();
5526 let pkg2 = resolve2.push_str(
5527 "test2.wit",
5528 r#"
5529 package foo:baz;
5530
5531 interface iface2 {
5532 record rec2 {
5533 f2: string,
5534 }
5535
5536 variant var2 {
5537 c2,
5538 }
5539 }
5540 "#,
5541 )?;
5542
5543 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5544 let rec2_old_id = resolve2.interfaces[iface2_old_id].types["rec2"];
5545 let var2_old_id = resolve2.interfaces[iface2_old_id].types["var2"];
5546
5547 let remap = resolve1.merge(resolve2)?;
5548
5549 let rec2_id = remap.types[rec2_old_id.index()].unwrap();
5550 let TypeDefKind::Record(record) = &resolve1.types[rec2_id].kind else {
5551 panic!("expected record");
5552 };
5553 assert!(
5554 record.fields[0].span.is_known(),
5555 "field should have span after merge"
5556 );
5557
5558 let var2_id = remap.types[var2_old_id.index()].unwrap();
5559 let TypeDefKind::Variant(variant) = &resolve1.types[var2_id].kind else {
5560 panic!("expected variant");
5561 };
5562 assert!(
5563 variant.cases[0].span.is_known(),
5564 "case should have span after merge"
5565 );
5566
5567 Ok(())
5568 }
5569
5570 #[test]
5571 fn param_spans_point_to_names() -> Result<()> {
5572 let source = "\
5573package foo:bar;
5574
5575interface iface {
5576 my-func: func(a: u32, b: string);
5577}
5578";
5579 let mut resolve = Resolve::default();
5580 let pkg = resolve.push_str("test.wit", source)?;
5581
5582 let iface_id = resolve.packages[pkg].interfaces["iface"];
5583 let func = &resolve.interfaces[iface_id].functions["my-func"];
5584 assert_eq!(func.params.len(), 2);
5585 for param in &func.params {
5586 let start = param.span.start() as usize;
5587 let end = param.span.end() as usize;
5588 let snippet = &source[start..end];
5589 assert_eq!(
5590 snippet, param.name,
5591 "param `{}` span points to {:?}",
5592 param.name, snippet
5593 );
5594 }
5595
5596 Ok(())
5597 }
5598
5599 #[test]
5600 fn param_spans_preserved_through_merge() -> Result<()> {
5601 let mut resolve1 = Resolve::default();
5602 resolve1.push_str(
5603 "test1.wit",
5604 r#"
5605 package foo:bar;
5606
5607 interface iface1 {
5608 f1: func(x: u32);
5609 }
5610 "#,
5611 )?;
5612
5613 let mut resolve2 = Resolve::default();
5614 let pkg2 = resolve2.push_str(
5615 "test2.wit",
5616 r#"
5617 package foo:baz;
5618
5619 interface iface2 {
5620 f2: func(y: string, z: bool);
5621 }
5622 "#,
5623 )?;
5624
5625 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5626
5627 let remap = resolve1.merge(resolve2)?;
5628
5629 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5630 let func = &resolve1.interfaces[iface2_id].functions["f2"];
5631 for param in &func.params {
5632 assert!(
5633 param.span.is_known(),
5634 "param `{}` should have span after merge",
5635 param.name
5636 );
5637 }
5638
5639 Ok(())
5640 }
5641
5642 #[test]
5647 fn exportize_importize_roundtrip() -> Result<()> {
5648 let mut resolve = Resolve::default();
5649 let pkg = resolve.push_str(
5650 "test.wit",
5651 r#"
5652 package foo:bar;
5653
5654 interface types {
5655 type my-type = u32;
5656 }
5657
5658 interface api {
5659 use types.{my-type};
5660 do-something: func(a: my-type) -> my-type;
5661 }
5662
5663 world w {
5664 export api;
5665 }
5666 "#,
5667 )?;
5668 let world_id = resolve.packages[pkg].worlds["w"];
5669
5670 let original_export_keys: Vec<String> = resolve.worlds[world_id]
5672 .exports
5673 .keys()
5674 .map(|k| resolve.name_world_key(k))
5675 .collect();
5676 assert!(!original_export_keys.is_empty());
5677 assert!(resolve.worlds[world_id].imports.iter().all(|(_, item)| {
5678 matches!(item, WorldItem::Interface { .. })
5681 }));
5682
5683 resolve.importize(world_id, Some("w-temp".to_string()))?;
5685 assert!(
5686 resolve.worlds[world_id].exports.is_empty(),
5687 "importize should leave no exports"
5688 );
5689 for key in &original_export_keys {
5691 assert!(
5692 resolve.worlds[world_id]
5693 .imports
5694 .keys()
5695 .any(|k| resolve.name_world_key(k) == *key),
5696 "expected `{key}` to be an import after importize"
5697 );
5698 }
5699
5700 resolve.exportize(world_id, Some("w-final".to_string()), None)?;
5702 assert!(
5703 !resolve.worlds[world_id].exports.is_empty(),
5704 "exportize should produce exports"
5705 );
5706 let final_export_keys: Vec<String> = resolve.worlds[world_id]
5708 .exports
5709 .keys()
5710 .map(|k| resolve.name_world_key(k))
5711 .collect();
5712 for key in &original_export_keys {
5713 assert!(
5714 final_export_keys.contains(key),
5715 "expected `{key}` to be an export after round-trip, got exports: {final_export_keys:?}"
5716 );
5717 }
5718
5719 Ok(())
5720 }
5721}