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::mem;
8
9use crate::resolve::error::{ResolveError, ResolveErrorKind};
10use crate::*;
11use anyhow::{Context, 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, Function, FunctionKind, Handle, IncludeName, Interface, InterfaceId,
27 LiftLowerAbi, ManglingAndAbi, PackageName, SourceMap, Stability, Type, TypeDef, TypeDefKind,
28 TypeId, TypeIdVisitor, TypeOwner, UnresolvedPackage, UnresolvedPackageGroup, World, WorldId,
29 WorldItem, WorldKey,
30};
31
32pub use clone::CloneMaps;
33
34mod clone;
35pub mod error;
36
37#[cfg(feature = "std")]
38mod fs;
39#[cfg(feature = "std")]
40pub use fs::PackageSourceMap;
41
42#[derive(Default, Clone, Debug)]
56#[cfg_attr(feature = "serde", derive(Serialize))]
57pub struct Resolve {
58 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
63 pub worlds: Arena<World>,
64
65 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
70 pub interfaces: Arena<Interface>,
71
72 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
78 pub types: Arena<TypeDef>,
79
80 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
85 pub packages: Arena<Package>,
86
87 #[cfg_attr(feature = "serde", serde(skip))]
89 pub package_names: IndexMap<PackageName, PackageId>,
90
91 #[cfg_attr(feature = "serde", serde(skip))]
98 pub features: IndexSet<String>,
99
100 #[cfg_attr(feature = "serde", serde(skip))]
102 pub all_features: bool,
103
104 #[cfg_attr(feature = "serde", serde(skip))]
106 pub source_map: SourceMap,
107}
108
109#[derive(Clone, Debug)]
115#[cfg_attr(feature = "serde", derive(Serialize))]
116pub struct Package {
117 pub name: PackageName,
119
120 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
122 pub docs: Docs,
123
124 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
127 pub interfaces: IndexMap<String, InterfaceId>,
128
129 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
131 pub worlds: IndexMap<String, WorldId>,
132}
133
134pub type PackageId = Id<Package>;
135
136#[derive(Clone, Debug)]
138pub struct PackageSources {
139 sources: Vec<Vec<String>>,
140 package_id_to_source_map_idx: BTreeMap<PackageId, usize>,
141}
142
143impl PackageSources {
144 pub fn from_single_source(package_id: PackageId, source: &str) -> Self {
145 Self {
146 sources: vec![vec![source.to_owned()]],
147 package_id_to_source_map_idx: BTreeMap::from([(package_id, 0)]),
148 }
149 }
150
151 pub fn from_source_maps(
152 source_maps: Vec<SourceMap>,
153 package_id_to_source_map_idx: BTreeMap<PackageId, usize>,
154 ) -> PackageSources {
155 for (package_id, idx) in &package_id_to_source_map_idx {
156 if *idx >= source_maps.len() {
157 panic!(
158 "Invalid source map index: {}, package id: {:?}, source maps size: {}",
159 idx,
160 package_id,
161 source_maps.len()
162 )
163 }
164 }
165
166 Self {
167 sources: source_maps
168 .into_iter()
169 .map(|source_map| source_map.source_names().map(|s| s.to_owned()).collect())
170 .collect(),
171 package_id_to_source_map_idx,
172 }
173 }
174
175 pub fn source_names(&self) -> impl Iterator<Item = &str> {
177 self.sources
178 .iter()
179 .flatten()
180 .map(|s| s.as_str())
181 .collect::<IndexSet<&str>>()
182 .into_iter()
183 }
184
185 pub fn package_source_names(&self, id: PackageId) -> Option<impl Iterator<Item = &str>> {
187 self.package_id_to_source_map_idx
188 .get(&id)
189 .map(|&idx| self.sources[idx].iter().map(|s| s.as_str()))
190 }
191}
192
193fn visit<'a>(
195 pkg: &'a UnresolvedPackage,
196 pkg_details_map: &'a BTreeMap<PackageName, (UnresolvedPackage, usize)>,
197 order: &mut IndexSet<PackageName>,
198 visiting: &mut HashSet<&'a PackageName>,
199 source_map_offsets: &[u32],
200) -> ResolveResult<()> {
201 if order.contains(&pkg.name) {
202 return Ok(());
203 }
204
205 let (_, source_map_index) = pkg_details_map
206 .get(&pkg.name)
207 .expect("No pkg_details found for package when doing topological sort");
208 let offset = source_map_offsets[*source_map_index];
209 for (i, (dep, _)) in pkg.foreign_deps.iter().enumerate() {
210 let mut span = pkg.foreign_dep_spans[i];
211 span.adjust(offset);
212 if !visiting.insert(dep) {
213 return Err(ResolveError::from(ResolveErrorKind::PackageCycle {
214 package: dep.clone(),
215 span,
216 }));
217 }
218 if let Some((dep_pkg, _)) = pkg_details_map.get(dep) {
219 visit(
220 dep_pkg,
221 pkg_details_map,
222 order,
223 visiting,
224 source_map_offsets,
225 )?;
226 }
227 assert!(visiting.remove(dep));
228 }
229 assert!(order.insert(pkg.name.clone()));
230 Ok(())
231}
232
233impl Resolve {
234 pub fn new() -> Resolve {
236 Resolve::default()
237 }
238
239 fn sort_unresolved_packages(
243 &mut self,
244 main: UnresolvedPackageGroup,
245 deps: Vec<UnresolvedPackageGroup>,
246 ) -> ResolveResult<(PackageId, PackageSources)> {
247 let mut source_maps: Vec<SourceMap> = Vec::new();
248 let mut all_packages: Vec<(UnresolvedPackage, usize)> = Vec::new();
249
250 let mut collect = |group: UnresolvedPackageGroup| {
251 let UnresolvedPackageGroup {
252 main,
253 nested,
254 source_map,
255 } = group;
256 let i = source_maps.len();
257 source_maps.push(source_map);
258 for pkg in nested.into_iter().chain([main]) {
259 all_packages.push((pkg, i));
260 }
261 };
262
263 let main_name = main.main.name.clone();
264 collect(main);
265 for dep in deps {
266 collect(dep);
267 }
268
269 let source_map_offsets: Vec<u32> = source_maps
274 .iter()
275 .map(|sm| self.push_source_map(sm.clone()))
276 .collect();
277
278 let mut pkg_details_map: BTreeMap<PackageName, (UnresolvedPackage, usize)> =
279 BTreeMap::new();
280 for (pkg, source_map_index) in all_packages {
281 let name = pkg.name.clone();
282 let my_span = pkg.package_name_span;
283 let offset = source_map_offsets[source_map_index];
284 if let Some((prev_pkg, prev_source_map_index)) =
285 pkg_details_map.insert(name.clone(), (pkg, source_map_index))
286 {
287 let prev_offset = source_map_offsets[prev_source_map_index];
288 let mut span1 = my_span;
289 span1.adjust(offset);
290 let mut span2 = prev_pkg.package_name_span;
291 span2.adjust(prev_offset);
292 return Err(ResolveError::from(ResolveErrorKind::DuplicatePackage {
293 name,
294 span1,
295 span2,
296 }));
297 }
298 }
299
300 let mut order = IndexSet::default();
304 {
305 let mut visiting = HashSet::new();
306 for (pkg, _) in pkg_details_map.values() {
307 visit(
308 pkg,
309 &pkg_details_map,
310 &mut order,
311 &mut visiting,
312 &source_map_offsets,
313 )?;
314 }
315 }
316
317 let mut package_id_to_source_map_idx = BTreeMap::new();
318 let mut main_pkg_id = None;
319 for name in order {
320 let (pkg, source_map_index) = pkg_details_map.remove(&name).unwrap();
321 let span_offset = source_map_offsets[source_map_index];
322 let is_main = pkg.name == main_name;
323 let id = self.push(pkg, span_offset)?;
324 if is_main {
325 assert!(main_pkg_id.is_none());
326 main_pkg_id = Some(id);
327 }
328 package_id_to_source_map_idx.insert(id, source_map_index);
329 }
330
331 Ok((
332 main_pkg_id.unwrap(),
333 PackageSources::from_source_maps(source_maps, package_id_to_source_map_idx),
334 ))
335 }
336
337 pub fn push_source_map(&mut self, source_map: SourceMap) -> u32 {
344 self.source_map.append(source_map)
345 }
346
347 pub fn push(
362 &mut self,
363 mut unresolved: UnresolvedPackage,
364 span_offset: u32,
365 ) -> ResolveResult<PackageId> {
366 unresolved.adjust_spans(span_offset);
367 let ret = Remap::default().append(self, unresolved);
368 if ret.is_ok() {
369 #[cfg(debug_assertions)]
370 self.assert_valid();
371 }
372 ret
373 }
374
375 pub fn push_group(
384 &mut self,
385 unresolved_group: UnresolvedPackageGroup,
386 ) -> ResolveResult<PackageId> {
387 let (pkg_id, _) = self.sort_unresolved_packages(unresolved_group, Vec::new())?;
388 Ok(pkg_id)
389 }
390
391 pub fn push_groups(
402 &mut self,
403 main: UnresolvedPackageGroup,
404 deps: Vec<UnresolvedPackageGroup>,
405 ) -> ResolveResult<PackageId> {
406 let (pkg_id, _) = self.sort_unresolved_packages(main, deps)?;
407 Ok(pkg_id)
408 }
409
410 pub fn push_source(&mut self, path: &str, contents: &str) -> anyhow::Result<PackageId> {
416 let mut map = SourceMap::default();
417 map.push_str(path, contents);
418 let group = self.parse_source_map(map)?;
419 Ok(self.push_group(group)?)
420 }
421
422 pub(crate) fn parse_source_map(
429 &mut self,
430 map: SourceMap,
431 ) -> anyhow::Result<UnresolvedPackageGroup> {
432 map.parse().map_err(|(map, mut e)| {
433 let offset = self.source_map.append(map);
434 e.adjust_spans(offset);
435 e.into()
436 })
437 }
438
439 pub fn render_location(&self, span: Span) -> String {
441 self.source_map.render_location(span)
442 }
443
444 #[cfg(feature = "std")]
447 pub fn render_error(&self, err: &anyhow::Error) -> String {
448 crate::render_anyhow_error(err, &self.source_map)
449 }
450
451 pub fn all_bits_valid(&self, ty: &Type) -> bool {
452 match ty {
453 Type::U8
454 | Type::S8
455 | Type::U16
456 | Type::S16
457 | Type::U32
458 | Type::S32
459 | Type::U64
460 | Type::S64
461 | Type::F32
462 | Type::F64 => true,
463
464 Type::Bool | Type::Char | Type::String | Type::ErrorContext => false,
465
466 Type::Id(id) => match &self.types[*id].kind {
467 TypeDefKind::List(_)
468 | TypeDefKind::Map(_, _)
469 | TypeDefKind::Variant(_)
470 | TypeDefKind::Enum(_)
471 | TypeDefKind::Option(_)
472 | TypeDefKind::Result(_)
473 | TypeDefKind::Future(_)
474 | TypeDefKind::Stream(_) => false,
475 TypeDefKind::Type(t) | TypeDefKind::FixedLengthList(t, ..) => {
476 self.all_bits_valid(t)
477 }
478
479 TypeDefKind::Handle(h) => match h {
480 crate::Handle::Own(_) => true,
481 crate::Handle::Borrow(_) => true,
482 },
483
484 TypeDefKind::Resource => false,
485 TypeDefKind::Record(r) => r.fields.iter().all(|f| self.all_bits_valid(&f.ty)),
486 TypeDefKind::Tuple(t) => t.types.iter().all(|t| self.all_bits_valid(t)),
487
488 TypeDefKind::Flags(_) => false,
492
493 TypeDefKind::Unknown => unreachable!(),
494 },
495 }
496 }
497
498 pub fn merge(&mut self, resolve: Resolve) -> anyhow::Result<Remap> {
510 log::trace!(
511 "merging {} packages into {} packages",
512 resolve.packages.len(),
513 self.packages.len()
514 );
515
516 let mut map = MergeMap::new(&resolve, &self);
517 map.build()?;
518 let MergeMap {
519 package_map,
520 interface_map,
521 type_map,
522 world_map,
523 interfaces_to_add,
524 worlds_to_add,
525 ..
526 } = map;
527
528 let mut remap = Remap::default();
547 let Resolve {
548 types,
549 worlds,
550 interfaces,
551 packages,
552 package_names,
553 features: _,
554 source_map,
555 ..
556 } = resolve;
557
558 let span_offset = self.source_map.append(source_map);
559
560 let mut moved_types = Vec::new();
561 for (id, mut ty) in types {
562 let new_id = match type_map.get(&id).copied() {
563 Some(id) => {
564 update_stability(&ty.stability, &mut self.types[id].stability, ty.span)?;
565 id
566 }
567 None => {
568 log::debug!("moving type {:?}", ty.name);
569 moved_types.push(id);
570 remap.update_typedef(self, &mut ty, Default::default())?;
571 ty.adjust_spans(span_offset);
572 self.types.alloc(ty)
573 }
574 };
575 assert_eq!(remap.types.len(), id.index());
576 remap.types.push(Some(new_id));
577 }
578
579 let mut moved_interfaces = Vec::new();
580 for (id, mut iface) in interfaces {
581 let new_id = match interface_map.get(&id).copied() {
582 Some(into_id) => {
583 update_stability(
584 &iface.stability,
585 &mut self.interfaces[into_id].stability,
586 iface.span,
587 )?;
588
589 for (name, from_type_id) in iface.types.iter() {
595 if self.interfaces[into_id].types.contains_key(name) {
596 continue;
597 }
598 let new_type_id = remap.map_type(*from_type_id, Default::default())?;
599 self.interfaces[into_id]
600 .types
601 .insert(name.clone(), new_type_id);
602 }
603
604 let extra_funcs: Vec<_> = iface
608 .functions
609 .into_iter()
610 .filter(|(name, _)| {
611 !self.interfaces[into_id]
612 .functions
613 .contains_key(name.as_str())
614 })
615 .collect();
616 for (name, mut func) in extra_funcs {
617 remap.update_function(self, &mut func, Default::default())?;
618 func.adjust_spans(span_offset);
619 self.interfaces[into_id].functions.insert(name, func);
620 }
621
622 into_id
623 }
624 None => {
625 log::debug!("moving interface {:?}", iface.name);
626 moved_interfaces.push(id);
627 remap.update_interface(self, &mut iface)?;
628 iface.adjust_spans(span_offset);
629 self.interfaces.alloc(iface)
630 }
631 };
632 assert_eq!(remap.interfaces.len(), id.index());
633 remap.interfaces.push(Some(new_id));
634 }
635
636 let mut moved_worlds = Vec::new();
637 for (id, mut world) in worlds {
638 let new_id = match world_map.get(&id).copied() {
639 Some(world_id) => {
640 update_stability(
641 &world.stability,
642 &mut self.worlds[world_id].stability,
643 world.span,
644 )?;
645 for from_import in world.imports.iter() {
646 Resolve::update_world_imports_stability(
647 from_import,
648 &mut self.worlds[world_id].imports,
649 &interface_map,
650 )?;
651 }
652 for from_export in world.exports.iter() {
653 Resolve::update_world_imports_stability(
654 from_export,
655 &mut self.worlds[world_id].exports,
656 &interface_map,
657 )?;
658 }
659 world_id
660 }
661 None => {
662 log::debug!("moving world {}", world.name);
663 moved_worlds.push(id);
664 let mut update =
665 |map: &mut IndexMap<WorldKey, WorldItem>| -> anyhow::Result<_> {
666 for (mut name, mut item) in mem::take(map) {
667 remap.update_world_key(&mut name, Default::default())?;
668 match &mut item {
669 WorldItem::Function(f) => {
670 remap.update_function(self, f, Default::default())?
671 }
672 WorldItem::Interface { id, .. } => {
673 *id = remap.map_interface(*id, Default::default())?;
674 }
675 WorldItem::Type { id, .. } => {
676 *id = remap.map_type(*id, Default::default())?
677 }
678 }
679 map.insert(name, item);
680 }
681 Ok(())
682 };
683 update(&mut world.imports)?;
684 update(&mut world.exports)?;
685 world.adjust_spans(span_offset);
686 self.worlds.alloc(world)
687 }
688 };
689 assert_eq!(remap.worlds.len(), id.index());
690 remap.worlds.push(Some(new_id));
691 }
692
693 for (id, mut pkg) in packages {
694 let new_id = match package_map.get(&id).copied() {
695 Some(id) => id,
696 None => {
697 for (_, id) in pkg.interfaces.iter_mut() {
698 *id = remap.map_interface(*id, Default::default())?;
699 }
700 for (_, id) in pkg.worlds.iter_mut() {
701 *id = remap.map_world(*id, Default::default())?;
702 }
703 self.packages.alloc(pkg)
704 }
705 };
706 assert_eq!(remap.packages.len(), id.index());
707 remap.packages.push(new_id);
708 }
709
710 for (name, id) in package_names {
711 let id = remap.packages[id.index()];
712 if let Some(prev) = self.package_names.insert(name, id) {
713 assert_eq!(prev, id);
714 }
715 }
716
717 for id in moved_worlds {
725 let id = remap.map_world(id, Default::default())?;
726 if let Some(pkg) = self.worlds[id].package.as_mut() {
727 *pkg = remap.packages[pkg.index()];
728 }
729 }
730 for id in moved_interfaces {
731 let id = remap.map_interface(id, Default::default())?;
732 if let Some(pkg) = self.interfaces[id].package.as_mut() {
733 *pkg = remap.packages[pkg.index()];
734 }
735 if let Some(clone_of) = self.interfaces[id].clone_of.as_mut() {
736 *clone_of = remap.map_interface(*clone_of, Default::default())?;
737 }
738 }
739 for id in moved_types {
740 let id = remap.map_type(id, Default::default())?;
741 match &mut self.types[id].owner {
742 TypeOwner::Interface(id) => *id = remap.map_interface(*id, Default::default())?,
743 TypeOwner::World(id) => *id = remap.map_world(*id, Default::default())?,
744 TypeOwner::None => {}
745 }
746 }
747
748 for (name, pkg, iface) in interfaces_to_add {
753 let prev = self.packages[pkg]
754 .interfaces
755 .insert(name, remap.map_interface(iface, Default::default())?);
756 assert!(prev.is_none());
757 }
758 for (name, pkg, world) in worlds_to_add {
759 let prev = self.packages[pkg]
760 .worlds
761 .insert(name, remap.map_world(world, Default::default())?);
762 assert!(prev.is_none());
763 }
764
765 log::trace!("now have {} packages", self.packages.len());
766
767 let world_ids: Vec<_> = self.worlds.iter().map(|(id, _)| id).collect();
771 for world_id in world_ids {
772 let world_span = self.worlds[world_id].span;
773 self.elaborate_world(world_id, world_span)?;
774 }
775
776 #[cfg(debug_assertions)]
777 self.assert_valid();
778 Ok(remap)
779 }
780
781 fn update_world_imports_stability(
782 from_item: (&WorldKey, &WorldItem),
783 into_items: &mut IndexMap<WorldKey, WorldItem>,
784 interface_map: &HashMap<Id<Interface>, Id<Interface>>,
785 ) -> anyhow::Result<()> {
786 match from_item.0 {
787 WorldKey::Name(_) => {
788 Ok(())
790 }
791 key @ WorldKey::Interface(_) => {
792 let new_key = MergeMap::map_name(key, interface_map);
793 if let Some(into) = into_items.get_mut(&new_key) {
794 match (from_item.1, into) {
795 (
796 WorldItem::Interface {
797 id: aid,
798 stability: astability,
799 span: aspan,
800 ..
801 },
802 WorldItem::Interface {
803 id: bid,
804 stability: bstability,
805 ..
806 },
807 ) => {
808 let aid = interface_map.get(aid).copied().unwrap_or(*aid);
809 assert_eq!(aid, *bid);
810 update_stability(astability, bstability, *aspan)?;
811 Ok(())
812 }
813 _ => unreachable!(),
814 }
815 } else {
816 unreachable!()
819 }
820 }
821 }
822 }
823
824 pub fn merge_worlds(
839 &mut self,
840 from: WorldId,
841 into: WorldId,
842 clone_maps: &mut CloneMaps,
843 ) -> anyhow::Result<()> {
844 let mut new_imports = Vec::new();
845 let mut new_exports = Vec::new();
846
847 let from_world = &self.worlds[from];
848 let into_world = &self.worlds[into];
849
850 log::trace!("merging {} into {}", from_world.name, into_world.name);
851
852 for (name, from_import) in from_world.imports.iter() {
860 let name_str = self.name_world_key(name);
861 match into_world.imports.get(name) {
862 Some(into_import) => {
863 log::trace!("info/from shared import on `{name_str}`");
864 self.merge_world_item(from_import, into_import)
865 .with_context(|| format!("failed to merge world import {name_str}"))?;
866 }
867 None => {
868 log::trace!("new import: `{name_str}`");
869 new_imports.push((name.clone(), from_import.clone()));
870 }
871 }
872 }
873
874 let mut must_be_imported = HashMap::new();
881 for (key, export) in into_world.exports.iter() {
882 for dep in self.world_item_direct_deps(export) {
883 if into_world.exports.contains_key(&WorldKey::Interface(dep)) {
884 continue;
885 }
886 self.foreach_interface_dep(dep, &mut |id| {
887 must_be_imported.insert(id, key.clone());
888 });
889 }
890 }
891
892 for (name, from_export) in from_world.exports.iter() {
895 let name_str = self.name_world_key(name);
896 match into_world.exports.get(name) {
897 Some(into_export) => {
898 log::trace!("info/from shared export on `{name_str}`");
899 self.merge_world_item(from_export, into_export)
900 .with_context(|| format!("failed to merge world export {name_str}"))?;
901 }
902 None => {
903 log::trace!("new export `{name_str}`");
904 self.ensure_can_add_world_export(
907 into_world,
908 name,
909 from_export,
910 &must_be_imported,
911 )
912 .with_context(|| {
913 format!("failed to add export `{}`", self.name_world_key(name))
914 })?;
915 new_exports.push((name.clone(), from_export.clone()));
916 }
917 }
918 }
919
920 let mut cloner = clone::Cloner::new(
934 self,
935 clone_maps,
936 TypeOwner::World(from),
937 TypeOwner::World(into),
938 );
939 cloner.register_world_type_overlap(from, into);
940 for (name, item) in new_imports.iter_mut().chain(&mut new_exports) {
941 cloner.world_item(name, item);
942 }
943
944 let into_world = &mut self.worlds[into];
946 for (name, import) in new_imports {
947 let prev = into_world.imports.insert(name, import);
948 assert!(prev.is_none());
949 }
950 for (name, export) in new_exports {
951 let prev = into_world.exports.insert(name, export);
952 assert!(prev.is_none());
953 }
954
955 #[cfg(debug_assertions)]
956 self.assert_valid();
957 Ok(())
958 }
959
960 fn merge_world_item(&self, from: &WorldItem, into: &WorldItem) -> anyhow::Result<()> {
961 let mut map = MergeMap::new(self, self);
962 match (from, into) {
963 (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
964 if from == into {
969 return Ok(());
970 }
971
972 map.build_interface(*from, *into)
982 .context("failed to merge interfaces")?;
983 }
984
985 (WorldItem::Function(from), WorldItem::Function(into)) => {
988 map.build_function(from, into)
989 .context("failed to merge functions")?;
990 }
991 (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
992 map.build_type_id(*from, *into)
993 .context("failed to merge types")?;
994 }
995
996 (WorldItem::Interface { .. }, _)
998 | (WorldItem::Function { .. }, _)
999 | (WorldItem::Type { .. }, _) => {
1000 bail!("different kinds of items");
1001 }
1002 }
1003 assert!(map.interfaces_to_add.is_empty());
1004 assert!(map.worlds_to_add.is_empty());
1005 Ok(())
1006 }
1007
1008 fn ensure_can_add_world_export(
1020 &self,
1021 into: &World,
1022 name: &WorldKey,
1023 item: &WorldItem,
1024 must_be_imported: &HashMap<InterfaceId, WorldKey>,
1025 ) -> anyhow::Result<()> {
1026 assert!(!into.exports.contains_key(name));
1027 let name = self.name_world_key(name);
1028
1029 for dep in self.world_item_direct_deps(item) {
1033 if into.exports.contains_key(&WorldKey::Interface(dep)) {
1034 continue;
1035 }
1036 self.ensure_not_exported(into, dep)
1037 .with_context(|| format!("failed validating export of `{name}`"))?;
1038 }
1039
1040 if let WorldItem::Interface { id, .. } = item {
1044 if let Some(export) = must_be_imported.get(id) {
1045 let export_name = self.name_world_key(export);
1046 bail!(
1047 "export `{export_name}` depends on `{name}` \
1048 previously as an import which will change meaning \
1049 if `{name}` is added as an export"
1050 );
1051 }
1052 }
1053
1054 Ok(())
1055 }
1056
1057 fn ensure_not_exported(&self, world: &World, id: InterfaceId) -> anyhow::Result<()> {
1058 let key = WorldKey::Interface(id);
1059 let name = self.name_world_key(&key);
1060 if world.exports.contains_key(&key) {
1061 bail!(
1062 "world exports `{name}` but it's also transitively used by an \
1063 import \
1064 which means that this is not valid"
1065 )
1066 }
1067 for dep in self.interface_direct_deps(id) {
1068 self.ensure_not_exported(world, dep)
1069 .with_context(|| format!("failed validating transitive import dep `{name}`"))?;
1070 }
1071 Ok(())
1072 }
1073
1074 fn world_item_direct_deps(&self, item: &WorldItem) -> impl Iterator<Item = InterfaceId> + '_ {
1080 let mut interface = None;
1081 let mut ty = None;
1082 match item {
1083 WorldItem::Function(_) => {}
1084 WorldItem::Type { id, .. } => ty = Some(*id),
1085 WorldItem::Interface { id, .. } => interface = Some(*id),
1086 }
1087
1088 interface
1089 .into_iter()
1090 .flat_map(move |id| self.interface_direct_deps(id))
1091 .chain(ty.and_then(|t| self.type_interface_dep(t)))
1092 }
1093
1094 fn foreach_interface_dep(&self, id: InterfaceId, f: &mut dyn FnMut(InterfaceId)) {
1098 self._foreach_interface_dep(id, f, &mut HashSet::new())
1099 }
1100
1101 fn _foreach_interface_dep(
1105 &self,
1106 id: InterfaceId,
1107 f: &mut dyn FnMut(InterfaceId),
1108 visited: &mut HashSet<InterfaceId>,
1109 ) {
1110 if !visited.insert(id) {
1111 return;
1112 }
1113 f(id);
1114 for dep in self.interface_direct_deps(id) {
1115 self._foreach_interface_dep(dep, f, visited);
1116 }
1117 }
1118
1119 pub fn id_of(&self, interface: InterfaceId) -> Option<String> {
1123 let interface = &self.interfaces[interface];
1124 Some(self.id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1125 }
1126
1127 pub fn canonicalized_id_of(&self, interface: InterfaceId) -> Option<String> {
1132 let interface = &self.interfaces[interface];
1133 Some(self.canonicalized_id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1134 }
1135
1136 fn rename_world(
1141 &mut self,
1142 world_id: WorldId,
1143 out_world_name: Option<String>,
1144 default_suffix: &str,
1145 ) {
1146 let world = &mut self.worlds[world_id];
1147 let pkg = &mut self.packages[world.package.unwrap()];
1148 pkg.worlds.shift_remove(&world.name);
1149 if let Some(name) = out_world_name {
1150 world.name = name.clone();
1151 pkg.worlds.insert(name, world_id);
1152 } else {
1153 world.name.push_str(default_suffix);
1154 pkg.worlds.insert(world.name.clone(), world_id);
1155 }
1156 }
1157
1158 pub fn importize(
1174 &mut self,
1175 world_id: WorldId,
1176 out_world_name: Option<String>,
1177 ) -> anyhow::Result<()> {
1178 self.rename_world(world_id, out_world_name, "-importized");
1179
1180 let world = &mut self.worlds[world_id];
1183 world.imports.retain(|_, item| match item {
1184 WorldItem::Type { .. } => true,
1185 _ => false,
1186 });
1187
1188 for (name, export) in mem::take(&mut world.exports) {
1189 match (name.clone(), world.imports.insert(name, export)) {
1190 (_, None) => {}
1192
1193 (WorldKey::Name(name), Some(_)) => {
1195 bail!("world export `{name}` conflicts with import of same name");
1196 }
1197
1198 (WorldKey::Interface(_), _) => unreachable!(),
1201 }
1202 }
1203
1204 let world_span = world.span;
1207 self.elaborate_world(world_id, world_span)?;
1208
1209 #[cfg(debug_assertions)]
1210 self.assert_valid();
1211 Ok(())
1212 }
1213
1214 pub fn exportize(
1233 &mut self,
1234 world_id: WorldId,
1235 out_world_name: Option<String>,
1236 filter: Option<&dyn Fn(&WorldKey, &WorldItem) -> bool>,
1237 ) -> anyhow::Result<()> {
1238 self.rename_world(world_id, out_world_name, "-exportized");
1239
1240 let world = &mut self.worlds[world_id];
1241 world.exports.clear();
1242
1243 let old_imports = mem::take(&mut world.imports);
1244 for (name, import) in old_imports {
1245 let should_move = match &filter {
1246 Some(f) => f(&name, &import),
1247 None => true,
1248 };
1249 if should_move {
1250 world.exports.insert(name, import);
1251 } else {
1252 world.imports.insert(name, import);
1253 }
1254 }
1255
1256 let world_span = world.span;
1259 self.elaborate_world(world_id, world_span)?;
1260
1261 #[cfg(debug_assertions)]
1262 self.assert_valid();
1263 Ok(())
1264 }
1265
1266 pub fn id_of_name(&self, pkg: PackageId, name: &str) -> String {
1268 let package = &self.packages[pkg];
1269 let mut base = String::new();
1270 base.push_str(&package.name.namespace);
1271 base.push_str(":");
1272 base.push_str(&package.name.name);
1273 base.push_str("/");
1274 base.push_str(name);
1275 if let Some(version) = &package.name.version {
1276 base.push_str(&format!("@{version}"));
1277 }
1278 base
1279 }
1280
1281 pub fn canonicalized_id_of_name(&self, pkg: PackageId, name: &str) -> String {
1287 let package = &self.packages[pkg];
1288 let mut base = String::new();
1289 base.push_str(&package.name.namespace);
1290 base.push_str(":");
1291 base.push_str(&package.name.name);
1292 base.push_str("/");
1293 base.push_str(name);
1294 if let Some(version) = &package.name.version {
1295 base.push_str("@");
1296 let string = PackageName::version_compat_track_string(version);
1297 base.push_str(&string);
1298 }
1299 base
1300 }
1301
1302 pub fn select_world(
1417 &self,
1418 main_packages: &[PackageId],
1419 world: Option<&str>,
1420 ) -> anyhow::Result<WorldId> {
1421 let world_path = match world {
1423 Some(world) => Some(
1424 parse_use_path(world)
1425 .with_context(|| format!("failed to parse world specifier `{world}`"))?,
1426 ),
1427 None => None,
1428 };
1429
1430 match world_path {
1431 Some(world_path) => {
1433 let (pkg, world_name) = match (main_packages, world_path) {
1434 ([], _) => bail!("No main packages defined"),
1436
1437 ([main_package], ParsedUsePath::Name(name)) => (*main_package, name),
1439
1440 (_, ParsedUsePath::Name(_name)) => {
1442 bail!(
1443 "There are multiple main packages; a world must be explicitly chosen:{}",
1444 self.worlds
1445 .iter()
1446 .map(|world| format!(
1447 "\n {}",
1448 self.id_of_name(world.1.package.unwrap(), &world.1.name)
1449 ))
1450 .collect::<String>()
1451 )
1452 }
1453
1454 (_, ParsedUsePath::Package(pkg, world_name)) => {
1456 let pkg = match self.package_names.get(&pkg) {
1457 Some(pkg) => *pkg,
1458 None => {
1459 let mut candidates =
1460 self.package_names.iter().filter(|(name, _)| {
1461 pkg.version.is_none()
1462 && pkg.name == name.name
1463 && pkg.namespace == name.namespace
1464 && name.version.is_some()
1465 });
1466 let candidate = candidates.next();
1467 if let Some((c2, _)) = candidates.next() {
1468 let (c1, _) = candidate.unwrap();
1469 bail!(
1470 "package name `{pkg}` is available at both \
1471 versions {} and {} but which is not specified",
1472 c1.version.as_ref().unwrap(),
1473 c2.version.as_ref().unwrap(),
1474 );
1475 }
1476 match candidate {
1477 Some((_, id)) => *id,
1478 None => bail!("unknown package `{pkg}`"),
1479 }
1480 }
1481 };
1482 (pkg, world_name.to_string())
1483 }
1484 };
1485
1486 let pkg = &self.packages[pkg];
1488 pkg.worlds.get(&world_name).copied().ok_or_else(|| {
1489 anyhow!("World `{world_name}` not found in package `{}`", pkg.name)
1490 })
1491 }
1492
1493 None => match main_packages {
1495 [] => bail!("No main packages defined"),
1496
1497 [main_package] => {
1499 let pkg = &self.packages[*main_package];
1500 match pkg.worlds.len() {
1501 0 => bail!("The main package `{}` contains no worlds", pkg.name),
1502 1 => Ok(pkg.worlds[0]),
1503 _ => bail!(
1504 "There are multiple worlds in `{}`; one must be explicitly chosen:{}",
1505 pkg.name,
1506 pkg.worlds
1507 .values()
1508 .map(|world| format!(
1509 "\n {}",
1510 self.id_of_name(*main_package, &self.worlds[*world].name)
1511 ))
1512 .collect::<String>()
1513 ),
1514 }
1515 }
1516
1517 _ => {
1519 bail!(
1520 "There are multiple main packages; a world must be explicitly chosen:{}",
1521 self.worlds
1522 .iter()
1523 .map(|world| format!(
1524 "\n {}",
1525 self.id_of_name(world.1.package.unwrap(), &world.1.name)
1526 ))
1527 .collect::<String>()
1528 )
1529 }
1530 },
1531 }
1532 }
1533
1534 pub fn name_world_key(&self, key: &WorldKey) -> String {
1536 match key {
1537 WorldKey::Name(s) => s.to_string(),
1538 WorldKey::Interface(i) => self.id_of(*i).expect("unexpected anonymous interface"),
1539 }
1540 }
1541
1542 pub fn name_canonicalized_world_key(&self, key: &WorldKey) -> String {
1545 match key {
1546 WorldKey::Name(s) => s.to_string(),
1547 WorldKey::Interface(i) => self
1548 .canonicalized_id_of(*i)
1549 .expect("unexpected anonymous interface"),
1550 }
1551 }
1552
1553 pub fn implements_value(&self, key: &WorldKey, item: &WorldItem) -> Option<String> {
1558 if let WorldKey::Name(_) = key {
1559 if let WorldItem::Interface { id, .. } = item {
1560 if self.interfaces[*id].name.is_some() {
1561 return Some(self.id_of(*id).unwrap().into());
1562 }
1563 }
1564 }
1565 None
1566 }
1567
1568 pub fn external_id_value(&self, key: &WorldKey, item: &WorldItem) -> Option<String> {
1573 let _ = key;
1574 match item {
1575 WorldItem::Interface { external_id, .. } => external_id.clone(),
1576 WorldItem::Function(f) => f.external_id.clone(),
1577 WorldItem::Type { id, .. } => self.types[*id].external_id.clone(),
1578 }
1579 }
1580
1581 pub fn type_interface_dep(&self, id: TypeId) -> Option<InterfaceId> {
1587 let ty = &self.types[id];
1588 let dep = match ty.kind {
1589 TypeDefKind::Type(Type::Id(id)) => id,
1590 _ => return None,
1591 };
1592 let other = &self.types[dep];
1593 if ty.owner == other.owner {
1594 None
1595 } else {
1596 match other.owner {
1597 TypeOwner::Interface(id) => Some(id),
1598 _ => unreachable!(),
1599 }
1600 }
1601 }
1602
1603 pub fn interface_direct_deps(&self, id: InterfaceId) -> impl Iterator<Item = InterfaceId> + '_ {
1613 self.interfaces[id]
1614 .types
1615 .iter()
1616 .filter_map(move |(_name, ty)| self.type_interface_dep(*ty))
1617 }
1618
1619 pub fn package_direct_deps(&self, id: PackageId) -> impl Iterator<Item = PackageId> + '_ {
1629 let pkg = &self.packages[id];
1630
1631 pkg.interfaces
1632 .iter()
1633 .flat_map(move |(_name, id)| self.interface_direct_deps(*id))
1634 .chain(pkg.worlds.iter().flat_map(move |(_name, id)| {
1635 let world = &self.worlds[*id];
1636 world
1637 .imports
1638 .iter()
1639 .chain(world.exports.iter())
1640 .filter_map(move |(_name, item)| match item {
1641 WorldItem::Interface { id, .. } => Some(*id),
1642 WorldItem::Function(_) => None,
1643 WorldItem::Type { id, .. } => self.type_interface_dep(*id),
1644 })
1645 }))
1646 .filter_map(move |iface_id| {
1647 let pkg = self.interfaces[iface_id].package?;
1648 if pkg == id { None } else { Some(pkg) }
1649 })
1650 }
1651
1652 pub fn topological_packages(&self) -> Vec<PackageId> {
1658 let mut pushed = vec![false; self.packages.len()];
1659 let mut order = Vec::new();
1660 for (id, _) in self.packages.iter() {
1661 self.build_topological_package_ordering(id, &mut pushed, &mut order);
1662 }
1663 order
1664 }
1665
1666 fn build_topological_package_ordering(
1667 &self,
1668 id: PackageId,
1669 pushed: &mut Vec<bool>,
1670 order: &mut Vec<PackageId>,
1671 ) {
1672 if pushed[id.index()] {
1673 return;
1674 }
1675 for dep in self.package_direct_deps(id) {
1676 self.build_topological_package_ordering(dep, pushed, order);
1677 }
1678 order.push(id);
1679 pushed[id.index()] = true;
1680 }
1681
1682 #[doc(hidden)]
1683 pub fn assert_valid(&self) {
1684 let mut package_interfaces = Vec::new();
1685 let mut package_worlds = Vec::new();
1686 for (id, pkg) in self.packages.iter() {
1687 let mut interfaces = HashSet::new();
1688 for (name, iface) in pkg.interfaces.iter() {
1689 assert!(interfaces.insert(*iface));
1690 let iface = &self.interfaces[*iface];
1691 assert_eq!(name, iface.name.as_ref().unwrap());
1692 assert_eq!(iface.package.unwrap(), id);
1693 }
1694 package_interfaces.push(pkg.interfaces.values().copied().collect::<HashSet<_>>());
1695 let mut worlds = HashSet::new();
1696 for (name, world) in pkg.worlds.iter() {
1697 assert!(worlds.insert(*world));
1698 assert_eq!(
1699 pkg.worlds.get_key_value(name),
1700 Some((name, world)),
1701 "`MutableKeys` impl may have been used to change a key's hash or equality"
1702 );
1703 let world = &self.worlds[*world];
1704 assert_eq!(*name, world.name);
1705 assert_eq!(world.package.unwrap(), id);
1706 }
1707 package_worlds.push(pkg.worlds.values().copied().collect::<HashSet<_>>());
1708 }
1709
1710 let mut interface_types = Vec::new();
1711 for (id, iface) in self.interfaces.iter() {
1712 assert!(self.packages.get(iface.package.unwrap()).is_some());
1713 if iface.name.is_some() {
1714 match iface.clone_of {
1715 Some(other) => {
1716 assert_eq!(iface.name, self.interfaces[other].name);
1717 }
1718 None => {
1719 assert!(package_interfaces[iface.package.unwrap().index()].contains(&id));
1720 }
1721 }
1722 }
1723
1724 for (name, ty) in iface.types.iter() {
1725 let ty = &self.types[*ty];
1726 assert_eq!(ty.name.as_ref(), Some(name));
1727 assert_eq!(ty.owner, TypeOwner::Interface(id));
1728 }
1729 interface_types.push(iface.types.values().copied().collect::<HashSet<_>>());
1730 for (name, f) in iface.functions.iter() {
1731 assert_eq!(*name, f.name);
1732 }
1733 }
1734
1735 let mut world_types = Vec::new();
1736 for (id, world) in self.worlds.iter() {
1737 log::debug!("validating world {}", &world.name);
1738 if let Some(package) = world.package {
1739 assert!(self.packages.get(package).is_some());
1740 assert!(package_worlds[package.index()].contains(&id));
1741 }
1742 assert!(world.includes.is_empty());
1743
1744 let mut types = HashSet::new();
1745 for (name, item) in world.imports.iter().chain(world.exports.iter()) {
1746 log::debug!("validating world item: {}", self.name_world_key(name));
1747 match item {
1748 WorldItem::Interface { id, .. } => {
1749 if matches!(name, WorldKey::Name(_)) {
1753 let iface = &self.interfaces[*id];
1754 if iface.name.is_none() {
1755 assert_eq!(iface.package, world.package);
1756 }
1757 }
1758 }
1759 WorldItem::Function(f) => {
1760 assert!(!matches!(name, WorldKey::Interface(_)));
1761 assert_eq!(f.name, name.clone().unwrap_name());
1762 }
1763 WorldItem::Type { id: ty, .. } => {
1764 assert!(!matches!(name, WorldKey::Interface(_)));
1765 assert!(types.insert(*ty));
1766 let ty = &self.types[*ty];
1767 assert_eq!(ty.name, Some(name.clone().unwrap_name()));
1768 assert_eq!(ty.owner, TypeOwner::World(id));
1769 }
1770 }
1771 }
1772 self.assert_world_elaborated(world);
1773 world_types.push(types);
1774 }
1775
1776 for (ty_id, ty) in self.types.iter() {
1777 match ty.owner {
1778 TypeOwner::Interface(id) => {
1779 assert!(self.interfaces.get(id).is_some());
1780 assert!(interface_types[id.index()].contains(&ty_id));
1781 }
1782 TypeOwner::World(id) => {
1783 assert!(self.worlds.get(id).is_some());
1784 assert!(world_types[id.index()].contains(&ty_id));
1785 }
1786 TypeOwner::None => {}
1787 }
1788 }
1789
1790 self.assert_topologically_sorted();
1791 }
1792
1793 fn assert_topologically_sorted(&self) {
1794 let mut positions = IndexMap::default();
1795 for id in self.topological_packages() {
1796 let pkg = &self.packages[id];
1797 log::debug!("pkg {}", pkg.name);
1798 let prev = positions.insert(Some(id), IndexSet::default());
1799 assert!(prev.is_none());
1800 }
1801 positions.insert(None, IndexSet::default());
1802
1803 for (id, iface) in self.interfaces.iter() {
1804 log::debug!("iface {:?}", iface.name);
1805 let ok = positions.get_mut(&iface.package).unwrap().insert(id);
1806 assert!(ok);
1807 }
1808
1809 for (_, world) in self.worlds.iter() {
1810 log::debug!("world {:?}", world.name);
1811
1812 let my_package = world.package;
1813 let my_package_pos = positions.get_index_of(&my_package).unwrap();
1814
1815 for (_, item) in world.imports.iter().chain(&world.exports) {
1816 let id = match item {
1817 WorldItem::Interface { id, .. } => *id,
1818 _ => continue,
1819 };
1820 let other_package = self.interfaces[id].package;
1821 let other_package_pos = positions.get_index_of(&other_package).unwrap();
1822
1823 assert!(other_package_pos <= my_package_pos);
1824 }
1825 }
1826
1827 for (_id, ty) in self.types.iter() {
1828 log::debug!("type {:?} {:?}", ty.name, ty.owner);
1829 let other_id = match ty.kind {
1830 TypeDefKind::Type(Type::Id(ty)) => ty,
1831 _ => continue,
1832 };
1833 let other = &self.types[other_id];
1834 if ty.kind == other.kind {
1835 continue;
1836 }
1837 let my_interface = match ty.owner {
1838 TypeOwner::Interface(id) => id,
1839 _ => continue,
1840 };
1841 let other_interface = match other.owner {
1842 TypeOwner::Interface(id) => id,
1843 _ => continue,
1844 };
1845
1846 let my_package = self.interfaces[my_interface].package;
1847 let other_package = self.interfaces[other_interface].package;
1848 let my_package_pos = positions.get_index_of(&my_package).unwrap();
1849 let other_package_pos = positions.get_index_of(&other_package).unwrap();
1850
1851 assert!(other_package_pos <= my_package_pos);
1852 }
1853 }
1854
1855 fn assert_world_elaborated(&self, world: &World) {
1856 for (key, item) in world.imports.iter() {
1857 log::debug!(
1858 "asserting elaborated world import {}",
1859 self.name_world_key(key)
1860 );
1861 match item {
1862 WorldItem::Type { id, .. } => self.assert_world_imports_type_deps(world, key, *id),
1863
1864 WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1866
1867 WorldItem::Interface { id, .. } => {
1869 for dep in self.interface_direct_deps(*id) {
1870 assert!(
1871 world.imports.contains_key(&WorldKey::Interface(dep)),
1872 "world import of {} is missing transitive dep of {}",
1873 self.name_world_key(key),
1874 self.id_of(dep).unwrap(),
1875 );
1876 }
1877 }
1878 }
1879 }
1880 for (key, item) in world.exports.iter() {
1881 log::debug!(
1882 "asserting elaborated world export {}",
1883 self.name_world_key(key)
1884 );
1885 match item {
1886 WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1888
1889 WorldItem::Interface { id, .. } => {
1893 for dep in self.interface_direct_deps(*id) {
1894 let dep_key = WorldKey::Interface(dep);
1895 if world.exports.contains_key(&dep_key) {
1896 continue;
1897 }
1898 self.foreach_interface_dep(dep, &mut |dep| {
1899 let dep_key = WorldKey::Interface(dep);
1900 assert!(
1901 world.imports.contains_key(&dep_key),
1902 "world should import {} (required by {})",
1903 self.name_world_key(&dep_key),
1904 self.name_world_key(key),
1905 );
1906 assert!(
1907 !world.exports.contains_key(&dep_key),
1908 "world should not export {} (required by {})",
1909 self.name_world_key(&dep_key),
1910 self.name_world_key(key),
1911 );
1912 });
1913 }
1914 }
1915
1916 WorldItem::Type { .. } => unreachable!(),
1918 }
1919 }
1920 }
1921
1922 fn assert_world_imports_type_deps(&self, world: &World, key: &WorldKey, ty: TypeId) {
1923 let ty = &self.types[ty];
1926 if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
1927 if let TypeOwner::Interface(id) = self.types[other].owner {
1928 let key = WorldKey::Interface(id);
1929 assert!(world.imports.contains_key(&key));
1930 return;
1931 }
1932 }
1933
1934 let mut visitor = MyVisit(self, Vec::new());
1938 visitor.visit_type_def(self, ty);
1939 for ty in visitor.1 {
1940 let ty = &self.types[ty];
1941 let Some(name) = ty.name.clone() else {
1942 continue;
1943 };
1944 let dep_key = WorldKey::Name(name);
1945 assert!(
1946 world.imports.contains_key(&dep_key),
1947 "world import `{}` should also force an import of `{}`",
1948 self.name_world_key(key),
1949 self.name_world_key(&dep_key),
1950 );
1951 }
1952
1953 struct MyVisit<'a>(&'a Resolve, Vec<TypeId>);
1954
1955 impl TypeIdVisitor for MyVisit<'_> {
1956 fn before_visit_type_id(&mut self, id: TypeId) -> bool {
1957 self.1.push(id);
1958 self.0.types[id].name.is_none()
1960 }
1961 }
1962 }
1963
1964 fn assert_world_function_imports_types(&self, world: &World, key: &WorldKey, func: &Function) {
1968 for ty in func
1969 .parameter_and_result_types()
1970 .chain(func.kind.resource().map(Type::Id))
1971 {
1972 let Type::Id(id) = ty else {
1973 continue;
1974 };
1975 self.assert_world_imports_type_deps(world, key, id);
1976 }
1977 }
1978
1979 fn include_stability(
1995 &self,
1996 stability: &Stability,
1997 pkg_id: &PackageId,
1998 span: Span,
1999 ) -> ResolveResult<bool> {
2000 Ok(match stability {
2001 Stability::Unknown => true,
2002 Stability::Stable { since, .. } => {
2005 let Some(p) = self.packages.get(*pkg_id) else {
2006 return Ok(true);
2014 };
2015
2016 let package_version = p.name.version.as_ref().ok_or_else(|| {
2019 ResolveError::new_semantic(
2020 span,
2021 format!(
2022 "package [{}] contains a feature gate with a version \
2023 specifier, so it must have a version",
2024 p.name
2025 ),
2026 )
2027 })?;
2028
2029 if since > package_version {
2033 return Err(ResolveError::new_semantic(
2034 span,
2035 format!(
2036 "feature gate cannot reference unreleased version \
2037 {since} of package [{}] (current version {package_version})",
2038 p.name
2039 ),
2040 ));
2041 }
2042
2043 true
2044 }
2045 Stability::Unstable { feature, .. } => {
2046 self.features.contains(feature) || self.all_features
2047 }
2048 })
2049 }
2050
2051 fn elaborate_world(&mut self, world_id: WorldId, span: Span) -> ResolveResult<()> {
2063 let mut new_imports = IndexMap::default();
2067 let world = &self.worlds[world_id];
2068
2069 let sort_key = |resolve: &Resolve, item: &WorldItem| match item {
2092 WorldItem::Interface { .. } => 0,
2093 WorldItem::Type { id, .. } => {
2094 let ty = &resolve.types[*id];
2095 match ty.kind {
2096 TypeDefKind::Type(Type::Id(t)) if resolve.types[t].owner != ty.owner => 1,
2097 _ => 2,
2098 }
2099 }
2100 WorldItem::Function(f) => {
2101 if f.kind.resource().is_none() {
2102 3
2103 } else {
2104 4
2105 }
2106 }
2107 };
2108
2109 let mut world_imports = world.imports.iter().collect::<Vec<_>>();
2112 world_imports.sort_by_key(|(_name, import)| sort_key(self, import));
2113 for (name, item) in world_imports {
2114 match item {
2115 WorldItem::Interface {
2118 id,
2119 stability,
2120 docs,
2121 external_id,
2122 ..
2123 } => {
2124 self.elaborate_world_import(
2125 &mut new_imports,
2126 name.clone(),
2127 *id,
2128 &stability,
2129 docs,
2130 external_id.as_deref(),
2131 );
2132 }
2133
2134 WorldItem::Function(_) => {
2137 let prev = new_imports.insert(name.clone(), item.clone());
2138 assert!(prev.is_none());
2139 }
2140
2141 WorldItem::Type { id, .. } => {
2145 if let Some(dep) = self.type_interface_dep(*id) {
2146 self.elaborate_world_import(
2147 &mut new_imports,
2148 WorldKey::Interface(dep),
2149 dep,
2150 &self.types[*id].stability,
2151 &Docs::default(),
2152 None,
2153 );
2154 }
2155 let prev = new_imports.insert(name.clone(), item.clone());
2156 assert!(prev.is_none());
2157 }
2158 }
2159 }
2160
2161 let mut new_exports = IndexMap::default();
2167 let mut export_interfaces = IndexMap::default();
2168 for (name, item) in world.exports.iter() {
2169 match item {
2170 WorldItem::Interface { .. } => {
2171 let prev = export_interfaces.insert(name.clone(), item.clone());
2172 assert!(prev.is_none());
2173 }
2174 WorldItem::Function(_) => {
2175 let prev = new_exports.insert(name.clone(), item.clone());
2176 assert!(prev.is_none());
2177 }
2178 WorldItem::Type { .. } => unreachable!(),
2179 }
2180 }
2181
2182 self.elaborate_world_exports(&export_interfaces, &mut new_imports, &mut new_exports, span)?;
2183
2184 new_imports.sort_by_cached_key(|_name, import| sort_key(self, import));
2188
2189 log::trace!("imports = {new_imports:?}");
2192 log::trace!("exports = {new_exports:?}");
2193 let world = &mut self.worlds[world_id];
2194 world.imports = new_imports;
2195 world.exports = new_exports;
2196
2197 Ok(())
2198 }
2199
2200 fn elaborate_world_import(
2201 &self,
2202 imports: &mut IndexMap<WorldKey, WorldItem>,
2203 key: WorldKey,
2204 id: InterfaceId,
2205 stability: &Stability,
2206 docs: &Docs,
2207 external_id: Option<&str>,
2208 ) {
2209 if imports.contains_key(&key) {
2210 return;
2211 }
2212 for dep in self.interface_direct_deps(id) {
2215 self.elaborate_world_import(
2216 imports,
2217 WorldKey::Interface(dep),
2218 dep,
2219 stability,
2220 &Docs::default(),
2221 None,
2222 );
2223 }
2224 let prev = imports.insert(
2225 key,
2226 WorldItem::Interface {
2227 id,
2228 stability: stability.clone(),
2229 docs: docs.clone(),
2230 span: Default::default(),
2231 external_id: external_id.map(|s| s.to_string()),
2232 },
2233 );
2234 assert!(prev.is_none());
2235 }
2236
2237 fn elaborate_world_exports(
2284 &self,
2285 export_interfaces: &IndexMap<WorldKey, WorldItem>,
2286 imports: &mut IndexMap<WorldKey, WorldItem>,
2287 exports: &mut IndexMap<WorldKey, WorldItem>,
2288 span: Span,
2289 ) -> ResolveResult<()> {
2290 let mut required_imports = HashSet::new();
2291 for (key, item) in export_interfaces.iter() {
2292 let name = self.name_world_key(&key);
2293 let ok = add_world_export(
2294 self,
2295 imports,
2296 exports,
2297 &export_interfaces,
2298 &mut required_imports,
2299 key.clone(),
2300 item.clone(),
2301 true,
2302 );
2303 if !ok {
2304 return Err(ResolveError::from(
2322 ResolveErrorKind::InvalidTransitiveDependency { name, span },
2323 ));
2324 }
2325 }
2326 return Ok(());
2327
2328 fn add_world_export(
2329 resolve: &Resolve,
2330 imports: &mut IndexMap<WorldKey, WorldItem>,
2331 exports: &mut IndexMap<WorldKey, WorldItem>,
2332 export_interfaces: &IndexMap<WorldKey, WorldItem>,
2333 required_imports: &mut HashSet<InterfaceId>,
2334 key: WorldKey,
2335 item: WorldItem,
2336 add_export: bool,
2337 ) -> bool {
2338 if exports.contains_key(&key) {
2339 if add_export {
2340 return true;
2341 } else {
2342 return false;
2343 }
2344 }
2345 let (id, stability, external_id) = match &item {
2346 WorldItem::Interface {
2347 id,
2348 stability,
2349 external_id,
2350 ..
2351 } => (*id, stability, external_id),
2352 _ => unreachable!(),
2353 };
2354 if !add_export && required_imports.contains(&id) {
2357 return true;
2358 }
2359 let ok = resolve.interface_direct_deps(id).all(|dep| {
2360 let item = WorldItem::Interface {
2361 id: dep,
2362 stability: stability.clone(),
2363 docs: Default::default(),
2364 span: Default::default(),
2365 external_id: external_id.clone(),
2366 };
2367 let key = WorldKey::Interface(dep);
2368 let add_export = add_export && export_interfaces.contains_key(&key);
2369 add_world_export(
2370 resolve,
2371 imports,
2372 exports,
2373 export_interfaces,
2374 required_imports,
2375 key,
2376 item,
2377 add_export,
2378 )
2379 });
2380 if !ok {
2381 return false;
2382 }
2383 if add_export {
2384 if required_imports.contains(&id) {
2385 return false;
2386 }
2387 let prev = exports.insert(key.clone(), item);
2388 assert!(prev.is_none());
2389 } else {
2390 required_imports.insert(id);
2391 if !imports.contains_key(&key) {
2392 imports.insert(key.clone(), item);
2393 }
2394 }
2395 true
2396 }
2397 }
2398
2399 pub fn merge_world_imports_based_on_semver(&mut self, world_id: WorldId) -> anyhow::Result<()> {
2411 let world = &self.worlds[world_id];
2412
2413 let mut semver_tracks = HashMap::new();
2422 let mut to_remove = HashSet::new();
2423 for (key, _) in world.imports.iter() {
2424 let iface_id = match key {
2425 WorldKey::Interface(id) => *id,
2426 WorldKey::Name(_) => continue,
2427 };
2428 let (track, version) = match self.semver_track(iface_id) {
2429 Some(track) => track,
2430 None => continue,
2431 };
2432 log::debug!(
2433 "{} is on track {}/{}",
2434 self.id_of(iface_id).unwrap(),
2435 track.0,
2436 track.1,
2437 );
2438 match semver_tracks.entry(track.clone()) {
2439 Entry::Vacant(e) => {
2440 e.insert((version, iface_id));
2441 }
2442 Entry::Occupied(mut e) => match version.cmp(&e.get().0) {
2443 Ordering::Greater => {
2444 to_remove.insert(e.get().1);
2445 e.insert((version, iface_id));
2446 }
2447 Ordering::Equal => {}
2448 Ordering::Less => {
2449 to_remove.insert(iface_id);
2450 }
2451 },
2452 }
2453 }
2454
2455 let mut replacements = HashMap::new();
2458 for id in to_remove {
2459 let (track, _) = self.semver_track(id).unwrap();
2460 let (_, latest) = semver_tracks[&track];
2461 let prev = replacements.insert(id, latest);
2462 assert!(prev.is_none());
2463 }
2464 drop(semver_tracks);
2467
2468 for (to_replace, replace_with) in replacements.iter() {
2473 self.merge_world_item(
2474 &WorldItem::Interface {
2475 id: *to_replace,
2476 stability: Default::default(),
2477 docs: Default::default(),
2478 span: Default::default(),
2479 external_id: Default::default(),
2480 },
2481 &WorldItem::Interface {
2482 id: *replace_with,
2483 stability: Default::default(),
2484 docs: Default::default(),
2485 span: Default::default(),
2486 external_id: Default::default(),
2487 },
2488 )
2489 .with_context(|| {
2490 let old_name = self.id_of(*to_replace).unwrap();
2491 let new_name = self.id_of(*replace_with).unwrap();
2492 format!(
2493 "failed to upgrade `{old_name}` to `{new_name}`, was \
2494 this semver-compatible update not semver compatible?"
2495 )
2496 })?;
2497 }
2498
2499 for (to_replace, replace_with) in replacements.iter() {
2500 log::debug!(
2501 "REPLACE {} => {}",
2502 self.id_of(*to_replace).unwrap(),
2503 self.id_of(*replace_with).unwrap(),
2504 );
2505 }
2506
2507 for (key, item) in mem::take(&mut self.worlds[world_id].imports) {
2516 if let WorldItem::Interface { id, .. } = item {
2517 if replacements.contains_key(&id) {
2518 continue;
2519 }
2520 }
2521
2522 self.update_interface_deps_of_world_item(&item, &replacements);
2523
2524 let prev = self.worlds[world_id].imports.insert(key, item);
2525 assert!(prev.is_none());
2526 }
2527 for (key, item) in mem::take(&mut self.worlds[world_id].exports) {
2528 self.update_interface_deps_of_world_item(&item, &replacements);
2529 let prev = self.worlds[world_id].exports.insert(key, item);
2530 assert!(prev.is_none());
2531 }
2532
2533 let ids = self.worlds.iter().map(|(id, _)| id).collect::<Vec<_>>();
2539 for world_id in ids {
2540 let world_span = self.worlds[world_id].span;
2541 self.elaborate_world(world_id, world_span)?;
2542 }
2543
2544 #[cfg(debug_assertions)]
2545 self.assert_valid();
2546
2547 Ok(())
2548 }
2549
2550 fn update_interface_deps_of_world_item(
2551 &mut self,
2552 item: &WorldItem,
2553 replacements: &HashMap<InterfaceId, InterfaceId>,
2554 ) {
2555 match *item {
2556 WorldItem::Type { id, .. } => self.update_interface_dep_of_type(id, &replacements),
2557 WorldItem::Interface { id, .. } => {
2558 let types = self.interfaces[id]
2559 .types
2560 .values()
2561 .copied()
2562 .collect::<Vec<_>>();
2563 for ty in types {
2564 self.update_interface_dep_of_type(ty, &replacements);
2565 }
2566 }
2567 WorldItem::Function(_) => {}
2568 }
2569 }
2570
2571 fn semver_track(&self, id: InterfaceId) -> Option<((PackageName, String), &Version)> {
2582 let iface = &self.interfaces[id];
2583 let pkg = &self.packages[iface.package?];
2584 let version = pkg.name.version.as_ref()?;
2585 let mut name = pkg.name.clone();
2586 name.version = Some(PackageName::version_compat_track(version));
2587 Some(((name, iface.name.clone()?), version))
2588 }
2589
2590 fn update_interface_dep_of_type(
2594 &mut self,
2595 ty: TypeId,
2596 replacements: &HashMap<InterfaceId, InterfaceId>,
2597 ) {
2598 let to_replace = match self.type_interface_dep(ty) {
2599 Some(id) => id,
2600 None => return,
2601 };
2602 let replace_with = match replacements.get(&to_replace) {
2603 Some(id) => id,
2604 None => return,
2605 };
2606 let dep = match self.types[ty].kind {
2607 TypeDefKind::Type(Type::Id(id)) => id,
2608 _ => return,
2609 };
2610 let name = self.types[dep].name.as_ref().unwrap();
2611 let replacement_id = self.interfaces[*replace_with].types[name];
2614 self.types[ty].kind = TypeDefKind::Type(Type::Id(replacement_id));
2615 }
2616
2617 pub fn wasm_import_name(
2624 &self,
2625 mangling: ManglingAndAbi,
2626 import: WasmImport<'_>,
2627 ) -> (String, String) {
2628 match mangling {
2629 ManglingAndAbi::Standard32 => match import {
2630 WasmImport::Func { interface, func } => {
2631 let module = match interface {
2632 Some(key) => format!("cm32p2|{}", self.name_canonicalized_world_key(key)),
2633 None => format!("cm32p2"),
2634 };
2635 (module, func.name.clone())
2636 }
2637 WasmImport::ResourceIntrinsic {
2638 interface,
2639 resource,
2640 intrinsic,
2641 } => {
2642 let name = self.types[resource].name.as_ref().unwrap();
2643 let (prefix, name) = match intrinsic {
2644 ResourceIntrinsic::ImportedDrop => ("", format!("{name}_drop")),
2645 ResourceIntrinsic::ExportedDrop => ("_ex_", format!("{name}_drop")),
2646 ResourceIntrinsic::ExportedNew => ("_ex_", format!("{name}_new")),
2647 ResourceIntrinsic::ExportedRep => ("_ex_", format!("{name}_rep")),
2648 };
2649 let module = match interface {
2650 Some(key) => {
2651 format!("cm32p2|{prefix}{}", self.name_canonicalized_world_key(key))
2652 }
2653 None => {
2654 assert_eq!(prefix, "");
2655 format!("cm32p2")
2656 }
2657 };
2658 (module, name)
2659 }
2660 WasmImport::FutureIntrinsic { .. } | WasmImport::StreamIntrinsic { .. } => {
2661 panic!(
2662 "at the time of writing, standard32 name mangling only supports the \
2663 synchronous ABI and does not define future/stream intrinsic imports; \
2664 use legacy mangling for these imports"
2665 )
2666 }
2667 },
2668 ManglingAndAbi::Legacy(abi) => match import {
2669 WasmImport::Func { interface, func } => {
2670 let module = match interface {
2671 Some(key) => self.name_world_key(key),
2672 None => format!("$root"),
2673 };
2674 (module, format!("{}{}", abi.import_prefix(), func.name))
2675 }
2676 WasmImport::ResourceIntrinsic {
2677 interface,
2678 resource,
2679 intrinsic,
2680 } => {
2681 let name = self.types[resource].name.as_ref().unwrap();
2682 let (prefix, name) = match intrinsic {
2683 ResourceIntrinsic::ImportedDrop => ("", format!("[resource-drop]{name}")),
2684 ResourceIntrinsic::ExportedDrop => {
2685 ("[export]", format!("[resource-drop]{name}"))
2686 }
2687 ResourceIntrinsic::ExportedNew => {
2688 ("[export]", format!("[resource-new]{name}"))
2689 }
2690 ResourceIntrinsic::ExportedRep => {
2691 ("[export]", format!("[resource-rep]{name}"))
2692 }
2693 };
2694 let module = match interface {
2695 Some(key) => format!("{prefix}{}", self.name_world_key(key)),
2696 None => {
2697 assert_eq!(prefix, "");
2698 format!("$root")
2699 }
2700 };
2701 (module, format!("{}{name}", abi.import_prefix()))
2702 }
2703 WasmImport::FutureIntrinsic {
2704 interface,
2705 func,
2706 ty,
2707 intrinsic,
2708 exported,
2709 async_,
2710 } => {
2711 let module_prefix = if exported { "[export]" } else { "" };
2712 let module = match interface {
2713 Some(key) => format!("{module_prefix}{}", self.name_world_key(key)),
2714 None => format!("{module_prefix}$root"),
2715 };
2716 let type_index = match ty {
2717 Some(ty) => func
2718 .find_futures_and_streams(self)
2719 .into_iter()
2720 .position(|candidate| candidate == ty)
2721 .unwrap_or_else(|| {
2722 panic!(
2723 "future type {ty:?} not found in `find_futures_and_streams` for `{}`",
2724 func.name
2725 )
2726 })
2727 .to_string(),
2728 None => "unit".to_string(),
2729 };
2730 let (async_prefix, name) = match intrinsic {
2731 FutureIntrinsic::New => {
2732 assert!(!async_, "future.new cannot be async-lowered");
2733 ("", "new")
2734 }
2735 FutureIntrinsic::Read => {
2736 (if async_ { "[async-lower]" } else { "" }, "read")
2737 }
2738 FutureIntrinsic::Write => {
2739 (if async_ { "[async-lower]" } else { "" }, "write")
2740 }
2741 FutureIntrinsic::CancelRead => {
2742 (if async_ { "[async-lower]" } else { "" }, "cancel-read")
2743 }
2744 FutureIntrinsic::CancelWrite => {
2745 (if async_ { "[async-lower]" } else { "" }, "cancel-write")
2746 }
2747 FutureIntrinsic::DropReadable => {
2748 assert!(!async_, "future.drop-readable cannot be async-lowered");
2749 ("", "drop-readable")
2750 }
2751 FutureIntrinsic::DropWritable => {
2752 assert!(!async_, "future.drop-writable cannot be async-lowered");
2753 ("", "drop-writable")
2754 }
2755 };
2756 (
2757 module,
2758 format!("{async_prefix}[future-{name}-{type_index}]{}", func.name),
2759 )
2760 }
2761 WasmImport::StreamIntrinsic {
2762 interface,
2763 func,
2764 ty,
2765 intrinsic,
2766 exported,
2767 async_,
2768 } => {
2769 let module_prefix = if exported { "[export]" } else { "" };
2770 let module = match interface {
2771 Some(key) => format!("{module_prefix}{}", self.name_world_key(key)),
2772 None => format!("{module_prefix}$root"),
2773 };
2774 let type_index = match ty {
2775 Some(ty) => func
2776 .find_futures_and_streams(self)
2777 .into_iter()
2778 .position(|candidate| candidate == ty)
2779 .unwrap_or_else(|| {
2780 panic!(
2781 "stream type {ty:?} not found in `find_futures_and_streams` for `{}`",
2782 func.name
2783 )
2784 })
2785 .to_string(),
2786 None => "unit".to_string(),
2787 };
2788 let (async_prefix, name) = match intrinsic {
2789 StreamIntrinsic::New => {
2790 assert!(!async_, "stream.new cannot be async-lowered");
2791 ("", "new")
2792 }
2793 StreamIntrinsic::Read => {
2794 (if async_ { "[async-lower]" } else { "" }, "read")
2795 }
2796 StreamIntrinsic::Write => {
2797 (if async_ { "[async-lower]" } else { "" }, "write")
2798 }
2799 StreamIntrinsic::CancelRead => {
2800 (if async_ { "[async-lower]" } else { "" }, "cancel-read")
2801 }
2802 StreamIntrinsic::CancelWrite => {
2803 (if async_ { "[async-lower]" } else { "" }, "cancel-write")
2804 }
2805 StreamIntrinsic::DropReadable => {
2806 assert!(!async_, "stream.drop-readable cannot be async-lowered");
2807 ("", "drop-readable")
2808 }
2809 StreamIntrinsic::DropWritable => {
2810 assert!(!async_, "stream.drop-writable cannot be async-lowered");
2811 ("", "drop-writable")
2812 }
2813 };
2814 (
2815 module,
2816 format!("{async_prefix}[stream-{name}-{type_index}]{}", func.name),
2817 )
2818 }
2819 },
2820 }
2821 }
2822
2823 pub fn wasm_export_name(&self, mangling: ManglingAndAbi, export: WasmExport<'_>) -> String {
2827 match mangling {
2828 ManglingAndAbi::Standard32 => match export {
2829 WasmExport::Func {
2830 interface,
2831 func,
2832 kind,
2833 } => {
2834 let mut name = String::from("cm32p2|");
2835 if let Some(interface) = interface {
2836 let s = self.name_canonicalized_world_key(interface);
2837 name.push_str(&s);
2838 }
2839 name.push_str("|");
2840 name.push_str(&func.name);
2841 match kind {
2842 WasmExportKind::Normal => {}
2843 WasmExportKind::PostReturn => name.push_str("_post"),
2844 WasmExportKind::Callback => todo!(
2845 "not yet supported: \
2846 async callback functions using standard name mangling"
2847 ),
2848 }
2849 name
2850 }
2851 WasmExport::ResourceDtor {
2852 interface,
2853 resource,
2854 } => {
2855 let name = self.types[resource].name.as_ref().unwrap();
2856 let interface = self.name_canonicalized_world_key(interface);
2857 format!("cm32p2|{interface}|{name}_dtor")
2858 }
2859 WasmExport::Memory => "cm32p2_memory".to_string(),
2860 WasmExport::Initialize => "cm32p2_initialize".to_string(),
2861 WasmExport::Realloc => "cm32p2_realloc".to_string(),
2862 },
2863 ManglingAndAbi::Legacy(abi) => match export {
2864 WasmExport::Func {
2865 interface,
2866 func,
2867 kind,
2868 } => {
2869 let mut name = abi.export_prefix().to_string();
2870 match kind {
2871 WasmExportKind::Normal => {}
2872 WasmExportKind::PostReturn => name.push_str("cabi_post_"),
2873 WasmExportKind::Callback => {
2874 assert!(matches!(abi, LiftLowerAbi::AsyncCallback));
2875 name = format!("[callback]{name}")
2876 }
2877 }
2878 if let Some(interface) = interface {
2879 let s = self.name_world_key(interface);
2880 name.push_str(&s);
2881 name.push_str("#");
2882 }
2883 name.push_str(&func.name);
2884 name
2885 }
2886 WasmExport::ResourceDtor {
2887 interface,
2888 resource,
2889 } => {
2890 let name = self.types[resource].name.as_ref().unwrap();
2891 let interface = self.name_world_key(interface);
2892 format!("{}{interface}#[dtor]{name}", abi.export_prefix())
2893 }
2894 WasmExport::Memory => "memory".to_string(),
2895 WasmExport::Initialize => "_initialize".to_string(),
2896 WasmExport::Realloc => "cabi_realloc".to_string(),
2897 },
2898 }
2899 }
2900
2901 pub fn generate_nominal_type_ids(&mut self, world_id: WorldId) {
2941 let mut seen = HashSet::new();
2942 let mut interface_keys_rewritten = HashSet::new();
2943 let mut maps = CloneMaps::default();
2944
2945 let world = &mut self.worlds[world_id];
2948 let mut imports = mem::take(&mut world.imports);
2949 let mut exports = mem::take(&mut world.exports);
2950
2951 log::trace!("nominalizing world imports");
2955 self.nominalize_world_items(
2956 &mut maps,
2957 world_id,
2958 &mut imports,
2959 &mut seen,
2960 &mut interface_keys_rewritten,
2961 );
2962 log::trace!("nominalizing world exports");
2963 self.nominalize_world_items(
2964 &mut maps,
2965 world_id,
2966 &mut exports,
2967 &mut seen,
2968 &mut interface_keys_rewritten,
2969 );
2970
2971 let world = &mut self.worlds[world_id];
2973 assert!(world.imports.is_empty());
2974 assert!(world.exports.is_empty());
2975 world.imports = imports;
2976 world.exports = exports;
2977
2978 #[cfg(debug_assertions)]
2979 self.assert_valid();
2980 }
2981
2982 fn nominalize_world_items(
3005 &mut self,
3006 maps: &mut CloneMaps,
3007 world: WorldId,
3008 items: &mut IndexMap<WorldKey, WorldItem>,
3009 seen: &mut HashSet<InterfaceId>,
3010 interface_keys_rewritten: &mut HashSet<InterfaceId>,
3011 ) {
3012 let mut order = items.iter().enumerate().collect::<Vec<_>>();
3110 order.sort_by_key(|(_, (key, item))| match (key, item) {
3111 (WorldKey::Name(_), WorldItem::Interface { .. }) => 1,
3112 _ => 0,
3113 });
3114 let mut to_rewrite = IndexMap::default();
3115 for (i, (key, item)) in order {
3116 let id = match item {
3117 WorldItem::Interface { id, .. } => *id,
3118
3119 WorldItem::Function(_) | WorldItem::Type { .. } => continue,
3122 };
3123
3124 let duplicated = !seen.insert(id);
3130 let any_dep_rewritten = self
3131 .interface_direct_deps(id)
3132 .any(|dep| interface_keys_rewritten.contains(&dep));
3133 if !(duplicated || any_dep_rewritten) {
3134 log::trace!("{} already nominal", self.name_world_key(key));
3135 continue;
3136 }
3137 log::trace!("{} getting rewritten nominal", self.name_world_key(key));
3138
3139 let is_name = matches!(key, WorldKey::Name(_));
3144 if !is_name {
3145 assert!(interface_keys_rewritten.insert(id));
3146 }
3147
3148 to_rewrite
3149 .entry(id)
3150 .or_insert(Vec::new())
3151 .push((i, is_name));
3152 }
3153
3154 for (id, mut list) in to_rewrite {
3185 list.sort_by_key(|(_, is_name)| if *is_name { 0 } else { 1 });
3186 for (i, is_name) in list {
3187 let prev_maps = if is_name { Some(maps.clone()) } else { None };
3188
3189 let mut cloner = clone::Cloner::new(
3190 self,
3191 maps,
3192 TypeOwner::World(world),
3193 TypeOwner::World(world),
3194 );
3195
3196 let mut new_id = id;
3197 cloner.new_package = cloner.resolve.interfaces[id].package;
3198 cloner.interface(&mut new_id);
3199 let (key, prev) = items.get_index_mut(i).unwrap();
3200 match prev {
3201 WorldItem::Interface { id, .. } => *id = new_id,
3202 _ => unreachable!(),
3203 }
3204
3205 match key {
3206 WorldKey::Interface(_) => {
3212 items.replace_index(i, WorldKey::Interface(new_id)).unwrap();
3213 }
3214
3215 WorldKey::Name(_) => {}
3218 }
3219
3220 if let Some(prev) = prev_maps {
3221 *maps = prev;
3222 }
3223 }
3224 }
3225 }
3226}
3227
3228#[derive(Debug)]
3230pub enum WasmImport<'a> {
3231 Func {
3233 interface: Option<&'a WorldKey>,
3238
3239 func: &'a Function,
3241 },
3242
3243 ResourceIntrinsic {
3245 interface: Option<&'a WorldKey>,
3247
3248 resource: TypeId,
3250
3251 intrinsic: ResourceIntrinsic,
3253 },
3254
3255 FutureIntrinsic {
3257 interface: Option<&'a WorldKey>,
3259
3260 func: &'a Function,
3262
3263 ty: Option<TypeId>,
3267
3268 intrinsic: FutureIntrinsic,
3270
3271 exported: bool,
3275
3276 async_: bool,
3280 },
3281
3282 StreamIntrinsic {
3284 interface: Option<&'a WorldKey>,
3286
3287 func: &'a Function,
3289
3290 ty: Option<TypeId>,
3294
3295 intrinsic: StreamIntrinsic,
3297
3298 exported: bool,
3302
3303 async_: bool,
3307 },
3308}
3309
3310#[derive(Debug)]
3313pub enum ResourceIntrinsic {
3314 ImportedDrop,
3315 ExportedDrop,
3316 ExportedNew,
3317 ExportedRep,
3318}
3319
3320#[derive(Debug)]
3323pub enum FutureIntrinsic {
3324 New,
3325 Read,
3326 Write,
3327 CancelRead,
3328 CancelWrite,
3329 DropReadable,
3330 DropWritable,
3331}
3332
3333#[derive(Debug)]
3336pub enum StreamIntrinsic {
3337 New,
3338 Read,
3339 Write,
3340 CancelRead,
3341 CancelWrite,
3342 DropReadable,
3343 DropWritable,
3344}
3345
3346#[derive(Debug)]
3349pub enum WasmExportKind {
3350 Normal,
3352
3353 PostReturn,
3355
3356 Callback,
3358}
3359
3360#[derive(Debug)]
3363pub enum WasmExport<'a> {
3364 Func {
3366 interface: Option<&'a WorldKey>,
3369
3370 func: &'a Function,
3372
3373 kind: WasmExportKind,
3375 },
3376
3377 ResourceDtor {
3379 interface: &'a WorldKey,
3381 resource: TypeId,
3383 },
3384
3385 Memory,
3387
3388 Initialize,
3390
3391 Realloc,
3393}
3394
3395#[derive(Default)]
3398pub struct Remap {
3399 pub types: Vec<Option<TypeId>>,
3400 pub interfaces: Vec<Option<InterfaceId>>,
3401 pub worlds: Vec<Option<WorldId>>,
3402 pub packages: Vec<PackageId>,
3403
3404 own_handles: HashMap<TypeId, TypeId>,
3414
3415 type_has_borrow: Vec<Option<bool>>,
3416}
3417
3418fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Span) -> ResolveResult<Id<T>> {
3419 match map.get(id.index()) {
3420 Some(Some(id)) => Ok(*id),
3421 Some(None) => {
3422 let msg = format!(
3423 "found a reference to a {desc} which is excluded \
3424 due to its feature not being activated"
3425 );
3426 Err(ResolveError::new_semantic(span, msg))
3427 }
3428 None => panic!("request to remap a {desc} that has not yet been registered"),
3429 }
3430}
3431
3432fn rename(original_name: &str, include_name: &IncludeName) -> Option<String> {
3433 if original_name == include_name.name {
3434 return Some(include_name.as_.to_string());
3435 }
3436 let (kind, rest) = original_name.split_once(']')?;
3437 match rest.split_once('.') {
3438 Some((name, rest)) if name == include_name.name => {
3439 Some(format!("{kind}]{}.{rest}", include_name.as_))
3440 }
3441 _ if rest == include_name.name => Some(format!("{kind}]{}", include_name.as_)),
3442 _ => None,
3443 }
3444}
3445
3446impl Remap {
3447 pub fn map_type(&self, id: TypeId, span: Span) -> ResolveResult<TypeId> {
3448 apply_map(&self.types, id, "type", span)
3449 }
3450
3451 pub fn map_interface(&self, id: InterfaceId, span: Span) -> ResolveResult<InterfaceId> {
3452 apply_map(&self.interfaces, id, "interface", span)
3453 }
3454
3455 pub fn map_world(&self, id: WorldId, span: Span) -> ResolveResult<WorldId> {
3456 apply_map(&self.worlds, id, "world", span)
3457 }
3458
3459 pub fn map_world_for_type(&self, id: WorldId, span: Span) -> ResolveResult<WorldId> {
3460 self.map_world(id, span).map_err(|e| {
3461 ResolveError::new_semantic(
3462 span,
3463 format!("{e}; this type is not gated by a feature but its world is"),
3464 )
3465 })
3466 }
3467
3468 pub fn map_interface_for_type(
3469 &self,
3470 id: InterfaceId,
3471 span: Span,
3472 ) -> ResolveResult<InterfaceId> {
3473 self.map_interface(id, span).map_err(|e| {
3474 ResolveError::new_semantic(
3475 span,
3476 format!("{e}; this type is not gated by a feature but its interface is"),
3477 )
3478 })
3479 }
3480
3481 fn append(
3482 &mut self,
3483 resolve: &mut Resolve,
3484 unresolved: UnresolvedPackage,
3485 ) -> ResolveResult<PackageId> {
3486 let pkgid = resolve.packages.alloc(Package {
3487 name: unresolved.name.clone(),
3488 docs: unresolved.docs.clone(),
3489 interfaces: Default::default(),
3490 worlds: Default::default(),
3491 });
3492 assert!(
3493 !resolve.package_names.contains_key(&unresolved.name),
3494 "attempting to re-add package `{}` when it's already present in this `Resolve`",
3495 unresolved.name,
3496 );
3497 resolve.package_names.insert(unresolved.name.clone(), pkgid);
3498 self.process_foreign_deps(resolve, pkgid, &unresolved)?;
3499
3500 let foreign_types = self.types.len();
3501 let foreign_interfaces = self.interfaces.len();
3502 let foreign_worlds = self.worlds.len();
3503
3504 for (id, mut ty) in unresolved.types.into_iter().skip(foreign_types) {
3510 let span = ty.span;
3511 if !resolve.include_stability(&ty.stability, &pkgid, span)? {
3512 self.types.push(None);
3513 continue;
3514 }
3515
3516 self.update_typedef(resolve, &mut ty, span)?;
3517 let new_id = resolve.types.alloc(ty);
3518 assert_eq!(self.types.len(), id.index());
3519
3520 let new_id = match resolve.types[new_id] {
3521 TypeDef {
3526 name: None,
3527 owner: TypeOwner::None,
3528 kind: TypeDefKind::Handle(Handle::Own(id)),
3529 docs: _,
3530 stability: _,
3531 span: _,
3532 external_id: _,
3533 } => *self.own_handles.entry(id).or_insert(new_id),
3534
3535 _ => new_id,
3538 };
3539 self.types.push(Some(new_id));
3540 }
3541
3542 for (id, mut iface) in unresolved.interfaces.into_iter().skip(foreign_interfaces) {
3545 let span = iface.span;
3546 if !resolve.include_stability(&iface.stability, &pkgid, span)? {
3547 self.interfaces.push(None);
3548 continue;
3549 }
3550 assert!(iface.package.is_none());
3551 iface.package = Some(pkgid);
3552 self.update_interface(resolve, &mut iface)?;
3553 let new_id = resolve.interfaces.alloc(iface);
3554 assert_eq!(self.interfaces.len(), id.index());
3555 self.interfaces.push(Some(new_id));
3556 }
3557
3558 for id in self.types.iter().skip(foreign_types) {
3561 let id = match id {
3562 Some(id) => *id,
3563 None => continue,
3564 };
3565 let span = resolve.types[id].span;
3566 match &mut resolve.types[id].owner {
3567 TypeOwner::Interface(iface_id) => {
3568 *iface_id = self.map_interface_for_type(*iface_id, span)?;
3569 }
3570 TypeOwner::World(_) | TypeOwner::None => {}
3571 }
3572 }
3573
3574 for (id, mut world) in unresolved.worlds.into_iter().skip(foreign_worlds) {
3582 let world_span = world.span;
3583 if !resolve.include_stability(&world.stability, &pkgid, world_span)? {
3584 self.worlds.push(None);
3585 continue;
3586 }
3587 self.update_world(&mut world, resolve, &pkgid)?;
3588
3589 let new_id = resolve.worlds.alloc(world);
3590 assert_eq!(self.worlds.len(), id.index());
3591 self.worlds.push(Some(new_id));
3592 }
3593
3594 for id in self.types.iter().skip(foreign_types) {
3596 let id = match id {
3597 Some(id) => *id,
3598 None => continue,
3599 };
3600 let span = resolve.types[id].span;
3601 match &mut resolve.types[id].owner {
3602 TypeOwner::World(world_id) => {
3603 *world_id = self.map_world_for_type(*world_id, span)?;
3604 }
3605 TypeOwner::Interface(_) | TypeOwner::None => {}
3606 }
3607 }
3608
3609 for id in self.worlds.iter().skip(foreign_worlds) {
3626 let Some(id) = *id else {
3627 continue;
3628 };
3629 self.process_world_includes(id, resolve, &pkgid)?;
3630
3631 let world_span = resolve.worlds[id].span;
3632 resolve.elaborate_world(id, world_span)?;
3633 }
3634
3635 for id in self.interfaces.iter().skip(foreign_interfaces) {
3637 let id = match id {
3638 Some(id) => *id,
3639 None => continue,
3640 };
3641 let iface = &mut resolve.interfaces[id];
3642 iface.package = Some(pkgid);
3643 if let Some(name) = &iface.name {
3644 let prev = resolve.packages[pkgid].interfaces.insert(name.clone(), id);
3645 assert!(prev.is_none());
3646 }
3647 }
3648 for id in self.worlds.iter().skip(foreign_worlds) {
3649 let id = match id {
3650 Some(id) => *id,
3651 None => continue,
3652 };
3653 let world = &mut resolve.worlds[id];
3654 world.package = Some(pkgid);
3655 let prev = resolve.packages[pkgid]
3656 .worlds
3657 .insert(world.name.clone(), id);
3658 assert!(prev.is_none());
3659 }
3660 Ok(pkgid)
3661 }
3662
3663 fn process_foreign_deps(
3664 &mut self,
3665 resolve: &mut Resolve,
3666 pkgid: PackageId,
3667 unresolved: &UnresolvedPackage,
3668 ) -> ResolveResult<()> {
3669 let mut world_to_package = HashMap::new();
3672 let mut interface_to_package = HashMap::new();
3673 for (i, (pkg_name, worlds_or_ifaces)) in unresolved.foreign_deps.iter().enumerate() {
3674 for (name, (item, stabilities)) in worlds_or_ifaces {
3675 match item {
3676 AstItem::Interface(unresolved_interface_id) => {
3677 let prev = interface_to_package.insert(
3678 *unresolved_interface_id,
3679 (pkg_name, name, unresolved.foreign_dep_spans[i], stabilities),
3680 );
3681 assert!(prev.is_none());
3682 }
3683 AstItem::World(unresolved_world_id) => {
3684 let prev = world_to_package.insert(
3685 *unresolved_world_id,
3686 (pkg_name, name, unresolved.foreign_dep_spans[i], stabilities),
3687 );
3688 assert!(prev.is_none());
3689 }
3690 }
3691 }
3692 }
3693
3694 self.process_foreign_interfaces(unresolved, &interface_to_package, resolve, &pkgid)?;
3698
3699 self.process_foreign_worlds(unresolved, &world_to_package, resolve, &pkgid)?;
3703
3704 self.process_foreign_types(unresolved, pkgid, resolve)?;
3707
3708 for (id, span) in unresolved.required_resource_types.iter() {
3709 let Ok(mut id) = self.map_type(*id, *span) else {
3714 continue;
3715 };
3716 loop {
3717 match resolve.types[id].kind {
3718 TypeDefKind::Type(Type::Id(i)) => id = i,
3719 TypeDefKind::Resource => break,
3720 _ => {
3721 return Err(ResolveError::new_semantic(
3722 *span,
3723 "type used in a handle must be a resource",
3724 ));
3725 }
3726 }
3727 }
3728 }
3729
3730 #[cfg(debug_assertions)]
3731 resolve.assert_valid();
3732
3733 Ok(())
3734 }
3735
3736 fn process_foreign_interfaces(
3737 &mut self,
3738 unresolved: &UnresolvedPackage,
3739 interface_to_package: &HashMap<InterfaceId, (&PackageName, &String, Span, &Vec<Stability>)>,
3740 resolve: &mut Resolve,
3741 parent_pkg_id: &PackageId,
3742 ) -> ResolveResult<()> {
3743 for (unresolved_iface_id, unresolved_iface) in unresolved.interfaces.iter() {
3744 let (pkg_name, interface, span, stabilities) =
3745 match interface_to_package.get(&unresolved_iface_id) {
3746 Some(items) => *items,
3747 None => break,
3751 };
3752
3753 let pkgid = resolve
3754 .package_names
3755 .get(pkg_name)
3756 .copied()
3757 .ok_or_else(|| {
3758 ResolveError::from(ResolveErrorKind::PackageNotFound {
3759 span,
3760 requested: pkg_name.clone(),
3761 known: resolve.package_names.keys().cloned().collect(),
3762 })
3763 })?;
3764
3765 assert!(unresolved_iface.functions.is_empty());
3767
3768 let pkg = &resolve.packages[pkgid];
3769 let iface_span = unresolved_iface.span;
3770
3771 let mut enabled = false;
3772 for stability in stabilities {
3773 if resolve.include_stability(stability, parent_pkg_id, iface_span)? {
3774 enabled = true;
3775 break;
3776 }
3777 }
3778
3779 if !enabled {
3780 self.interfaces.push(None);
3781 continue;
3782 }
3783
3784 let iface_id = pkg.interfaces.get(interface).copied().ok_or_else(|| {
3785 ResolveError::from(ResolveErrorKind::InterfaceNotFound {
3786 span: iface_span,
3787 requested: interface.to_string(),
3788 package: pkg.name.clone(),
3789 })
3790 })?;
3791 assert_eq!(self.interfaces.len(), unresolved_iface_id.index());
3792 self.interfaces.push(Some(iface_id));
3793 }
3794 for (id, _) in unresolved.interfaces.iter().skip(self.interfaces.len()) {
3795 assert!(
3796 interface_to_package.get(&id).is_none(),
3797 "found foreign interface after local interface"
3798 );
3799 }
3800 Ok(())
3801 }
3802
3803 fn process_foreign_worlds(
3804 &mut self,
3805 unresolved: &UnresolvedPackage,
3806 world_to_package: &HashMap<WorldId, (&PackageName, &String, Span, &Vec<Stability>)>,
3807 resolve: &mut Resolve,
3808 parent_pkg_id: &PackageId,
3809 ) -> ResolveResult<()> {
3810 for (unresolved_world_id, unresolved_world) in unresolved.worlds.iter() {
3811 let (pkg_name, world, span, stabilities) =
3812 match world_to_package.get(&unresolved_world_id) {
3813 Some(items) => *items,
3814 None => break,
3817 };
3818
3819 let pkgid = resolve
3820 .package_names
3821 .get(pkg_name)
3822 .copied()
3823 .ok_or_else(|| {
3824 ResolveError::from(ResolveErrorKind::PackageNotFound {
3825 span,
3826 requested: pkg_name.clone(),
3827 known: resolve.package_names.keys().cloned().collect(),
3828 })
3829 })?;
3830 let pkg = &resolve.packages[pkgid];
3831 let world_span = unresolved_world.span;
3832
3833 let mut enabled = false;
3834 for stability in stabilities {
3835 if resolve.include_stability(stability, parent_pkg_id, world_span)? {
3836 enabled = true;
3837 break;
3838 }
3839 }
3840
3841 if !enabled {
3842 self.worlds.push(None);
3843 continue;
3844 }
3845
3846 let world_id = pkg.worlds.get(world).copied().ok_or_else(|| {
3847 ResolveError::from(ResolveErrorKind::WorldNotFound {
3848 span: world_span,
3849 requested: world.to_string(),
3850 package: pkg.name.clone(),
3851 })
3852 })?;
3853 assert_eq!(self.worlds.len(), unresolved_world_id.index());
3854 self.worlds.push(Some(world_id));
3855 }
3856 for (id, _) in unresolved.worlds.iter().skip(self.worlds.len()) {
3857 assert!(
3858 world_to_package.get(&id).is_none(),
3859 "found foreign world after local world"
3860 );
3861 }
3862 Ok(())
3863 }
3864
3865 fn process_foreign_types(
3866 &mut self,
3867 unresolved: &UnresolvedPackage,
3868 pkgid: PackageId,
3869 resolve: &mut Resolve,
3870 ) -> ResolveResult<()> {
3871 for (unresolved_type_id, unresolved_ty) in unresolved.types.iter() {
3872 match unresolved_ty.kind {
3876 TypeDefKind::Unknown => {}
3877 _ => break,
3878 }
3879
3880 let span = unresolved_ty.span;
3881 if !resolve.include_stability(&unresolved_ty.stability, &pkgid, span)? {
3882 self.types.push(None);
3883 continue;
3884 }
3885
3886 let unresolved_iface_id = match unresolved_ty.owner {
3887 TypeOwner::Interface(id) => id,
3888 _ => unreachable!(),
3889 };
3890 let iface_id = self.map_interface(unresolved_iface_id, Default::default())?;
3891 let name = unresolved_ty.name.as_ref().unwrap();
3892 let span = unresolved.unknown_type_spans[unresolved_type_id.index()];
3893 let type_id = *resolve.interfaces[iface_id]
3894 .types
3895 .get(name)
3896 .ok_or_else(|| {
3897 ResolveError::new_semantic(
3898 span,
3899 format!("type `{name}` not defined in interface"),
3900 )
3901 })?;
3902 assert_eq!(self.types.len(), unresolved_type_id.index());
3903 self.types.push(Some(type_id));
3904 }
3905 for (_, ty) in unresolved.types.iter().skip(self.types.len()) {
3906 if let TypeDefKind::Unknown = ty.kind {
3907 panic!("unknown type after defined type");
3908 }
3909 }
3910 Ok(())
3911 }
3912
3913 fn update_typedef(
3914 &mut self,
3915 resolve: &mut Resolve,
3916 ty: &mut TypeDef,
3917 span: Span,
3918 ) -> ResolveResult<()> {
3919 use crate::TypeDefKind::*;
3922 match &mut ty.kind {
3923 Handle(handle) => match handle {
3924 crate::Handle::Own(ty) | crate::Handle::Borrow(ty) => {
3925 self.update_type_id(ty, span)?
3926 }
3927 },
3928 Resource => {}
3929 Record(r) => {
3930 for field in r.fields.iter_mut() {
3931 self.update_ty(resolve, &mut field.ty, field.span)?
3932 }
3933 }
3934 Tuple(t) => {
3935 for ty in t.types.iter_mut() {
3936 self.update_ty(resolve, ty, span)?;
3937 }
3938 }
3939 Variant(v) => {
3940 for case in v.cases.iter_mut() {
3941 if let Some(t) = &mut case.ty {
3942 self.update_ty(resolve, t, span)?;
3943 }
3944 }
3945 }
3946 Option(t)
3947 | List(t, ..)
3948 | FixedLengthList(t, ..)
3949 | Future(Some(t))
3950 | Stream(Some(t)) => self.update_ty(resolve, t, span)?,
3951 Map(k, v) => {
3952 self.update_ty(resolve, k, span)?;
3953 self.update_ty(resolve, v, span)?;
3954 }
3955 Result(r) => {
3956 if let Some(ty) = &mut r.ok {
3957 self.update_ty(resolve, ty, span)?;
3958 }
3959 if let Some(ty) = &mut r.err {
3960 self.update_ty(resolve, ty, span)?;
3961 }
3962 }
3963
3964 Type(crate::Type::Id(id)) => self.update_type_id(id, span)?,
3969 Type(_) => {}
3970
3971 Flags(_) | Enum(_) | Future(None) | Stream(None) => {}
3973
3974 Unknown => unreachable!(),
3975 }
3976
3977 Ok(())
3978 }
3979
3980 fn update_ty(&mut self, resolve: &mut Resolve, ty: &mut Type, span: Span) -> ResolveResult<()> {
3981 let id = match ty {
3982 Type::Id(id) => id,
3983 _ => return Ok(()),
3984 };
3985 self.update_type_id(id, span)?;
3986
3987 let mut cur = *id;
3992 let points_to_resource = loop {
3993 match resolve.types[cur].kind {
3994 TypeDefKind::Type(Type::Id(id)) => cur = id,
3995 TypeDefKind::Resource => break true,
3996 _ => break false,
3997 }
3998 };
3999
4000 if points_to_resource {
4001 *id = *self.own_handles.entry(*id).or_insert_with(|| {
4002 resolve.types.alloc(TypeDef {
4003 name: None,
4004 owner: TypeOwner::None,
4005 kind: TypeDefKind::Handle(Handle::Own(*id)),
4006 docs: Default::default(),
4007 stability: Default::default(),
4008 span: Default::default(),
4009 external_id: None,
4010 })
4011 });
4012 }
4013 Ok(())
4014 }
4015
4016 fn update_type_id(&self, id: &mut TypeId, span: Span) -> ResolveResult<()> {
4017 *id = self.map_type(*id, span)?;
4018 Ok(())
4019 }
4020
4021 fn update_interface(
4022 &mut self,
4023 resolve: &mut Resolve,
4024 iface: &mut Interface,
4025 ) -> ResolveResult<()> {
4026 iface.types.retain(|_, ty| self.types[ty.index()].is_some());
4027 let iface_pkg_id = iface.package.as_ref().unwrap_or_else(|| {
4028 panic!(
4029 "unexpectedly missing package on interface [{}]",
4030 iface
4031 .name
4032 .as_ref()
4033 .map(String::as_str)
4034 .unwrap_or("<unknown>"),
4035 )
4036 });
4037
4038 for (_name, ty) in iface.types.iter_mut() {
4041 self.update_type_id(ty, iface.span)?;
4042 }
4043 for (_, func) in iface.functions.iter_mut() {
4044 let span = func.span;
4045 if !resolve.include_stability(&func.stability, iface_pkg_id, span)? {
4046 continue;
4047 }
4048 self.update_function(resolve, func, span)?
4049 }
4050
4051 for (name, func) in mem::take(&mut iface.functions) {
4054 if resolve.include_stability(&func.stability, iface_pkg_id, func.span)? {
4055 iface.functions.insert(name, func);
4056 }
4057 }
4058
4059 Ok(())
4060 }
4061
4062 fn update_function(
4063 &mut self,
4064 resolve: &mut Resolve,
4065 func: &mut Function,
4066 span: Span,
4067 ) -> ResolveResult<()> {
4068 if let Some(id) = func.kind.resource_mut() {
4069 self.update_type_id(id, span)?;
4070 }
4071 for param in func.params.iter_mut() {
4072 self.update_ty(resolve, &mut param.ty, span)?;
4073 }
4074 if let Some(ty) = &mut func.result {
4075 self.update_ty(resolve, ty, span)?;
4076 }
4077
4078 if let Some(ty) = &func.result {
4079 if self.type_has_borrow(resolve, ty) {
4080 return Err(ResolveError::new_semantic(
4081 span,
4082 format!(
4083 "function `{}` returns a type which contains a `borrow<T>` which is not supported",
4084 func.name,
4085 ),
4086 ));
4087 }
4088 }
4089
4090 Ok(())
4091 }
4092
4093 fn update_world(
4094 &mut self,
4095 world: &mut World,
4096 resolve: &mut Resolve,
4097 pkg_id: &PackageId,
4098 ) -> ResolveResult<()> {
4099 let imports = mem::take(&mut world.imports).into_iter().map(|p| (p, true));
4103 let exports = mem::take(&mut world.exports)
4104 .into_iter()
4105 .map(|p| (p, false));
4106 for ((mut name, mut item), import) in imports.chain(exports) {
4107 let span = item.span();
4108 if let WorldItem::Type { id, .. } = &mut item {
4111 *id = self.map_type(*id, span)?;
4112 }
4113 let stability = item.stability(resolve);
4114 if !resolve.include_stability(stability, pkg_id, span)? {
4115 continue;
4116 }
4117 self.update_world_key(&mut name, span)?;
4118 match &mut item {
4119 WorldItem::Interface { id, .. } => {
4120 *id = self.map_interface(*id, span)?;
4121 }
4122 WorldItem::Function(f) => {
4123 self.update_function(resolve, f, span)?;
4124 }
4125 WorldItem::Type { .. } => {
4126 }
4128 }
4129
4130 let dst = if import {
4131 &mut world.imports
4132 } else {
4133 &mut world.exports
4134 };
4135 let prev = dst.insert(name, item);
4136 assert!(prev.is_none());
4137 }
4138
4139 Ok(())
4140 }
4141
4142 fn process_world_includes(
4143 &self,
4144 id: WorldId,
4145 resolve: &mut Resolve,
4146 pkg_id: &PackageId,
4147 ) -> ResolveResult<()> {
4148 let world = &mut resolve.worlds[id];
4149 let includes = mem::take(&mut world.includes);
4152 for include in includes {
4153 if !resolve.include_stability(&include.stability, pkg_id, include.span)? {
4154 continue;
4155 }
4156 self.resolve_include(
4157 id,
4158 include.id,
4159 &include.names,
4160 include.span,
4161 pkg_id,
4162 resolve,
4163 )?;
4164 }
4165
4166 Self::validate_world_case_insensitive_names(resolve, id)?;
4168
4169 Ok(())
4170 }
4171
4172 fn validate_world_case_insensitive_names(
4176 resolve: &Resolve,
4177 world_id: WorldId,
4178 ) -> ResolveResult<()> {
4179 let world = &resolve.worlds[world_id];
4180
4181 let validate_names =
4183 |items: &IndexMap<WorldKey, WorldItem>, item_type: &str| -> ResolveResult<()> {
4184 let mut seen_lowercase: HashMap<String, String> = HashMap::new();
4185
4186 for key in items.keys() {
4187 if let WorldKey::Name(name) = key {
4189 let lowercase_name = name.to_lowercase();
4190
4191 if let Some(existing_name) = seen_lowercase.get(&lowercase_name) {
4192 if existing_name != name {
4195 return Err(ResolveError::new_semantic(
4199 Span::default(),
4200 format!(
4201 "{item_type} `{name}` in world `{}` conflicts with \
4202 {item_type} `{existing_name}` \
4203 (kebab-case identifiers are case-insensitive)",
4204 world.name,
4205 ),
4206 ));
4207 }
4208 }
4209
4210 seen_lowercase.insert(lowercase_name, name.clone());
4211 }
4212 }
4213
4214 Ok(())
4215 };
4216
4217 validate_names(&world.imports, "import")?;
4218 validate_names(&world.exports, "export")?;
4219
4220 Ok(())
4221 }
4222
4223 fn update_world_key(&self, key: &mut WorldKey, span: Span) -> ResolveResult<()> {
4224 match key {
4225 WorldKey::Name(_) => {}
4226 WorldKey::Interface(id) => {
4227 *id = self.map_interface(*id, span)?;
4228 }
4229 }
4230 Ok(())
4231 }
4232
4233 fn resolve_include(
4234 &self,
4235 id: WorldId,
4236 include_world_id_orig: WorldId,
4237 names: &[IncludeName],
4238 span: Span,
4239 pkg_id: &PackageId,
4240 resolve: &mut Resolve,
4241 ) -> ResolveResult<()> {
4242 let world = &resolve.worlds[id];
4243 let include_world_id = self.map_world(include_world_id_orig, span)?;
4244 let include_world = resolve.worlds[include_world_id].clone();
4245 let mut names_ = names.to_owned();
4246 let is_external_include = world.package != include_world.package;
4247
4248 for import in include_world.imports.iter() {
4250 self.remove_matching_name(import, &mut names_);
4251 }
4252 for export in include_world.exports.iter() {
4253 self.remove_matching_name(export, &mut names_);
4254 }
4255 if !names_.is_empty() {
4256 return Err(ResolveError::new_semantic(
4257 span,
4258 format!(
4259 "no import or export kebab-name `{}`. Note that an ID does not support renaming",
4260 names_[0].name
4261 ),
4262 ));
4263 }
4264
4265 let mut maps = Default::default();
4266 let mut cloner = clone::Cloner::new(
4267 resolve,
4268 &mut maps,
4269 TypeOwner::World(if is_external_include {
4270 include_world_id
4271 } else {
4272 include_world_id
4273 }),
4275 TypeOwner::World(id),
4276 );
4277 cloner.new_package = Some(*pkg_id);
4278
4279 for import in include_world.imports.iter() {
4281 self.resolve_include_item(
4282 &mut cloner,
4283 names,
4284 |resolve| &mut resolve.worlds[id].imports,
4285 import,
4286 span,
4287 "import",
4288 is_external_include,
4289 )?;
4290 }
4291
4292 for export in include_world.exports.iter() {
4293 self.resolve_include_item(
4294 &mut cloner,
4295 names,
4296 |resolve| &mut resolve.worlds[id].exports,
4297 export,
4298 span,
4299 "export",
4300 is_external_include,
4301 )?;
4302 }
4303 Ok(())
4304 }
4305
4306 fn resolve_include_item(
4307 &self,
4308 cloner: &mut clone::Cloner<'_>,
4309 names: &[IncludeName],
4310 get_items: impl Fn(&mut Resolve) -> &mut IndexMap<WorldKey, WorldItem>,
4311 item: (&WorldKey, &WorldItem),
4312 span: Span,
4313 item_type: &str,
4314 is_external_include: bool,
4315 ) -> ResolveResult<()> {
4316 match item.0 {
4317 WorldKey::Name(n) => {
4318 let n = names
4319 .into_iter()
4320 .find_map(|include_name| rename(n, include_name))
4321 .unwrap_or(n.clone());
4322
4323 let mut new_item = item.1.clone();
4329 let key = WorldKey::Name(n.clone());
4330 cloner.world_item(&key, &mut new_item);
4331 match &mut new_item {
4332 WorldItem::Function(f) => f.name = n.clone(),
4333 WorldItem::Type { id, .. } => cloner.resolve.types[*id].name = Some(n.clone()),
4334 WorldItem::Interface { .. } => {}
4335 }
4336
4337 let prev = get_items(cloner.resolve).insert(key, new_item);
4338 if prev.is_some() {
4339 return Err(ResolveError::from(ResolveErrorKind::ItemShadowing {
4340 span,
4341 item_type: item_type.to_owned(),
4342 name: n,
4343 }));
4344 }
4345 }
4346 key @ WorldKey::Interface(_) => {
4347 let prev = get_items(cloner.resolve)
4348 .entry(key.clone())
4349 .or_insert(item.1.clone());
4350 match (&item.1, prev) {
4351 (
4352 WorldItem::Interface {
4353 id: aid,
4354 stability: astability,
4355 span: aspan,
4356 ..
4357 },
4358 WorldItem::Interface {
4359 id: bid,
4360 stability: bstability,
4361 ..
4362 },
4363 ) => {
4364 assert_eq!(*aid, *bid);
4365 merge_include_stability(
4366 astability,
4367 bstability,
4368 is_external_include,
4369 *aspan,
4370 )?;
4371 }
4372 (WorldItem::Interface { .. }, _) => unreachable!(),
4373 (WorldItem::Function(_), _) => unreachable!(),
4374 (WorldItem::Type { .. }, _) => unreachable!(),
4375 }
4376 }
4377 };
4378
4379 Ok(())
4380 }
4381
4382 fn remove_matching_name(&self, item: (&WorldKey, &WorldItem), names: &mut Vec<IncludeName>) {
4383 match item.0 {
4384 WorldKey::Name(n) => {
4385 names.retain(|name| rename(n, name).is_none());
4386 }
4387 _ => {}
4388 }
4389 }
4390
4391 fn type_has_borrow(&mut self, resolve: &Resolve, ty: &Type) -> bool {
4392 let id = match ty {
4393 Type::Id(id) => *id,
4394 _ => return false,
4395 };
4396
4397 if let Some(Some(has_borrow)) = self.type_has_borrow.get(id.index()) {
4398 return *has_borrow;
4399 }
4400
4401 let result = self.typedef_has_borrow(resolve, &resolve.types[id]);
4402 if self.type_has_borrow.len() <= id.index() {
4403 self.type_has_borrow.resize(id.index() + 1, None);
4404 }
4405 self.type_has_borrow[id.index()] = Some(result);
4406 result
4407 }
4408
4409 fn typedef_has_borrow(&mut self, resolve: &Resolve, ty: &TypeDef) -> bool {
4410 match &ty.kind {
4411 TypeDefKind::Type(t) => self.type_has_borrow(resolve, t),
4412 TypeDefKind::Variant(v) => v
4413 .cases
4414 .iter()
4415 .filter_map(|case| case.ty.as_ref())
4416 .any(|ty| self.type_has_borrow(resolve, ty)),
4417 TypeDefKind::Handle(Handle::Borrow(_)) => true,
4418 TypeDefKind::Handle(Handle::Own(_)) => false,
4419 TypeDefKind::Resource => false,
4420 TypeDefKind::Record(r) => r
4421 .fields
4422 .iter()
4423 .any(|case| self.type_has_borrow(resolve, &case.ty)),
4424 TypeDefKind::Flags(_) => false,
4425 TypeDefKind::Tuple(t) => t.types.iter().any(|t| self.type_has_borrow(resolve, t)),
4426 TypeDefKind::Enum(_) => false,
4427 TypeDefKind::List(ty)
4428 | TypeDefKind::FixedLengthList(ty, ..)
4429 | TypeDefKind::Future(Some(ty))
4430 | TypeDefKind::Stream(Some(ty))
4431 | TypeDefKind::Option(ty) => self.type_has_borrow(resolve, ty),
4432 TypeDefKind::Map(k, v) => {
4433 self.type_has_borrow(resolve, k) || self.type_has_borrow(resolve, v)
4434 }
4435 TypeDefKind::Result(r) => [&r.ok, &r.err]
4436 .iter()
4437 .filter_map(|t| t.as_ref())
4438 .any(|t| self.type_has_borrow(resolve, t)),
4439 TypeDefKind::Future(None) | TypeDefKind::Stream(None) => false,
4440 TypeDefKind::Unknown => unreachable!(),
4441 }
4442 }
4443}
4444
4445struct MergeMap<'a> {
4446 package_map: HashMap<PackageId, PackageId>,
4449
4450 interface_map: HashMap<InterfaceId, InterfaceId>,
4453
4454 type_map: HashMap<TypeId, TypeId>,
4457
4458 world_map: HashMap<WorldId, WorldId>,
4461
4462 interfaces_to_add: Vec<(String, PackageId, InterfaceId)>,
4470 worlds_to_add: Vec<(String, PackageId, WorldId)>,
4471
4472 from: &'a Resolve,
4474
4475 into: &'a Resolve,
4477}
4478
4479impl<'a> MergeMap<'a> {
4480 fn new(from: &'a Resolve, into: &'a Resolve) -> MergeMap<'a> {
4481 MergeMap {
4482 package_map: Default::default(),
4483 interface_map: Default::default(),
4484 type_map: Default::default(),
4485 world_map: Default::default(),
4486 interfaces_to_add: Default::default(),
4487 worlds_to_add: Default::default(),
4488 from,
4489 into,
4490 }
4491 }
4492
4493 fn build(&mut self) -> anyhow::Result<()> {
4494 for from_id in self.from.topological_packages() {
4495 let from = &self.from.packages[from_id];
4496 let into_id = match self.into.package_names.get(&from.name) {
4497 Some(id) => *id,
4498
4499 None => {
4502 log::trace!("adding unique package {}", from.name);
4503 continue;
4504 }
4505 };
4506 log::trace!("merging duplicate package {}", from.name);
4507
4508 self.build_package(from_id, into_id).with_context(|| {
4509 format!("failed to merge package `{}` into existing copy", from.name)
4510 })?;
4511 }
4512
4513 Ok(())
4514 }
4515
4516 fn build_package(&mut self, from_id: PackageId, into_id: PackageId) -> anyhow::Result<()> {
4517 let prev = self.package_map.insert(from_id, into_id);
4518 assert!(prev.is_none());
4519
4520 let from = &self.from.packages[from_id];
4521 let into = &self.into.packages[into_id];
4522
4523 for (name, from_interface_id) in from.interfaces.iter() {
4527 let into_interface_id = match into.interfaces.get(name) {
4528 Some(id) => *id,
4529 None => {
4530 log::trace!("adding unique interface {name}");
4531 self.interfaces_to_add
4532 .push((name.clone(), into_id, *from_interface_id));
4533 continue;
4534 }
4535 };
4536
4537 log::trace!("merging duplicate interfaces {name}");
4538 self.build_interface(*from_interface_id, into_interface_id)
4539 .with_context(|| format!("failed to merge interface `{name}`"))?;
4540 }
4541
4542 for (name, from_world_id) in from.worlds.iter() {
4543 let into_world_id = match into.worlds.get(name) {
4544 Some(id) => *id,
4545 None => {
4546 log::trace!("adding unique world {name}");
4547 self.worlds_to_add
4548 .push((name.clone(), into_id, *from_world_id));
4549 continue;
4550 }
4551 };
4552
4553 log::trace!("merging duplicate worlds {name}");
4554 self.build_world(*from_world_id, into_world_id)
4555 .with_context(|| format!("failed to merge world `{name}`"))?;
4556 }
4557
4558 Ok(())
4559 }
4560
4561 fn build_interface(
4562 &mut self,
4563 from_id: InterfaceId,
4564 into_id: InterfaceId,
4565 ) -> anyhow::Result<()> {
4566 let prev = self.interface_map.insert(from_id, into_id);
4567 assert!(prev.is_none());
4568
4569 let from_interface = &self.from.interfaces[from_id];
4570 let into_interface = &self.into.interfaces[into_id];
4571
4572 for (name, from_type_id) in from_interface.types.iter() {
4580 let into_type_id = match into_interface.types.get(name) {
4581 Some(id) => *id,
4582 None => continue,
4585 };
4586 let prev = self.type_map.insert(*from_type_id, into_type_id);
4587 assert!(prev.is_none());
4588
4589 self.build_type_id(*from_type_id, into_type_id)
4590 .with_context(|| format!("mismatch in type `{name}`"))?;
4591 }
4592
4593 for (name, from_func) in from_interface.functions.iter() {
4594 let into_func = match into_interface.functions.get(name) {
4595 Some(func) => func,
4596 None => continue,
4599 };
4600 self.build_function(from_func, into_func)
4601 .with_context(|| format!("mismatch in function `{name}`"))?;
4602 }
4603
4604 Ok(())
4605 }
4606
4607 fn build_type_id(&mut self, from_id: TypeId, into_id: TypeId) -> anyhow::Result<()> {
4608 let _ = from_id;
4612 let _ = into_id;
4613 Ok(())
4614 }
4615
4616 fn build_type(&mut self, from_ty: &Type, into_ty: &Type) -> anyhow::Result<()> {
4617 match (from_ty, into_ty) {
4618 (Type::Id(from), Type::Id(into)) => {
4619 self.build_type_id(*from, *into)?;
4620 }
4621 (from, into) if from != into => bail!("different kinds of types"),
4622 _ => {}
4623 }
4624 Ok(())
4625 }
4626
4627 fn build_function(&mut self, from_func: &Function, into_func: &Function) -> anyhow::Result<()> {
4628 if from_func.name != into_func.name {
4629 bail!(
4630 "different function names `{}` and `{}`",
4631 from_func.name,
4632 into_func.name
4633 );
4634 }
4635 match (&from_func.kind, &into_func.kind) {
4636 (FunctionKind::Freestanding, FunctionKind::Freestanding) => {}
4637 (FunctionKind::AsyncFreestanding, FunctionKind::AsyncFreestanding) => {}
4638
4639 (FunctionKind::Method(from), FunctionKind::Method(into))
4640 | (FunctionKind::Static(from), FunctionKind::Static(into))
4641 | (FunctionKind::AsyncMethod(from), FunctionKind::AsyncMethod(into))
4642 | (FunctionKind::AsyncStatic(from), FunctionKind::AsyncStatic(into))
4643 | (FunctionKind::Constructor(from), FunctionKind::Constructor(into)) => {
4644 self.build_type_id(*from, *into)
4645 .context("different function kind types")?;
4646 }
4647
4648 (FunctionKind::Method(_), _)
4649 | (FunctionKind::Constructor(_), _)
4650 | (FunctionKind::Static(_), _)
4651 | (FunctionKind::Freestanding, _)
4652 | (FunctionKind::AsyncFreestanding, _)
4653 | (FunctionKind::AsyncMethod(_), _)
4654 | (FunctionKind::AsyncStatic(_), _) => {
4655 bail!("different function kind types")
4656 }
4657 }
4658
4659 if from_func.params.len() != into_func.params.len() {
4660 bail!("different number of function parameters");
4661 }
4662 for (from_param, into_param) in from_func.params.iter().zip(&into_func.params) {
4663 if from_param.name != into_param.name {
4664 bail!(
4665 "different function parameter names: {} != {}",
4666 from_param.name,
4667 into_param.name
4668 );
4669 }
4670 self.build_type(&from_param.ty, &into_param.ty)
4671 .with_context(|| {
4672 format!(
4673 "different function parameter types for `{}`",
4674 from_param.name
4675 )
4676 })?;
4677 }
4678 match (&from_func.result, &into_func.result) {
4679 (Some(from_ty), Some(into_ty)) => {
4680 self.build_type(from_ty, into_ty)
4681 .context("different function result types")?;
4682 }
4683 (None, None) => {}
4684 (Some(_), None) | (None, Some(_)) => bail!("different number of function results"),
4685 }
4686 Ok(())
4687 }
4688
4689 fn build_world(&mut self, from_id: WorldId, into_id: WorldId) -> anyhow::Result<()> {
4690 let prev = self.world_map.insert(from_id, into_id);
4691 assert!(prev.is_none());
4692
4693 let from_world = &self.from.worlds[from_id];
4694 let into_world = &self.into.worlds[into_id];
4695
4696 if from_world.imports.len() != into_world.imports.len() {
4705 bail!("world contains different number of imports than expected");
4706 }
4707 if from_world.exports.len() != into_world.exports.len() {
4708 bail!("world contains different number of exports than expected");
4709 }
4710
4711 for (from_name, from) in from_world.imports.iter() {
4712 let into_name = MergeMap::map_name(from_name, &self.interface_map);
4713 let name_str = self.from.name_world_key(from_name);
4714 let into = into_world
4715 .imports
4716 .get(&into_name)
4717 .ok_or_else(|| anyhow!("import `{name_str}` not found in target world"))?;
4718 self.match_world_item(from, into)
4719 .with_context(|| format!("import `{name_str}` didn't match target world"))?;
4720 }
4721
4722 for (from_name, from) in from_world.exports.iter() {
4723 let into_name = MergeMap::map_name(from_name, &self.interface_map);
4724 let name_str = self.from.name_world_key(from_name);
4725 let into = into_world
4726 .exports
4727 .get(&into_name)
4728 .ok_or_else(|| anyhow!("export `{name_str}` not found in target world"))?;
4729 self.match_world_item(from, into)
4730 .with_context(|| format!("export `{name_str}` didn't match target world"))?;
4731 }
4732
4733 Ok(())
4734 }
4735
4736 fn map_name(
4737 from_name: &WorldKey,
4738 interface_map: &HashMap<InterfaceId, InterfaceId>,
4739 ) -> WorldKey {
4740 match from_name {
4741 WorldKey::Name(s) => WorldKey::Name(s.clone()),
4742 WorldKey::Interface(id) => {
4743 WorldKey::Interface(interface_map.get(id).copied().unwrap_or(*id))
4744 }
4745 }
4746 }
4747
4748 fn match_world_item(&mut self, from: &WorldItem, into: &WorldItem) -> anyhow::Result<()> {
4749 match (from, into) {
4750 (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
4751 match (
4752 &self.from.interfaces[*from].name,
4753 &self.into.interfaces[*into].name,
4754 ) {
4755 (None, None) => self.build_interface(*from, *into)?,
4759
4760 _ => {
4765 if self.interface_map.get(from) != Some(into) {
4766 bail!("interfaces are not the same");
4767 }
4768 }
4769 }
4770 }
4771 (WorldItem::Function(from), WorldItem::Function(into)) => {
4772 let _ = (from, into);
4773 }
4776 (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
4777 let prev = self.type_map.insert(*from, *into);
4780 assert!(prev.is_none());
4781 }
4782
4783 (WorldItem::Interface { .. }, _)
4784 | (WorldItem::Function(_), _)
4785 | (WorldItem::Type { .. }, _) => {
4786 bail!("world items do not have the same type")
4787 }
4788 }
4789 Ok(())
4790 }
4791}
4792
4793fn update_stability(from: &Stability, into: &mut Stability, span: Span) -> ResolveResult<()> {
4799 if from == into || from.is_unknown() {
4802 return Ok(());
4803 }
4804 if into.is_unknown() {
4807 *into = from.clone();
4808 return Ok(());
4809 }
4810
4811 Err(ResolveError::from(ResolveErrorKind::StabilityMismatch {
4814 span,
4815 from: from.clone(),
4816 into: into.clone(),
4817 }))
4818}
4819
4820fn merge_include_stability(
4821 from: &Stability,
4822 into: &mut Stability,
4823 is_external_include: bool,
4824 span: Span,
4825) -> ResolveResult<()> {
4826 if is_external_include && from.is_stable() {
4827 log::trace!("dropped stability from external package");
4828 *into = Stability::Unknown;
4829 return Ok(());
4830 }
4831
4832 update_stability(from, into, span)
4833}
4834
4835#[cfg(test)]
4836mod tests {
4837 use crate::alloc::format;
4838 use crate::alloc::string::{String, ToString};
4839 use crate::alloc::vec::Vec;
4840 use crate::{Resolve, SourceMap, WorldItem, WorldKey};
4841 use anyhow::Result;
4842
4843 #[test]
4844 fn select_world() -> Result<()> {
4845 let mut resolve = Resolve::default();
4846 resolve.push_str(
4847 "test.wit",
4848 r#"
4849 package foo:bar@0.1.0;
4850
4851 world foo {}
4852 "#,
4853 )?;
4854 resolve.push_str(
4855 "test.wit",
4856 r#"
4857 package foo:baz@0.1.0;
4858
4859 world foo {}
4860 "#,
4861 )?;
4862 resolve.push_str(
4863 "test.wit",
4864 r#"
4865 package foo:baz@0.2.0;
4866
4867 world foo {}
4868 "#,
4869 )?;
4870
4871 let dummy = resolve.push_str(
4872 "test.wit",
4873 r#"
4874 package foo:dummy;
4875
4876 world foo {}
4877 "#,
4878 )?;
4879
4880 assert!(resolve.select_world(&[dummy], None).is_ok());
4881 assert!(resolve.select_world(&[dummy], Some("xx")).is_err());
4882 assert!(resolve.select_world(&[dummy], Some("")).is_err());
4883 assert!(resolve.select_world(&[dummy], Some("foo:bar/foo")).is_ok());
4884 assert!(
4885 resolve
4886 .select_world(&[dummy], Some("foo:bar/foo@0.1.0"))
4887 .is_ok()
4888 );
4889 assert!(resolve.select_world(&[dummy], Some("foo:baz/foo")).is_err());
4890 assert!(
4891 resolve
4892 .select_world(&[dummy], Some("foo:baz/foo@0.1.0"))
4893 .is_ok()
4894 );
4895 assert!(
4896 resolve
4897 .select_world(&[dummy], Some("foo:baz/foo@0.2.0"))
4898 .is_ok()
4899 );
4900 Ok(())
4901 }
4902
4903 #[test]
4904 fn wasm_import_name_future_and_stream_intrinsics() -> Result<()> {
4905 use crate::{FutureIntrinsic, LiftLowerAbi, ManglingAndAbi, StreamIntrinsic, WasmImport};
4906
4907 let mut resolve = Resolve::default();
4908 let pkg = resolve.push_str(
4909 "test.wit",
4910 r#"
4911 package foo:bar;
4912
4913 interface iface {
4914 iface-func: func(x: future<u32>) -> stream<u32>;
4915 }
4916
4917 world w {
4918 import import-func: func(x: future<future<u32>>, y: u32) -> stream<string>;
4919 export export-func: func(x: future, y: stream);
4920 import iface;
4921 export iface;
4922 }
4923 "#,
4924 )?;
4925 let world = resolve.packages[pkg].worlds["w"];
4926 let world = &resolve.worlds[world];
4927 let mangling = ManglingAndAbi::Legacy(LiftLowerAbi::AsyncStackful);
4928
4929 let WorldItem::Function(import_func) =
4930 &world.imports[&WorldKey::Name("import-func".to_string())]
4931 else {
4932 panic!("expected `import-func` to be a top-level world import");
4933 };
4934 let WorldItem::Function(export_func) =
4935 &world.exports[&WorldKey::Name("export-func".to_string())]
4936 else {
4937 panic!("expected `export-func` to be a top-level world export");
4938 };
4939 let import_types = import_func.find_futures_and_streams(&resolve);
4940 assert_eq!(import_types.len(), 3);
4941
4942 let (interface_key, interface_func) = world
4943 .imports
4944 .iter()
4945 .find_map(|(key, item)| match item {
4946 WorldItem::Interface { id, .. } => Some((
4947 key.clone(),
4948 &resolve.interfaces[*id].functions["iface-func"],
4949 )),
4950 _ => None,
4951 })
4952 .expect("expected interface import");
4953 let interface_types = interface_func.find_futures_and_streams(&resolve);
4954 assert_eq!(interface_types.len(), 2);
4955
4956 let (module, name) = resolve.wasm_import_name(
4957 mangling,
4958 WasmImport::FutureIntrinsic {
4959 interface: None,
4960 func: import_func,
4961 ty: Some(import_types[0]),
4962 intrinsic: FutureIntrinsic::New,
4963 exported: false,
4964 async_: false,
4965 },
4966 );
4967 assert_eq!(module, "$root");
4968 assert_eq!(name, "[future-new-0]import-func");
4969
4970 let (module, name) = resolve.wasm_import_name(
4971 mangling,
4972 WasmImport::FutureIntrinsic {
4973 interface: None,
4974 func: import_func,
4975 ty: Some(import_types[1]),
4976 intrinsic: FutureIntrinsic::Read,
4977 exported: false,
4978 async_: true,
4979 },
4980 );
4981 assert_eq!(module, "$root");
4982 assert_eq!(name, "[async-lower][future-read-1]import-func");
4983
4984 let (module, name) = resolve.wasm_import_name(
4985 mangling,
4986 WasmImport::StreamIntrinsic {
4987 interface: None,
4988 func: import_func,
4989 ty: Some(import_types[2]),
4990 intrinsic: StreamIntrinsic::CancelRead,
4991 exported: false,
4992 async_: true,
4993 },
4994 );
4995 assert_eq!(module, "$root");
4996 assert_eq!(name, "[async-lower][stream-cancel-read-2]import-func");
4997
4998 let (module, name) = resolve.wasm_import_name(
4999 mangling,
5000 WasmImport::FutureIntrinsic {
5001 interface: None,
5002 func: export_func,
5003 ty: None,
5004 intrinsic: FutureIntrinsic::DropReadable,
5005 exported: true,
5006 async_: false,
5007 },
5008 );
5009 assert_eq!(module, "[export]$root");
5010 assert_eq!(name, "[future-drop-readable-unit]export-func");
5011
5012 let (module, name) = resolve.wasm_import_name(
5013 mangling,
5014 WasmImport::StreamIntrinsic {
5015 interface: None,
5016 func: export_func,
5017 ty: None,
5018 intrinsic: StreamIntrinsic::Write,
5019 exported: true,
5020 async_: true,
5021 },
5022 );
5023 assert_eq!(module, "[export]$root");
5024 assert_eq!(name, "[async-lower][stream-write-unit]export-func");
5025
5026 let (module, name) = resolve.wasm_import_name(
5027 mangling,
5028 WasmImport::StreamIntrinsic {
5029 interface: Some(&interface_key),
5030 func: interface_func,
5031 ty: Some(interface_types[1]),
5032 intrinsic: StreamIntrinsic::Read,
5033 exported: true,
5034 async_: false,
5035 },
5036 );
5037 assert_eq!(
5038 module,
5039 format!("[export]{}", resolve.name_world_key(&interface_key))
5040 );
5041 assert_eq!(name, "[stream-read-1]iface-func");
5042
5043 Ok(())
5044 }
5045
5046 #[test]
5049 fn select_world_multiple_packages() -> Result<()> {
5050 use wit_parser::Resolve;
5051
5052 let mut resolve = Resolve::default();
5053
5054 let stuff = resolve.push_str(
5056 "./my-test.wit",
5057 r#"
5058 package test:stuff;
5059
5060 world foo {
5061 // ...
5062 }
5063 "#,
5064 )?;
5065 assert!(resolve.select_world(&[stuff], None).is_ok());
5066 assert!(resolve.select_world(&[stuff], Some("foo")).is_ok());
5067
5068 let empty = resolve.push_str(
5071 "./my-test.wit",
5072 r#"
5073 package test:empty;
5074 "#,
5075 )?;
5076 assert!(resolve.select_world(&[stuff, empty], None).is_err());
5077 assert!(resolve.select_world(&[stuff, empty], Some("foo")).is_err());
5078 assert!(resolve.select_world(&[empty], None).is_err());
5079 assert!(resolve.select_world(&[empty], Some("foo")).is_err());
5080
5081 Ok(())
5082 }
5083
5084 #[test]
5086 fn select_world_versions() -> Result<()> {
5087 use wit_parser::Resolve;
5088
5089 let mut resolve = Resolve::default();
5090
5091 let _id = resolve.push_str(
5092 "./my-test.wit",
5093 r#"
5094 package example:distraction;
5095 "#,
5096 )?;
5097
5098 let versions_1 = resolve.push_str(
5101 "./my-test.wit",
5102 r#"
5103 package example:versions@1.0.0;
5104
5105 world foo { /* ... */ }
5106 "#,
5107 )?;
5108 assert!(resolve.select_world(&[versions_1], Some("foo")).is_ok());
5109 assert!(
5110 resolve
5111 .select_world(&[versions_1], Some("foo@1.0.0"))
5112 .is_err()
5113 );
5114 assert!(
5115 resolve
5116 .select_world(&[versions_1], Some("example:versions/foo"))
5117 .is_ok()
5118 );
5119 assert!(
5120 resolve
5121 .select_world(&[versions_1], Some("example:versions/foo@1.0.0"))
5122 .is_ok()
5123 );
5124
5125 let versions_2 = resolve.push_str(
5128 "./my-test.wit",
5129 r#"
5130 package example:versions@2.0.0;
5131
5132 world foo { /* ... */ }
5133 "#,
5134 )?;
5135 assert!(
5136 resolve
5137 .select_world(&[versions_1, versions_2], Some("foo"))
5138 .is_err()
5139 );
5140 assert!(
5141 resolve
5142 .select_world(&[versions_1, versions_2], Some("foo@1.0.0"))
5143 .is_err()
5144 );
5145 assert!(
5146 resolve
5147 .select_world(&[versions_1, versions_2], Some("foo@2.0.0"))
5148 .is_err()
5149 );
5150 assert!(
5151 resolve
5152 .select_world(&[versions_1, versions_2], Some("example:versions/foo"))
5153 .is_err()
5154 );
5155 assert!(
5156 resolve
5157 .select_world(
5158 &[versions_1, versions_2],
5159 Some("example:versions/foo@1.0.0")
5160 )
5161 .is_ok()
5162 );
5163 assert!(
5164 resolve
5165 .select_world(
5166 &[versions_1, versions_2],
5167 Some("example:versions/foo@2.0.0")
5168 )
5169 .is_ok()
5170 );
5171
5172 Ok(())
5173 }
5174
5175 #[test]
5177 fn select_world_override_qualification() -> Result<()> {
5178 use wit_parser::Resolve;
5179
5180 let mut resolve = Resolve::default();
5181
5182 let other = resolve.push_str(
5183 "./my-test.wit",
5184 r#"
5185 package example:other;
5186
5187 world foo { }
5188 "#,
5189 )?;
5190
5191 let fq = resolve.push_str(
5193 "./my-test.wit",
5194 r#"
5195 package example:fq;
5196
5197 world bar { }
5198 "#,
5199 )?;
5200 assert!(resolve.select_world(&[other, fq], Some("foo")).is_err());
5201 assert!(resolve.select_world(&[other, fq], Some("bar")).is_err());
5202 assert!(
5203 resolve
5204 .select_world(&[other, fq], Some("example:other/foo"))
5205 .is_ok()
5206 );
5207 assert!(
5208 resolve
5209 .select_world(&[other, fq], Some("example:fq/bar"))
5210 .is_ok()
5211 );
5212 assert!(
5213 resolve
5214 .select_world(&[other, fq], Some("example:other/bar"))
5215 .is_err()
5216 );
5217 assert!(
5218 resolve
5219 .select_world(&[other, fq], Some("example:fq/foo"))
5220 .is_err()
5221 );
5222
5223 Ok(())
5224 }
5225
5226 #[test]
5228 fn select_world_fully_qualified() -> Result<()> {
5229 use wit_parser::Resolve;
5230
5231 let mut resolve = Resolve::default();
5232
5233 let distraction = resolve.push_str(
5234 "./my-test.wit",
5235 r#"
5236 package example:distraction;
5237 "#,
5238 )?;
5239
5240 let multiworld = resolve.push_str(
5243 "./my-test.wit",
5244 r#"
5245 package example:multiworld;
5246
5247 world foo { /* ... */ }
5248
5249 world bar { /* ... */ }
5250 "#,
5251 )?;
5252 assert!(
5253 resolve
5254 .select_world(&[distraction, multiworld], None)
5255 .is_err()
5256 );
5257 assert!(
5258 resolve
5259 .select_world(&[distraction, multiworld], Some("foo"))
5260 .is_err()
5261 );
5262 assert!(
5263 resolve
5264 .select_world(&[distraction, multiworld], Some("example:multiworld/foo"))
5265 .is_ok()
5266 );
5267 assert!(
5268 resolve
5269 .select_world(&[distraction, multiworld], Some("bar"))
5270 .is_err()
5271 );
5272 assert!(
5273 resolve
5274 .select_world(&[distraction, multiworld], Some("example:multiworld/bar"))
5275 .is_ok()
5276 );
5277
5278 Ok(())
5279 }
5280
5281 #[test]
5283 fn select_world_packages() -> Result<()> {
5284 use wit_parser::Resolve;
5285
5286 let mut resolve = Resolve::default();
5287
5288 let wit1 = resolve.push_str(
5291 "./my-test.wit",
5292 r#"
5293 package example:wit1;
5294
5295 world foo {
5296 // ...
5297 }
5298 "#,
5299 )?;
5300 assert!(resolve.select_world(&[wit1], None).is_ok());
5301 assert!(resolve.select_world(&[wit1], Some("foo")).is_ok());
5302 assert!(
5303 resolve
5304 .select_world(&[wit1], Some("example:wit1/foo"))
5305 .is_ok()
5306 );
5307 assert!(resolve.select_world(&[wit1], Some("bar")).is_err());
5308 assert!(
5309 resolve
5310 .select_world(&[wit1], Some("example:wit2/foo"))
5311 .is_err()
5312 );
5313
5314 let wit2 = resolve.push_str(
5317 "./my-test.wit",
5318 r#"
5319 package example:wit2;
5320
5321 world foo { /* ... */ }
5322 "#,
5323 )?;
5324 assert!(resolve.select_world(&[wit1, wit2], None).is_err());
5325 assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
5326 assert!(
5327 resolve
5328 .select_world(&[wit1, wit2], Some("example:wit1/foo"))
5329 .is_ok()
5330 );
5331 assert!(resolve.select_world(&[wit2], None).is_ok());
5332 assert!(resolve.select_world(&[wit2], Some("foo")).is_ok());
5333 assert!(
5334 resolve
5335 .select_world(&[wit2], Some("example:wit1/foo"))
5336 .is_ok()
5337 );
5338 assert!(resolve.select_world(&[wit1, wit2], Some("bar")).is_err());
5339 assert!(
5340 resolve
5341 .select_world(&[wit1, wit2], Some("example:wit2/foo"))
5342 .is_ok()
5343 );
5344 assert!(resolve.select_world(&[wit2], Some("bar")).is_err());
5345 assert!(
5346 resolve
5347 .select_world(&[wit2], Some("example:wit2/foo"))
5348 .is_ok()
5349 );
5350
5351 Ok(())
5352 }
5353
5354 #[test]
5355 fn span_preservation() -> Result<()> {
5356 let mut resolve = Resolve::default();
5357 let pkg = resolve.push_str(
5358 "test.wit",
5359 r#"
5360 package foo:bar;
5361
5362 interface my-iface {
5363 type my-type = u32;
5364 my-func: func();
5365 }
5366
5367 world my-world {
5368 export my-export: func();
5369 }
5370 "#,
5371 )?;
5372
5373 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5374 assert!(resolve.interfaces[iface_id].span.is_known());
5375
5376 let type_id = resolve.interfaces[iface_id].types["my-type"];
5377 assert!(resolve.types[type_id].span.is_known());
5378
5379 assert!(
5380 resolve.interfaces[iface_id].functions["my-func"]
5381 .span
5382 .is_known()
5383 );
5384
5385 let world_id = resolve.packages[pkg].worlds["my-world"];
5386 assert!(resolve.worlds[world_id].span.is_known());
5387
5388 let WorldItem::Function(f) =
5389 &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5390 else {
5391 panic!("expected function");
5392 };
5393 assert!(f.span.is_known());
5394
5395 Ok(())
5396 }
5397
5398 #[test]
5399 fn span_preservation_through_merge() -> Result<()> {
5400 let mut resolve1 = Resolve::default();
5401 resolve1.push_str(
5402 "test1.wit",
5403 r#"
5404 package foo:bar;
5405
5406 interface iface1 {
5407 type type1 = u32;
5408 func1: func();
5409 }
5410 "#,
5411 )?;
5412
5413 let mut resolve2 = Resolve::default();
5414 let pkg2 = resolve2.push_str(
5415 "test2.wit",
5416 r#"
5417 package foo:baz;
5418
5419 interface iface2 {
5420 type type2 = string;
5421 func2: func();
5422 }
5423 "#,
5424 )?;
5425
5426 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5427 let remap = resolve1.merge(resolve2)?;
5428 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5429
5430 assert!(resolve1.interfaces[iface2_id].span.is_known());
5431
5432 let type2_id = resolve1.interfaces[iface2_id].types["type2"];
5433 assert!(resolve1.types[type2_id].span.is_known());
5434
5435 assert!(
5436 resolve1.interfaces[iface2_id].functions["func2"]
5437 .span
5438 .is_known()
5439 );
5440
5441 Ok(())
5442 }
5443
5444 #[test]
5445 fn span_preservation_through_include() -> Result<()> {
5446 let mut resolve = Resolve::default();
5447 let pkg = resolve.push_str(
5448 "test.wit",
5449 r#"
5450 package foo:bar;
5451
5452 world base {
5453 export my-func: func();
5454 }
5455
5456 world extended {
5457 include base;
5458 }
5459 "#,
5460 )?;
5461
5462 let base_id = resolve.packages[pkg].worlds["base"];
5463 let extended_id = resolve.packages[pkg].worlds["extended"];
5464
5465 let WorldItem::Function(base_func) =
5466 &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5467 else {
5468 panic!("expected function");
5469 };
5470 assert!(base_func.span.is_known());
5471
5472 let WorldItem::Function(extended_func) =
5473 &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5474 else {
5475 panic!("expected function");
5476 };
5477 assert!(extended_func.span.is_known());
5478
5479 Ok(())
5480 }
5481
5482 #[test]
5483 fn span_preservation_through_include_with_rename() -> Result<()> {
5484 let mut resolve = Resolve::default();
5485 let pkg = resolve.push_str(
5486 "test.wit",
5487 r#"
5488 package foo:bar;
5489
5490 world base {
5491 export original-name: func();
5492 }
5493
5494 world extended {
5495 include base with { original-name as renamed-func }
5496 }
5497 "#,
5498 )?;
5499
5500 let extended_id = resolve.packages[pkg].worlds["extended"];
5501
5502 let WorldItem::Function(f) =
5503 &resolve.worlds[extended_id].exports[&WorldKey::Name("renamed-func".to_string())]
5504 else {
5505 panic!("expected function");
5506 };
5507 assert!(f.span.is_known());
5508
5509 assert!(
5510 !resolve.worlds[extended_id]
5511 .exports
5512 .contains_key(&WorldKey::Name("original-name".to_string()))
5513 );
5514
5515 Ok(())
5516 }
5517
5518 #[test]
5520 fn span_preservation_through_include_reverse_order() -> Result<()> {
5521 let mut resolve = Resolve::default();
5522 let pkg = resolve.push_str(
5523 "test.wit",
5524 r#"
5525 package foo:bar;
5526
5527 world extended {
5528 include base;
5529 }
5530
5531 world base {
5532 export my-func: func();
5533 }
5534 "#,
5535 )?;
5536
5537 let base_id = resolve.packages[pkg].worlds["base"];
5538 let extended_id = resolve.packages[pkg].worlds["extended"];
5539
5540 let WorldItem::Function(base_func) =
5541 &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5542 else {
5543 panic!("expected function");
5544 };
5545 assert!(base_func.span.is_known());
5546
5547 let WorldItem::Function(extended_func) =
5548 &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5549 else {
5550 panic!("expected function");
5551 };
5552 assert!(extended_func.span.is_known());
5553
5554 Ok(())
5555 }
5556
5557 #[test]
5558 fn span_line_numbers() -> Result<()> {
5559 let mut resolve = Resolve::default();
5560 let pkg = resolve.push_source(
5561 "test.wit",
5562 "package foo:bar;
5563
5564interface my-iface {
5565 type my-type = u32;
5566 my-func: func();
5567}
5568
5569world my-world {
5570 export my-export: func();
5571}
5572",
5573 )?;
5574
5575 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5576 let iface_span = resolve.interfaces[iface_id].span;
5577 let iface_loc = resolve.render_location(iface_span);
5578 assert!(
5579 iface_loc.contains(":3:"),
5580 "interface location was {iface_loc}"
5581 );
5582
5583 let type_id = resolve.interfaces[iface_id].types["my-type"];
5584 let type_span = resolve.types[type_id].span;
5585 let type_loc = resolve.render_location(type_span);
5586 assert!(type_loc.contains(":4:"), "type location was {type_loc}");
5587
5588 let func_span = resolve.interfaces[iface_id].functions["my-func"].span;
5589 let func_loc = resolve.render_location(func_span);
5590 assert!(func_loc.contains(":5:"), "function location was {func_loc}");
5591
5592 let world_id = resolve.packages[pkg].worlds["my-world"];
5593 let world_span = resolve.worlds[world_id].span;
5594 let world_loc = resolve.render_location(world_span);
5595 assert!(world_loc.contains(":8:"), "world location was {world_loc}");
5596
5597 let WorldItem::Function(export_func) =
5598 &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5599 else {
5600 panic!("expected function");
5601 };
5602 let export_loc = resolve.render_location(export_func.span);
5603 assert!(
5604 export_loc.contains(":9:"),
5605 "export location was {export_loc}"
5606 );
5607
5608 Ok(())
5609 }
5610
5611 #[test]
5612 fn span_line_numbers_through_merge() -> Result<()> {
5613 let mut resolve1 = Resolve::default();
5614 resolve1.push_source(
5615 "first.wit",
5616 "package foo:first;
5617
5618interface iface1 {
5619 func1: func();
5620}
5621",
5622 )?;
5623
5624 let mut resolve2 = Resolve::default();
5625 let pkg2 = resolve2.push_source(
5626 "second.wit",
5627 "package foo:second;
5628
5629interface iface2 {
5630 func2: func();
5631}
5632",
5633 )?;
5634
5635 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5636 let remap = resolve1.merge(resolve2)?;
5637 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5638
5639 let iface2_span = resolve1.interfaces[iface2_id].span;
5640 let iface2_loc = resolve1.render_location(iface2_span);
5641 assert!(
5642 iface2_loc.contains("second.wit"),
5643 "should reference second.wit, got {iface2_loc}"
5644 );
5645 assert!(
5646 iface2_loc.contains(":3:"),
5647 "interface should be on line 3, got {iface2_loc}"
5648 );
5649
5650 let func2_span = resolve1.interfaces[iface2_id].functions["func2"].span;
5651 let func2_loc = resolve1.render_location(func2_span);
5652 assert!(
5653 func2_loc.contains("second.wit"),
5654 "should reference second.wit, got {func2_loc}"
5655 );
5656 assert!(
5657 func2_loc.contains(":4:"),
5658 "function should be on line 4, got {func2_loc}"
5659 );
5660
5661 Ok(())
5662 }
5663
5664 #[test]
5665 fn span_line_numbers_multiple_sources() -> Result<()> {
5666 let mut resolve = Resolve::default();
5667
5668 let pkg1 = resolve.push_source(
5669 "first.wit",
5670 "package test:first;
5671
5672interface first-iface {
5673 first-func: func();
5674}
5675",
5676 )?;
5677
5678 let pkg2 = resolve.push_source(
5679 "second.wit",
5680 "package test:second;
5681
5682interface second-iface {
5683 second-func: func();
5684}
5685",
5686 )?;
5687
5688 let iface1_id = resolve.packages[pkg1].interfaces["first-iface"];
5689 let iface1_span = resolve.interfaces[iface1_id].span;
5690 let iface1_loc = resolve.render_location(iface1_span);
5691 assert!(
5692 iface1_loc.contains("first.wit"),
5693 "should reference first.wit, got {iface1_loc}"
5694 );
5695 assert!(
5696 iface1_loc.contains(":3:"),
5697 "interface should be on line 3, got {iface1_loc}"
5698 );
5699
5700 let func1_span = resolve.interfaces[iface1_id].functions["first-func"].span;
5701 let func1_loc = resolve.render_location(func1_span);
5702 assert!(
5703 func1_loc.contains("first.wit"),
5704 "should reference first.wit, got {func1_loc}"
5705 );
5706 assert!(
5707 func1_loc.contains(":4:"),
5708 "function should be on line 4, got {func1_loc}"
5709 );
5710
5711 let iface2_id = resolve.packages[pkg2].interfaces["second-iface"];
5712 let iface2_span = resolve.interfaces[iface2_id].span;
5713 let iface2_loc = resolve.render_location(iface2_span);
5714 assert!(
5715 iface2_loc.contains("second.wit"),
5716 "should reference second.wit, got {iface2_loc}"
5717 );
5718 assert!(
5719 iface2_loc.contains(":3:"),
5720 "interface should be on line 3, got {iface2_loc}"
5721 );
5722
5723 let func2_span = resolve.interfaces[iface2_id].functions["second-func"].span;
5724 let func2_loc = resolve.render_location(func2_span);
5725 assert!(
5726 func2_loc.contains("second.wit"),
5727 "should reference second.wit, got {func2_loc}"
5728 );
5729 assert!(
5730 func2_loc.contains(":4:"),
5731 "function should be on line 4, got {func2_loc}"
5732 );
5733
5734 Ok(())
5735 }
5736
5737 #[test]
5738 fn span_preservation_for_fields_and_cases() -> Result<()> {
5739 use crate::TypeDefKind;
5740
5741 let mut resolve = Resolve::default();
5742 let pkg = resolve.push_str(
5743 "test.wit",
5744 r#"
5745 package foo:bar;
5746
5747 interface my-iface {
5748 record my-record {
5749 field1: u32,
5750 field2: string,
5751 }
5752
5753 flags my-flags {
5754 flag1,
5755 flag2,
5756 }
5757
5758 variant my-variant {
5759 case1,
5760 case2(u32),
5761 }
5762
5763 enum my-enum {
5764 val1,
5765 val2,
5766 }
5767 }
5768 "#,
5769 )?;
5770
5771 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5772
5773 let record_id = resolve.interfaces[iface_id].types["my-record"];
5775 let TypeDefKind::Record(record) = &resolve.types[record_id].kind else {
5776 panic!("expected record");
5777 };
5778 assert!(record.fields[0].span.is_known(), "field1 should have span");
5779 assert!(record.fields[1].span.is_known(), "field2 should have span");
5780
5781 let flags_id = resolve.interfaces[iface_id].types["my-flags"];
5783 let TypeDefKind::Flags(flags) = &resolve.types[flags_id].kind else {
5784 panic!("expected flags");
5785 };
5786 assert!(flags.flags[0].span.is_known(), "flag1 should have span");
5787 assert!(flags.flags[1].span.is_known(), "flag2 should have span");
5788
5789 let variant_id = resolve.interfaces[iface_id].types["my-variant"];
5791 let TypeDefKind::Variant(variant) = &resolve.types[variant_id].kind else {
5792 panic!("expected variant");
5793 };
5794 assert!(variant.cases[0].span.is_known(), "case1 should have span");
5795 assert!(variant.cases[1].span.is_known(), "case2 should have span");
5796
5797 let enum_id = resolve.interfaces[iface_id].types["my-enum"];
5799 let TypeDefKind::Enum(e) = &resolve.types[enum_id].kind else {
5800 panic!("expected enum");
5801 };
5802 assert!(e.cases[0].span.is_known(), "val1 should have span");
5803 assert!(e.cases[1].span.is_known(), "val2 should have span");
5804
5805 Ok(())
5806 }
5807
5808 #[test]
5809 fn span_preservation_for_fields_through_merge() -> Result<()> {
5810 use crate::TypeDefKind;
5811
5812 let mut resolve1 = Resolve::default();
5813 resolve1.push_str(
5814 "test1.wit",
5815 r#"
5816 package foo:bar;
5817
5818 interface iface1 {
5819 record rec1 {
5820 f1: u32,
5821 }
5822 }
5823 "#,
5824 )?;
5825
5826 let mut resolve2 = Resolve::default();
5827 let pkg2 = resolve2.push_str(
5828 "test2.wit",
5829 r#"
5830 package foo:baz;
5831
5832 interface iface2 {
5833 record rec2 {
5834 f2: string,
5835 }
5836
5837 variant var2 {
5838 c2,
5839 }
5840 }
5841 "#,
5842 )?;
5843
5844 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5845 let rec2_old_id = resolve2.interfaces[iface2_old_id].types["rec2"];
5846 let var2_old_id = resolve2.interfaces[iface2_old_id].types["var2"];
5847
5848 let remap = resolve1.merge(resolve2)?;
5849
5850 let rec2_id = remap.types[rec2_old_id.index()].unwrap();
5851 let TypeDefKind::Record(record) = &resolve1.types[rec2_id].kind else {
5852 panic!("expected record");
5853 };
5854 assert!(
5855 record.fields[0].span.is_known(),
5856 "field should have span after merge"
5857 );
5858
5859 let var2_id = remap.types[var2_old_id.index()].unwrap();
5860 let TypeDefKind::Variant(variant) = &resolve1.types[var2_id].kind else {
5861 panic!("expected variant");
5862 };
5863 assert!(
5864 variant.cases[0].span.is_known(),
5865 "case should have span after merge"
5866 );
5867
5868 Ok(())
5869 }
5870
5871 #[test]
5872 fn param_spans_point_to_names() -> Result<()> {
5873 let source = "\
5874package foo:bar;
5875
5876interface iface {
5877 my-func: func(a: u32, b: string);
5878}
5879";
5880 let mut resolve = Resolve::default();
5881 let pkg = resolve.push_str("test.wit", source)?;
5882
5883 let iface_id = resolve.packages[pkg].interfaces["iface"];
5884 let func = &resolve.interfaces[iface_id].functions["my-func"];
5885 assert_eq!(func.params.len(), 2);
5886 for param in &func.params {
5887 let start = param.span.start() as usize;
5888 let end = param.span.end() as usize;
5889 let snippet = &source[start..end];
5890 assert_eq!(
5891 snippet, param.name,
5892 "param `{}` span points to {:?}",
5893 param.name, snippet
5894 );
5895 }
5896
5897 Ok(())
5898 }
5899
5900 #[test]
5901 fn push_groups_resolves_dep_before_main() -> Result<()> {
5902 let dep = {
5905 let mut map = SourceMap::default();
5906 map.push_str(
5907 "file:///dep.wit",
5908 "package foo:dep;\ninterface i { type t = u32; }",
5909 );
5910 map.parse().map_err(|(_, e)| e)?
5911 };
5912 let main = {
5913 let mut map = SourceMap::default();
5914 map.push_str(
5915 "file:///main.wit",
5916 "package foo:main;\ninterface j { use foo:dep/i.{t}; type u = t; }",
5917 );
5918 map.parse().map_err(|(_, e)| e)?
5919 };
5920 let mut resolve = Resolve::default();
5921 resolve.push_groups(main, Vec::from([dep]))?;
5922 assert_eq!(resolve.packages.len(), 2);
5923 Ok(())
5924 }
5925
5926 #[test]
5927 fn push_groups_cycle_error_contains_location() {
5928 let a = {
5932 let mut map = SourceMap::default();
5933 map.push_str(
5934 "file:///a.wit",
5935 "package foo:a;\ninterface i { use foo:b/j.{}; }",
5936 );
5937 map.parse().unwrap()
5938 };
5939 let b = {
5940 let mut map = SourceMap::default();
5941 map.push_str(
5942 "file:///b.wit",
5943 "package foo:b;\ninterface j { use foo:a/i.{}; }",
5944 );
5945 map.parse().unwrap()
5946 };
5947 let mut resolve = Resolve::default();
5948 let err = resolve.push_groups(a, Vec::from([b])).unwrap_err();
5949 let msg = err.render(&resolve.source_map);
5950 assert!(
5951 msg.contains("file:///"),
5952 "cycle error should contain a file URI, got: {msg}"
5953 );
5954 }
5955
5956 #[test]
5957 fn param_spans_preserved_through_merge() -> Result<()> {
5958 let mut resolve1 = Resolve::default();
5959 resolve1.push_str(
5960 "test1.wit",
5961 r#"
5962 package foo:bar;
5963
5964 interface iface1 {
5965 f1: func(x: u32);
5966 }
5967 "#,
5968 )?;
5969
5970 let mut resolve2 = Resolve::default();
5971 let pkg2 = resolve2.push_str(
5972 "test2.wit",
5973 r#"
5974 package foo:baz;
5975
5976 interface iface2 {
5977 f2: func(y: string, z: bool);
5978 }
5979 "#,
5980 )?;
5981
5982 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5983
5984 let remap = resolve1.merge(resolve2)?;
5985
5986 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5987 let func = &resolve1.interfaces[iface2_id].functions["f2"];
5988 for param in &func.params {
5989 assert!(
5990 param.span.is_known(),
5991 "param `{}` should have span after merge",
5992 param.name
5993 );
5994 }
5995
5996 Ok(())
5997 }
5998
5999 #[test]
6004 fn exportize_importize_roundtrip() -> Result<()> {
6005 let mut resolve = Resolve::default();
6006 let pkg = resolve.push_str(
6007 "test.wit",
6008 r#"
6009 package foo:bar;
6010
6011 interface types {
6012 type my-type = u32;
6013 }
6014
6015 interface api {
6016 use types.{my-type};
6017 do-something: func(a: my-type) -> my-type;
6018 }
6019
6020 world w {
6021 export api;
6022 }
6023 "#,
6024 )?;
6025 let world_id = resolve.packages[pkg].worlds["w"];
6026
6027 let original_export_keys: Vec<String> = resolve.worlds[world_id]
6029 .exports
6030 .keys()
6031 .map(|k| resolve.name_world_key(k))
6032 .collect();
6033 assert!(!original_export_keys.is_empty());
6034 assert!(resolve.worlds[world_id].imports.iter().all(|(_, item)| {
6035 matches!(item, WorldItem::Interface { .. })
6038 }));
6039
6040 resolve.importize(world_id, Some("w-temp".to_string()))?;
6042 assert!(
6043 resolve.worlds[world_id].exports.is_empty(),
6044 "importize should leave no exports"
6045 );
6046 for key in &original_export_keys {
6048 assert!(
6049 resolve.worlds[world_id]
6050 .imports
6051 .keys()
6052 .any(|k| resolve.name_world_key(k) == *key),
6053 "expected `{key}` to be an import after importize"
6054 );
6055 }
6056
6057 resolve.exportize(world_id, Some("w-final".to_string()), None)?;
6059 assert!(
6060 !resolve.worlds[world_id].exports.is_empty(),
6061 "exportize should produce exports"
6062 );
6063 let final_export_keys: Vec<String> = resolve.worlds[world_id]
6065 .exports
6066 .keys()
6067 .map(|k| resolve.name_world_key(k))
6068 .collect();
6069 for key in &original_export_keys {
6070 assert!(
6071 final_export_keys.contains(key),
6072 "expected `{key}` to be an export after round-trip, got exports: {final_export_keys:?}"
6073 );
6074 }
6075
6076 Ok(())
6077 }
6078}