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::new_semantic(iface_span, "interface not found in package")
3786 })?;
3787 assert_eq!(self.interfaces.len(), unresolved_iface_id.index());
3788 self.interfaces.push(Some(iface_id));
3789 }
3790 for (id, _) in unresolved.interfaces.iter().skip(self.interfaces.len()) {
3791 assert!(
3792 interface_to_package.get(&id).is_none(),
3793 "found foreign interface after local interface"
3794 );
3795 }
3796 Ok(())
3797 }
3798
3799 fn process_foreign_worlds(
3800 &mut self,
3801 unresolved: &UnresolvedPackage,
3802 world_to_package: &HashMap<WorldId, (&PackageName, &String, Span, &Vec<Stability>)>,
3803 resolve: &mut Resolve,
3804 parent_pkg_id: &PackageId,
3805 ) -> ResolveResult<()> {
3806 for (unresolved_world_id, unresolved_world) in unresolved.worlds.iter() {
3807 let (pkg_name, world, span, stabilities) =
3808 match world_to_package.get(&unresolved_world_id) {
3809 Some(items) => *items,
3810 None => break,
3813 };
3814
3815 let pkgid = resolve
3816 .package_names
3817 .get(pkg_name)
3818 .copied()
3819 .ok_or_else(|| {
3820 ResolveError::from(ResolveErrorKind::PackageNotFound {
3821 span,
3822 requested: pkg_name.clone(),
3823 known: resolve.package_names.keys().cloned().collect(),
3824 })
3825 })?;
3826 let pkg = &resolve.packages[pkgid];
3827 let world_span = unresolved_world.span;
3828
3829 let mut enabled = false;
3830 for stability in stabilities {
3831 if resolve.include_stability(stability, parent_pkg_id, world_span)? {
3832 enabled = true;
3833 break;
3834 }
3835 }
3836
3837 if !enabled {
3838 self.worlds.push(None);
3839 continue;
3840 }
3841
3842 let world_id = pkg.worlds.get(world).copied().ok_or_else(|| {
3843 ResolveError::new_semantic(world_span, "world not found in package")
3844 })?;
3845 assert_eq!(self.worlds.len(), unresolved_world_id.index());
3846 self.worlds.push(Some(world_id));
3847 }
3848 for (id, _) in unresolved.worlds.iter().skip(self.worlds.len()) {
3849 assert!(
3850 world_to_package.get(&id).is_none(),
3851 "found foreign world after local world"
3852 );
3853 }
3854 Ok(())
3855 }
3856
3857 fn process_foreign_types(
3858 &mut self,
3859 unresolved: &UnresolvedPackage,
3860 pkgid: PackageId,
3861 resolve: &mut Resolve,
3862 ) -> ResolveResult<()> {
3863 for (unresolved_type_id, unresolved_ty) in unresolved.types.iter() {
3864 match unresolved_ty.kind {
3868 TypeDefKind::Unknown => {}
3869 _ => break,
3870 }
3871
3872 let span = unresolved_ty.span;
3873 if !resolve.include_stability(&unresolved_ty.stability, &pkgid, span)? {
3874 self.types.push(None);
3875 continue;
3876 }
3877
3878 let unresolved_iface_id = match unresolved_ty.owner {
3879 TypeOwner::Interface(id) => id,
3880 _ => unreachable!(),
3881 };
3882 let iface_id = self.map_interface(unresolved_iface_id, Default::default())?;
3883 let name = unresolved_ty.name.as_ref().unwrap();
3884 let span = unresolved.unknown_type_spans[unresolved_type_id.index()];
3885 let type_id = *resolve.interfaces[iface_id]
3886 .types
3887 .get(name)
3888 .ok_or_else(|| {
3889 ResolveError::new_semantic(
3890 span,
3891 format!("type `{name}` not defined in interface"),
3892 )
3893 })?;
3894 assert_eq!(self.types.len(), unresolved_type_id.index());
3895 self.types.push(Some(type_id));
3896 }
3897 for (_, ty) in unresolved.types.iter().skip(self.types.len()) {
3898 if let TypeDefKind::Unknown = ty.kind {
3899 panic!("unknown type after defined type");
3900 }
3901 }
3902 Ok(())
3903 }
3904
3905 fn update_typedef(
3906 &mut self,
3907 resolve: &mut Resolve,
3908 ty: &mut TypeDef,
3909 span: Span,
3910 ) -> ResolveResult<()> {
3911 use crate::TypeDefKind::*;
3914 match &mut ty.kind {
3915 Handle(handle) => match handle {
3916 crate::Handle::Own(ty) | crate::Handle::Borrow(ty) => {
3917 self.update_type_id(ty, span)?
3918 }
3919 },
3920 Resource => {}
3921 Record(r) => {
3922 for field in r.fields.iter_mut() {
3923 self.update_ty(resolve, &mut field.ty, field.span)?
3924 }
3925 }
3926 Tuple(t) => {
3927 for ty in t.types.iter_mut() {
3928 self.update_ty(resolve, ty, span)?;
3929 }
3930 }
3931 Variant(v) => {
3932 for case in v.cases.iter_mut() {
3933 if let Some(t) = &mut case.ty {
3934 self.update_ty(resolve, t, span)?;
3935 }
3936 }
3937 }
3938 Option(t)
3939 | List(t, ..)
3940 | FixedLengthList(t, ..)
3941 | Future(Some(t))
3942 | Stream(Some(t)) => self.update_ty(resolve, t, span)?,
3943 Map(k, v) => {
3944 self.update_ty(resolve, k, span)?;
3945 self.update_ty(resolve, v, span)?;
3946 }
3947 Result(r) => {
3948 if let Some(ty) = &mut r.ok {
3949 self.update_ty(resolve, ty, span)?;
3950 }
3951 if let Some(ty) = &mut r.err {
3952 self.update_ty(resolve, ty, span)?;
3953 }
3954 }
3955
3956 Type(crate::Type::Id(id)) => self.update_type_id(id, span)?,
3961 Type(_) => {}
3962
3963 Flags(_) | Enum(_) | Future(None) | Stream(None) => {}
3965
3966 Unknown => unreachable!(),
3967 }
3968
3969 Ok(())
3970 }
3971
3972 fn update_ty(&mut self, resolve: &mut Resolve, ty: &mut Type, span: Span) -> ResolveResult<()> {
3973 let id = match ty {
3974 Type::Id(id) => id,
3975 _ => return Ok(()),
3976 };
3977 self.update_type_id(id, span)?;
3978
3979 let mut cur = *id;
3984 let points_to_resource = loop {
3985 match resolve.types[cur].kind {
3986 TypeDefKind::Type(Type::Id(id)) => cur = id,
3987 TypeDefKind::Resource => break true,
3988 _ => break false,
3989 }
3990 };
3991
3992 if points_to_resource {
3993 *id = *self.own_handles.entry(*id).or_insert_with(|| {
3994 resolve.types.alloc(TypeDef {
3995 name: None,
3996 owner: TypeOwner::None,
3997 kind: TypeDefKind::Handle(Handle::Own(*id)),
3998 docs: Default::default(),
3999 stability: Default::default(),
4000 span: Default::default(),
4001 external_id: None,
4002 })
4003 });
4004 }
4005 Ok(())
4006 }
4007
4008 fn update_type_id(&self, id: &mut TypeId, span: Span) -> ResolveResult<()> {
4009 *id = self.map_type(*id, span)?;
4010 Ok(())
4011 }
4012
4013 fn update_interface(
4014 &mut self,
4015 resolve: &mut Resolve,
4016 iface: &mut Interface,
4017 ) -> ResolveResult<()> {
4018 iface.types.retain(|_, ty| self.types[ty.index()].is_some());
4019 let iface_pkg_id = iface.package.as_ref().unwrap_or_else(|| {
4020 panic!(
4021 "unexpectedly missing package on interface [{}]",
4022 iface
4023 .name
4024 .as_ref()
4025 .map(String::as_str)
4026 .unwrap_or("<unknown>"),
4027 )
4028 });
4029
4030 for (_name, ty) in iface.types.iter_mut() {
4033 self.update_type_id(ty, iface.span)?;
4034 }
4035 for (_, func) in iface.functions.iter_mut() {
4036 let span = func.span;
4037 if !resolve.include_stability(&func.stability, iface_pkg_id, span)? {
4038 continue;
4039 }
4040 self.update_function(resolve, func, span)?
4041 }
4042
4043 for (name, func) in mem::take(&mut iface.functions) {
4046 if resolve.include_stability(&func.stability, iface_pkg_id, func.span)? {
4047 iface.functions.insert(name, func);
4048 }
4049 }
4050
4051 Ok(())
4052 }
4053
4054 fn update_function(
4055 &mut self,
4056 resolve: &mut Resolve,
4057 func: &mut Function,
4058 span: Span,
4059 ) -> ResolveResult<()> {
4060 if let Some(id) = func.kind.resource_mut() {
4061 self.update_type_id(id, span)?;
4062 }
4063 for param in func.params.iter_mut() {
4064 self.update_ty(resolve, &mut param.ty, span)?;
4065 }
4066 if let Some(ty) = &mut func.result {
4067 self.update_ty(resolve, ty, span)?;
4068 }
4069
4070 if let Some(ty) = &func.result {
4071 if self.type_has_borrow(resolve, ty) {
4072 return Err(ResolveError::new_semantic(
4073 span,
4074 format!(
4075 "function `{}` returns a type which contains a `borrow<T>` which is not supported",
4076 func.name,
4077 ),
4078 ));
4079 }
4080 }
4081
4082 Ok(())
4083 }
4084
4085 fn update_world(
4086 &mut self,
4087 world: &mut World,
4088 resolve: &mut Resolve,
4089 pkg_id: &PackageId,
4090 ) -> ResolveResult<()> {
4091 let imports = mem::take(&mut world.imports).into_iter().map(|p| (p, true));
4095 let exports = mem::take(&mut world.exports)
4096 .into_iter()
4097 .map(|p| (p, false));
4098 for ((mut name, mut item), import) in imports.chain(exports) {
4099 let span = item.span();
4100 if let WorldItem::Type { id, .. } = &mut item {
4103 *id = self.map_type(*id, span)?;
4104 }
4105 let stability = item.stability(resolve);
4106 if !resolve.include_stability(stability, pkg_id, span)? {
4107 continue;
4108 }
4109 self.update_world_key(&mut name, span)?;
4110 match &mut item {
4111 WorldItem::Interface { id, .. } => {
4112 *id = self.map_interface(*id, span)?;
4113 }
4114 WorldItem::Function(f) => {
4115 self.update_function(resolve, f, span)?;
4116 }
4117 WorldItem::Type { .. } => {
4118 }
4120 }
4121
4122 let dst = if import {
4123 &mut world.imports
4124 } else {
4125 &mut world.exports
4126 };
4127 let prev = dst.insert(name, item);
4128 assert!(prev.is_none());
4129 }
4130
4131 Ok(())
4132 }
4133
4134 fn process_world_includes(
4135 &self,
4136 id: WorldId,
4137 resolve: &mut Resolve,
4138 pkg_id: &PackageId,
4139 ) -> ResolveResult<()> {
4140 let world = &mut resolve.worlds[id];
4141 let includes = mem::take(&mut world.includes);
4144 for include in includes {
4145 if !resolve.include_stability(&include.stability, pkg_id, include.span)? {
4146 continue;
4147 }
4148 self.resolve_include(
4149 id,
4150 include.id,
4151 &include.names,
4152 include.span,
4153 pkg_id,
4154 resolve,
4155 )?;
4156 }
4157
4158 Self::validate_world_case_insensitive_names(resolve, id)?;
4160
4161 Ok(())
4162 }
4163
4164 fn validate_world_case_insensitive_names(
4168 resolve: &Resolve,
4169 world_id: WorldId,
4170 ) -> ResolveResult<()> {
4171 let world = &resolve.worlds[world_id];
4172
4173 let validate_names =
4175 |items: &IndexMap<WorldKey, WorldItem>, item_type: &str| -> ResolveResult<()> {
4176 let mut seen_lowercase: HashMap<String, String> = HashMap::new();
4177
4178 for key in items.keys() {
4179 if let WorldKey::Name(name) = key {
4181 let lowercase_name = name.to_lowercase();
4182
4183 if let Some(existing_name) = seen_lowercase.get(&lowercase_name) {
4184 if existing_name != name {
4187 return Err(ResolveError::new_semantic(
4191 Span::default(),
4192 format!(
4193 "{item_type} `{name}` in world `{}` conflicts with \
4194 {item_type} `{existing_name}` \
4195 (kebab-case identifiers are case-insensitive)",
4196 world.name,
4197 ),
4198 ));
4199 }
4200 }
4201
4202 seen_lowercase.insert(lowercase_name, name.clone());
4203 }
4204 }
4205
4206 Ok(())
4207 };
4208
4209 validate_names(&world.imports, "import")?;
4210 validate_names(&world.exports, "export")?;
4211
4212 Ok(())
4213 }
4214
4215 fn update_world_key(&self, key: &mut WorldKey, span: Span) -> ResolveResult<()> {
4216 match key {
4217 WorldKey::Name(_) => {}
4218 WorldKey::Interface(id) => {
4219 *id = self.map_interface(*id, span)?;
4220 }
4221 }
4222 Ok(())
4223 }
4224
4225 fn resolve_include(
4226 &self,
4227 id: WorldId,
4228 include_world_id_orig: WorldId,
4229 names: &[IncludeName],
4230 span: Span,
4231 pkg_id: &PackageId,
4232 resolve: &mut Resolve,
4233 ) -> ResolveResult<()> {
4234 let world = &resolve.worlds[id];
4235 let include_world_id = self.map_world(include_world_id_orig, span)?;
4236 let include_world = resolve.worlds[include_world_id].clone();
4237 let mut names_ = names.to_owned();
4238 let is_external_include = world.package != include_world.package;
4239
4240 for import in include_world.imports.iter() {
4242 self.remove_matching_name(import, &mut names_);
4243 }
4244 for export in include_world.exports.iter() {
4245 self.remove_matching_name(export, &mut names_);
4246 }
4247 if !names_.is_empty() {
4248 return Err(ResolveError::new_semantic(
4249 span,
4250 format!(
4251 "no import or export kebab-name `{}`. Note that an ID does not support renaming",
4252 names_[0].name
4253 ),
4254 ));
4255 }
4256
4257 let mut maps = Default::default();
4258 let mut cloner = clone::Cloner::new(
4259 resolve,
4260 &mut maps,
4261 TypeOwner::World(if is_external_include {
4262 include_world_id
4263 } else {
4264 include_world_id
4265 }),
4267 TypeOwner::World(id),
4268 );
4269 cloner.new_package = Some(*pkg_id);
4270
4271 for import in include_world.imports.iter() {
4273 self.resolve_include_item(
4274 &mut cloner,
4275 names,
4276 |resolve| &mut resolve.worlds[id].imports,
4277 import,
4278 span,
4279 "import",
4280 is_external_include,
4281 )?;
4282 }
4283
4284 for export in include_world.exports.iter() {
4285 self.resolve_include_item(
4286 &mut cloner,
4287 names,
4288 |resolve| &mut resolve.worlds[id].exports,
4289 export,
4290 span,
4291 "export",
4292 is_external_include,
4293 )?;
4294 }
4295 Ok(())
4296 }
4297
4298 fn resolve_include_item(
4299 &self,
4300 cloner: &mut clone::Cloner<'_>,
4301 names: &[IncludeName],
4302 get_items: impl Fn(&mut Resolve) -> &mut IndexMap<WorldKey, WorldItem>,
4303 item: (&WorldKey, &WorldItem),
4304 span: Span,
4305 item_type: &str,
4306 is_external_include: bool,
4307 ) -> ResolveResult<()> {
4308 match item.0 {
4309 WorldKey::Name(n) => {
4310 let n = names
4311 .into_iter()
4312 .find_map(|include_name| rename(n, include_name))
4313 .unwrap_or(n.clone());
4314
4315 let mut new_item = item.1.clone();
4321 let key = WorldKey::Name(n.clone());
4322 cloner.world_item(&key, &mut new_item);
4323 match &mut new_item {
4324 WorldItem::Function(f) => f.name = n.clone(),
4325 WorldItem::Type { id, .. } => cloner.resolve.types[*id].name = Some(n.clone()),
4326 WorldItem::Interface { .. } => {}
4327 }
4328
4329 let prev = get_items(cloner.resolve).insert(key, new_item);
4330 if prev.is_some() {
4331 return Err(ResolveError::from(ResolveErrorKind::ItemShadowing {
4332 span,
4333 item_type: item_type.to_owned(),
4334 name: n,
4335 }));
4336 }
4337 }
4338 key @ WorldKey::Interface(_) => {
4339 let prev = get_items(cloner.resolve)
4340 .entry(key.clone())
4341 .or_insert(item.1.clone());
4342 match (&item.1, prev) {
4343 (
4344 WorldItem::Interface {
4345 id: aid,
4346 stability: astability,
4347 span: aspan,
4348 ..
4349 },
4350 WorldItem::Interface {
4351 id: bid,
4352 stability: bstability,
4353 ..
4354 },
4355 ) => {
4356 assert_eq!(*aid, *bid);
4357 merge_include_stability(
4358 astability,
4359 bstability,
4360 is_external_include,
4361 *aspan,
4362 )?;
4363 }
4364 (WorldItem::Interface { .. }, _) => unreachable!(),
4365 (WorldItem::Function(_), _) => unreachable!(),
4366 (WorldItem::Type { .. }, _) => unreachable!(),
4367 }
4368 }
4369 };
4370
4371 Ok(())
4372 }
4373
4374 fn remove_matching_name(&self, item: (&WorldKey, &WorldItem), names: &mut Vec<IncludeName>) {
4375 match item.0 {
4376 WorldKey::Name(n) => {
4377 names.retain(|name| rename(n, name).is_none());
4378 }
4379 _ => {}
4380 }
4381 }
4382
4383 fn type_has_borrow(&mut self, resolve: &Resolve, ty: &Type) -> bool {
4384 let id = match ty {
4385 Type::Id(id) => *id,
4386 _ => return false,
4387 };
4388
4389 if let Some(Some(has_borrow)) = self.type_has_borrow.get(id.index()) {
4390 return *has_borrow;
4391 }
4392
4393 let result = self.typedef_has_borrow(resolve, &resolve.types[id]);
4394 if self.type_has_borrow.len() <= id.index() {
4395 self.type_has_borrow.resize(id.index() + 1, None);
4396 }
4397 self.type_has_borrow[id.index()] = Some(result);
4398 result
4399 }
4400
4401 fn typedef_has_borrow(&mut self, resolve: &Resolve, ty: &TypeDef) -> bool {
4402 match &ty.kind {
4403 TypeDefKind::Type(t) => self.type_has_borrow(resolve, t),
4404 TypeDefKind::Variant(v) => v
4405 .cases
4406 .iter()
4407 .filter_map(|case| case.ty.as_ref())
4408 .any(|ty| self.type_has_borrow(resolve, ty)),
4409 TypeDefKind::Handle(Handle::Borrow(_)) => true,
4410 TypeDefKind::Handle(Handle::Own(_)) => false,
4411 TypeDefKind::Resource => false,
4412 TypeDefKind::Record(r) => r
4413 .fields
4414 .iter()
4415 .any(|case| self.type_has_borrow(resolve, &case.ty)),
4416 TypeDefKind::Flags(_) => false,
4417 TypeDefKind::Tuple(t) => t.types.iter().any(|t| self.type_has_borrow(resolve, t)),
4418 TypeDefKind::Enum(_) => false,
4419 TypeDefKind::List(ty)
4420 | TypeDefKind::FixedLengthList(ty, ..)
4421 | TypeDefKind::Future(Some(ty))
4422 | TypeDefKind::Stream(Some(ty))
4423 | TypeDefKind::Option(ty) => self.type_has_borrow(resolve, ty),
4424 TypeDefKind::Map(k, v) => {
4425 self.type_has_borrow(resolve, k) || self.type_has_borrow(resolve, v)
4426 }
4427 TypeDefKind::Result(r) => [&r.ok, &r.err]
4428 .iter()
4429 .filter_map(|t| t.as_ref())
4430 .any(|t| self.type_has_borrow(resolve, t)),
4431 TypeDefKind::Future(None) | TypeDefKind::Stream(None) => false,
4432 TypeDefKind::Unknown => unreachable!(),
4433 }
4434 }
4435}
4436
4437struct MergeMap<'a> {
4438 package_map: HashMap<PackageId, PackageId>,
4441
4442 interface_map: HashMap<InterfaceId, InterfaceId>,
4445
4446 type_map: HashMap<TypeId, TypeId>,
4449
4450 world_map: HashMap<WorldId, WorldId>,
4453
4454 interfaces_to_add: Vec<(String, PackageId, InterfaceId)>,
4462 worlds_to_add: Vec<(String, PackageId, WorldId)>,
4463
4464 from: &'a Resolve,
4466
4467 into: &'a Resolve,
4469}
4470
4471impl<'a> MergeMap<'a> {
4472 fn new(from: &'a Resolve, into: &'a Resolve) -> MergeMap<'a> {
4473 MergeMap {
4474 package_map: Default::default(),
4475 interface_map: Default::default(),
4476 type_map: Default::default(),
4477 world_map: Default::default(),
4478 interfaces_to_add: Default::default(),
4479 worlds_to_add: Default::default(),
4480 from,
4481 into,
4482 }
4483 }
4484
4485 fn build(&mut self) -> anyhow::Result<()> {
4486 for from_id in self.from.topological_packages() {
4487 let from = &self.from.packages[from_id];
4488 let into_id = match self.into.package_names.get(&from.name) {
4489 Some(id) => *id,
4490
4491 None => {
4494 log::trace!("adding unique package {}", from.name);
4495 continue;
4496 }
4497 };
4498 log::trace!("merging duplicate package {}", from.name);
4499
4500 self.build_package(from_id, into_id).with_context(|| {
4501 format!("failed to merge package `{}` into existing copy", from.name)
4502 })?;
4503 }
4504
4505 Ok(())
4506 }
4507
4508 fn build_package(&mut self, from_id: PackageId, into_id: PackageId) -> anyhow::Result<()> {
4509 let prev = self.package_map.insert(from_id, into_id);
4510 assert!(prev.is_none());
4511
4512 let from = &self.from.packages[from_id];
4513 let into = &self.into.packages[into_id];
4514
4515 for (name, from_interface_id) in from.interfaces.iter() {
4519 let into_interface_id = match into.interfaces.get(name) {
4520 Some(id) => *id,
4521 None => {
4522 log::trace!("adding unique interface {name}");
4523 self.interfaces_to_add
4524 .push((name.clone(), into_id, *from_interface_id));
4525 continue;
4526 }
4527 };
4528
4529 log::trace!("merging duplicate interfaces {name}");
4530 self.build_interface(*from_interface_id, into_interface_id)
4531 .with_context(|| format!("failed to merge interface `{name}`"))?;
4532 }
4533
4534 for (name, from_world_id) in from.worlds.iter() {
4535 let into_world_id = match into.worlds.get(name) {
4536 Some(id) => *id,
4537 None => {
4538 log::trace!("adding unique world {name}");
4539 self.worlds_to_add
4540 .push((name.clone(), into_id, *from_world_id));
4541 continue;
4542 }
4543 };
4544
4545 log::trace!("merging duplicate worlds {name}");
4546 self.build_world(*from_world_id, into_world_id)
4547 .with_context(|| format!("failed to merge world `{name}`"))?;
4548 }
4549
4550 Ok(())
4551 }
4552
4553 fn build_interface(
4554 &mut self,
4555 from_id: InterfaceId,
4556 into_id: InterfaceId,
4557 ) -> anyhow::Result<()> {
4558 let prev = self.interface_map.insert(from_id, into_id);
4559 assert!(prev.is_none());
4560
4561 let from_interface = &self.from.interfaces[from_id];
4562 let into_interface = &self.into.interfaces[into_id];
4563
4564 for (name, from_type_id) in from_interface.types.iter() {
4572 let into_type_id = match into_interface.types.get(name) {
4573 Some(id) => *id,
4574 None => continue,
4577 };
4578 let prev = self.type_map.insert(*from_type_id, into_type_id);
4579 assert!(prev.is_none());
4580
4581 self.build_type_id(*from_type_id, into_type_id)
4582 .with_context(|| format!("mismatch in type `{name}`"))?;
4583 }
4584
4585 for (name, from_func) in from_interface.functions.iter() {
4586 let into_func = match into_interface.functions.get(name) {
4587 Some(func) => func,
4588 None => continue,
4591 };
4592 self.build_function(from_func, into_func)
4593 .with_context(|| format!("mismatch in function `{name}`"))?;
4594 }
4595
4596 Ok(())
4597 }
4598
4599 fn build_type_id(&mut self, from_id: TypeId, into_id: TypeId) -> anyhow::Result<()> {
4600 let _ = from_id;
4604 let _ = into_id;
4605 Ok(())
4606 }
4607
4608 fn build_type(&mut self, from_ty: &Type, into_ty: &Type) -> anyhow::Result<()> {
4609 match (from_ty, into_ty) {
4610 (Type::Id(from), Type::Id(into)) => {
4611 self.build_type_id(*from, *into)?;
4612 }
4613 (from, into) if from != into => bail!("different kinds of types"),
4614 _ => {}
4615 }
4616 Ok(())
4617 }
4618
4619 fn build_function(&mut self, from_func: &Function, into_func: &Function) -> anyhow::Result<()> {
4620 if from_func.name != into_func.name {
4621 bail!(
4622 "different function names `{}` and `{}`",
4623 from_func.name,
4624 into_func.name
4625 );
4626 }
4627 match (&from_func.kind, &into_func.kind) {
4628 (FunctionKind::Freestanding, FunctionKind::Freestanding) => {}
4629 (FunctionKind::AsyncFreestanding, FunctionKind::AsyncFreestanding) => {}
4630
4631 (FunctionKind::Method(from), FunctionKind::Method(into))
4632 | (FunctionKind::Static(from), FunctionKind::Static(into))
4633 | (FunctionKind::AsyncMethod(from), FunctionKind::AsyncMethod(into))
4634 | (FunctionKind::AsyncStatic(from), FunctionKind::AsyncStatic(into))
4635 | (FunctionKind::Constructor(from), FunctionKind::Constructor(into)) => {
4636 self.build_type_id(*from, *into)
4637 .context("different function kind types")?;
4638 }
4639
4640 (FunctionKind::Method(_), _)
4641 | (FunctionKind::Constructor(_), _)
4642 | (FunctionKind::Static(_), _)
4643 | (FunctionKind::Freestanding, _)
4644 | (FunctionKind::AsyncFreestanding, _)
4645 | (FunctionKind::AsyncMethod(_), _)
4646 | (FunctionKind::AsyncStatic(_), _) => {
4647 bail!("different function kind types")
4648 }
4649 }
4650
4651 if from_func.params.len() != into_func.params.len() {
4652 bail!("different number of function parameters");
4653 }
4654 for (from_param, into_param) in from_func.params.iter().zip(&into_func.params) {
4655 if from_param.name != into_param.name {
4656 bail!(
4657 "different function parameter names: {} != {}",
4658 from_param.name,
4659 into_param.name
4660 );
4661 }
4662 self.build_type(&from_param.ty, &into_param.ty)
4663 .with_context(|| {
4664 format!(
4665 "different function parameter types for `{}`",
4666 from_param.name
4667 )
4668 })?;
4669 }
4670 match (&from_func.result, &into_func.result) {
4671 (Some(from_ty), Some(into_ty)) => {
4672 self.build_type(from_ty, into_ty)
4673 .context("different function result types")?;
4674 }
4675 (None, None) => {}
4676 (Some(_), None) | (None, Some(_)) => bail!("different number of function results"),
4677 }
4678 Ok(())
4679 }
4680
4681 fn build_world(&mut self, from_id: WorldId, into_id: WorldId) -> anyhow::Result<()> {
4682 let prev = self.world_map.insert(from_id, into_id);
4683 assert!(prev.is_none());
4684
4685 let from_world = &self.from.worlds[from_id];
4686 let into_world = &self.into.worlds[into_id];
4687
4688 if from_world.imports.len() != into_world.imports.len() {
4697 bail!("world contains different number of imports than expected");
4698 }
4699 if from_world.exports.len() != into_world.exports.len() {
4700 bail!("world contains different number of exports than expected");
4701 }
4702
4703 for (from_name, from) in from_world.imports.iter() {
4704 let into_name = MergeMap::map_name(from_name, &self.interface_map);
4705 let name_str = self.from.name_world_key(from_name);
4706 let into = into_world
4707 .imports
4708 .get(&into_name)
4709 .ok_or_else(|| anyhow!("import `{name_str}` not found in target world"))?;
4710 self.match_world_item(from, into)
4711 .with_context(|| format!("import `{name_str}` didn't match target world"))?;
4712 }
4713
4714 for (from_name, from) in from_world.exports.iter() {
4715 let into_name = MergeMap::map_name(from_name, &self.interface_map);
4716 let name_str = self.from.name_world_key(from_name);
4717 let into = into_world
4718 .exports
4719 .get(&into_name)
4720 .ok_or_else(|| anyhow!("export `{name_str}` not found in target world"))?;
4721 self.match_world_item(from, into)
4722 .with_context(|| format!("export `{name_str}` didn't match target world"))?;
4723 }
4724
4725 Ok(())
4726 }
4727
4728 fn map_name(
4729 from_name: &WorldKey,
4730 interface_map: &HashMap<InterfaceId, InterfaceId>,
4731 ) -> WorldKey {
4732 match from_name {
4733 WorldKey::Name(s) => WorldKey::Name(s.clone()),
4734 WorldKey::Interface(id) => {
4735 WorldKey::Interface(interface_map.get(id).copied().unwrap_or(*id))
4736 }
4737 }
4738 }
4739
4740 fn match_world_item(&mut self, from: &WorldItem, into: &WorldItem) -> anyhow::Result<()> {
4741 match (from, into) {
4742 (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
4743 match (
4744 &self.from.interfaces[*from].name,
4745 &self.into.interfaces[*into].name,
4746 ) {
4747 (None, None) => self.build_interface(*from, *into)?,
4751
4752 _ => {
4757 if self.interface_map.get(from) != Some(into) {
4758 bail!("interfaces are not the same");
4759 }
4760 }
4761 }
4762 }
4763 (WorldItem::Function(from), WorldItem::Function(into)) => {
4764 let _ = (from, into);
4765 }
4768 (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
4769 let prev = self.type_map.insert(*from, *into);
4772 assert!(prev.is_none());
4773 }
4774
4775 (WorldItem::Interface { .. }, _)
4776 | (WorldItem::Function(_), _)
4777 | (WorldItem::Type { .. }, _) => {
4778 bail!("world items do not have the same type")
4779 }
4780 }
4781 Ok(())
4782 }
4783}
4784
4785fn update_stability(from: &Stability, into: &mut Stability, span: Span) -> ResolveResult<()> {
4791 if from == into || from.is_unknown() {
4794 return Ok(());
4795 }
4796 if into.is_unknown() {
4799 *into = from.clone();
4800 return Ok(());
4801 }
4802
4803 Err(ResolveError::from(ResolveErrorKind::StabilityMismatch {
4806 span,
4807 from: from.clone(),
4808 into: into.clone(),
4809 }))
4810}
4811
4812fn merge_include_stability(
4813 from: &Stability,
4814 into: &mut Stability,
4815 is_external_include: bool,
4816 span: Span,
4817) -> ResolveResult<()> {
4818 if is_external_include && from.is_stable() {
4819 log::trace!("dropped stability from external package");
4820 *into = Stability::Unknown;
4821 return Ok(());
4822 }
4823
4824 update_stability(from, into, span)
4825}
4826
4827#[cfg(test)]
4828mod tests {
4829 use crate::alloc::format;
4830 use crate::alloc::string::{String, ToString};
4831 use crate::alloc::vec::Vec;
4832 use crate::{Resolve, SourceMap, WorldItem, WorldKey};
4833 use anyhow::Result;
4834
4835 #[test]
4836 fn select_world() -> Result<()> {
4837 let mut resolve = Resolve::default();
4838 resolve.push_str(
4839 "test.wit",
4840 r#"
4841 package foo:bar@0.1.0;
4842
4843 world foo {}
4844 "#,
4845 )?;
4846 resolve.push_str(
4847 "test.wit",
4848 r#"
4849 package foo:baz@0.1.0;
4850
4851 world foo {}
4852 "#,
4853 )?;
4854 resolve.push_str(
4855 "test.wit",
4856 r#"
4857 package foo:baz@0.2.0;
4858
4859 world foo {}
4860 "#,
4861 )?;
4862
4863 let dummy = resolve.push_str(
4864 "test.wit",
4865 r#"
4866 package foo:dummy;
4867
4868 world foo {}
4869 "#,
4870 )?;
4871
4872 assert!(resolve.select_world(&[dummy], None).is_ok());
4873 assert!(resolve.select_world(&[dummy], Some("xx")).is_err());
4874 assert!(resolve.select_world(&[dummy], Some("")).is_err());
4875 assert!(resolve.select_world(&[dummy], Some("foo:bar/foo")).is_ok());
4876 assert!(
4877 resolve
4878 .select_world(&[dummy], Some("foo:bar/foo@0.1.0"))
4879 .is_ok()
4880 );
4881 assert!(resolve.select_world(&[dummy], Some("foo:baz/foo")).is_err());
4882 assert!(
4883 resolve
4884 .select_world(&[dummy], Some("foo:baz/foo@0.1.0"))
4885 .is_ok()
4886 );
4887 assert!(
4888 resolve
4889 .select_world(&[dummy], Some("foo:baz/foo@0.2.0"))
4890 .is_ok()
4891 );
4892 Ok(())
4893 }
4894
4895 #[test]
4896 fn wasm_import_name_future_and_stream_intrinsics() -> Result<()> {
4897 use crate::{FutureIntrinsic, LiftLowerAbi, ManglingAndAbi, StreamIntrinsic, WasmImport};
4898
4899 let mut resolve = Resolve::default();
4900 let pkg = resolve.push_str(
4901 "test.wit",
4902 r#"
4903 package foo:bar;
4904
4905 interface iface {
4906 iface-func: func(x: future<u32>) -> stream<u32>;
4907 }
4908
4909 world w {
4910 import import-func: func(x: future<future<u32>>, y: u32) -> stream<string>;
4911 export export-func: func(x: future, y: stream);
4912 import iface;
4913 export iface;
4914 }
4915 "#,
4916 )?;
4917 let world = resolve.packages[pkg].worlds["w"];
4918 let world = &resolve.worlds[world];
4919 let mangling = ManglingAndAbi::Legacy(LiftLowerAbi::AsyncStackful);
4920
4921 let WorldItem::Function(import_func) =
4922 &world.imports[&WorldKey::Name("import-func".to_string())]
4923 else {
4924 panic!("expected `import-func` to be a top-level world import");
4925 };
4926 let WorldItem::Function(export_func) =
4927 &world.exports[&WorldKey::Name("export-func".to_string())]
4928 else {
4929 panic!("expected `export-func` to be a top-level world export");
4930 };
4931 let import_types = import_func.find_futures_and_streams(&resolve);
4932 assert_eq!(import_types.len(), 3);
4933
4934 let (interface_key, interface_func) = world
4935 .imports
4936 .iter()
4937 .find_map(|(key, item)| match item {
4938 WorldItem::Interface { id, .. } => Some((
4939 key.clone(),
4940 &resolve.interfaces[*id].functions["iface-func"],
4941 )),
4942 _ => None,
4943 })
4944 .expect("expected interface import");
4945 let interface_types = interface_func.find_futures_and_streams(&resolve);
4946 assert_eq!(interface_types.len(), 2);
4947
4948 let (module, name) = resolve.wasm_import_name(
4949 mangling,
4950 WasmImport::FutureIntrinsic {
4951 interface: None,
4952 func: import_func,
4953 ty: Some(import_types[0]),
4954 intrinsic: FutureIntrinsic::New,
4955 exported: false,
4956 async_: false,
4957 },
4958 );
4959 assert_eq!(module, "$root");
4960 assert_eq!(name, "[future-new-0]import-func");
4961
4962 let (module, name) = resolve.wasm_import_name(
4963 mangling,
4964 WasmImport::FutureIntrinsic {
4965 interface: None,
4966 func: import_func,
4967 ty: Some(import_types[1]),
4968 intrinsic: FutureIntrinsic::Read,
4969 exported: false,
4970 async_: true,
4971 },
4972 );
4973 assert_eq!(module, "$root");
4974 assert_eq!(name, "[async-lower][future-read-1]import-func");
4975
4976 let (module, name) = resolve.wasm_import_name(
4977 mangling,
4978 WasmImport::StreamIntrinsic {
4979 interface: None,
4980 func: import_func,
4981 ty: Some(import_types[2]),
4982 intrinsic: StreamIntrinsic::CancelRead,
4983 exported: false,
4984 async_: true,
4985 },
4986 );
4987 assert_eq!(module, "$root");
4988 assert_eq!(name, "[async-lower][stream-cancel-read-2]import-func");
4989
4990 let (module, name) = resolve.wasm_import_name(
4991 mangling,
4992 WasmImport::FutureIntrinsic {
4993 interface: None,
4994 func: export_func,
4995 ty: None,
4996 intrinsic: FutureIntrinsic::DropReadable,
4997 exported: true,
4998 async_: false,
4999 },
5000 );
5001 assert_eq!(module, "[export]$root");
5002 assert_eq!(name, "[future-drop-readable-unit]export-func");
5003
5004 let (module, name) = resolve.wasm_import_name(
5005 mangling,
5006 WasmImport::StreamIntrinsic {
5007 interface: None,
5008 func: export_func,
5009 ty: None,
5010 intrinsic: StreamIntrinsic::Write,
5011 exported: true,
5012 async_: true,
5013 },
5014 );
5015 assert_eq!(module, "[export]$root");
5016 assert_eq!(name, "[async-lower][stream-write-unit]export-func");
5017
5018 let (module, name) = resolve.wasm_import_name(
5019 mangling,
5020 WasmImport::StreamIntrinsic {
5021 interface: Some(&interface_key),
5022 func: interface_func,
5023 ty: Some(interface_types[1]),
5024 intrinsic: StreamIntrinsic::Read,
5025 exported: true,
5026 async_: false,
5027 },
5028 );
5029 assert_eq!(
5030 module,
5031 format!("[export]{}", resolve.name_world_key(&interface_key))
5032 );
5033 assert_eq!(name, "[stream-read-1]iface-func");
5034
5035 Ok(())
5036 }
5037
5038 #[test]
5041 fn select_world_multiple_packages() -> Result<()> {
5042 use wit_parser::Resolve;
5043
5044 let mut resolve = Resolve::default();
5045
5046 let stuff = resolve.push_str(
5048 "./my-test.wit",
5049 r#"
5050 package test:stuff;
5051
5052 world foo {
5053 // ...
5054 }
5055 "#,
5056 )?;
5057 assert!(resolve.select_world(&[stuff], None).is_ok());
5058 assert!(resolve.select_world(&[stuff], Some("foo")).is_ok());
5059
5060 let empty = resolve.push_str(
5063 "./my-test.wit",
5064 r#"
5065 package test:empty;
5066 "#,
5067 )?;
5068 assert!(resolve.select_world(&[stuff, empty], None).is_err());
5069 assert!(resolve.select_world(&[stuff, empty], Some("foo")).is_err());
5070 assert!(resolve.select_world(&[empty], None).is_err());
5071 assert!(resolve.select_world(&[empty], Some("foo")).is_err());
5072
5073 Ok(())
5074 }
5075
5076 #[test]
5078 fn select_world_versions() -> Result<()> {
5079 use wit_parser::Resolve;
5080
5081 let mut resolve = Resolve::default();
5082
5083 let _id = resolve.push_str(
5084 "./my-test.wit",
5085 r#"
5086 package example:distraction;
5087 "#,
5088 )?;
5089
5090 let versions_1 = resolve.push_str(
5093 "./my-test.wit",
5094 r#"
5095 package example:versions@1.0.0;
5096
5097 world foo { /* ... */ }
5098 "#,
5099 )?;
5100 assert!(resolve.select_world(&[versions_1], Some("foo")).is_ok());
5101 assert!(
5102 resolve
5103 .select_world(&[versions_1], Some("foo@1.0.0"))
5104 .is_err()
5105 );
5106 assert!(
5107 resolve
5108 .select_world(&[versions_1], Some("example:versions/foo"))
5109 .is_ok()
5110 );
5111 assert!(
5112 resolve
5113 .select_world(&[versions_1], Some("example:versions/foo@1.0.0"))
5114 .is_ok()
5115 );
5116
5117 let versions_2 = resolve.push_str(
5120 "./my-test.wit",
5121 r#"
5122 package example:versions@2.0.0;
5123
5124 world foo { /* ... */ }
5125 "#,
5126 )?;
5127 assert!(
5128 resolve
5129 .select_world(&[versions_1, versions_2], Some("foo"))
5130 .is_err()
5131 );
5132 assert!(
5133 resolve
5134 .select_world(&[versions_1, versions_2], Some("foo@1.0.0"))
5135 .is_err()
5136 );
5137 assert!(
5138 resolve
5139 .select_world(&[versions_1, versions_2], Some("foo@2.0.0"))
5140 .is_err()
5141 );
5142 assert!(
5143 resolve
5144 .select_world(&[versions_1, versions_2], Some("example:versions/foo"))
5145 .is_err()
5146 );
5147 assert!(
5148 resolve
5149 .select_world(
5150 &[versions_1, versions_2],
5151 Some("example:versions/foo@1.0.0")
5152 )
5153 .is_ok()
5154 );
5155 assert!(
5156 resolve
5157 .select_world(
5158 &[versions_1, versions_2],
5159 Some("example:versions/foo@2.0.0")
5160 )
5161 .is_ok()
5162 );
5163
5164 Ok(())
5165 }
5166
5167 #[test]
5169 fn select_world_override_qualification() -> Result<()> {
5170 use wit_parser::Resolve;
5171
5172 let mut resolve = Resolve::default();
5173
5174 let other = resolve.push_str(
5175 "./my-test.wit",
5176 r#"
5177 package example:other;
5178
5179 world foo { }
5180 "#,
5181 )?;
5182
5183 let fq = resolve.push_str(
5185 "./my-test.wit",
5186 r#"
5187 package example:fq;
5188
5189 world bar { }
5190 "#,
5191 )?;
5192 assert!(resolve.select_world(&[other, fq], Some("foo")).is_err());
5193 assert!(resolve.select_world(&[other, fq], Some("bar")).is_err());
5194 assert!(
5195 resolve
5196 .select_world(&[other, fq], Some("example:other/foo"))
5197 .is_ok()
5198 );
5199 assert!(
5200 resolve
5201 .select_world(&[other, fq], Some("example:fq/bar"))
5202 .is_ok()
5203 );
5204 assert!(
5205 resolve
5206 .select_world(&[other, fq], Some("example:other/bar"))
5207 .is_err()
5208 );
5209 assert!(
5210 resolve
5211 .select_world(&[other, fq], Some("example:fq/foo"))
5212 .is_err()
5213 );
5214
5215 Ok(())
5216 }
5217
5218 #[test]
5220 fn select_world_fully_qualified() -> Result<()> {
5221 use wit_parser::Resolve;
5222
5223 let mut resolve = Resolve::default();
5224
5225 let distraction = resolve.push_str(
5226 "./my-test.wit",
5227 r#"
5228 package example:distraction;
5229 "#,
5230 )?;
5231
5232 let multiworld = resolve.push_str(
5235 "./my-test.wit",
5236 r#"
5237 package example:multiworld;
5238
5239 world foo { /* ... */ }
5240
5241 world bar { /* ... */ }
5242 "#,
5243 )?;
5244 assert!(
5245 resolve
5246 .select_world(&[distraction, multiworld], None)
5247 .is_err()
5248 );
5249 assert!(
5250 resolve
5251 .select_world(&[distraction, multiworld], Some("foo"))
5252 .is_err()
5253 );
5254 assert!(
5255 resolve
5256 .select_world(&[distraction, multiworld], Some("example:multiworld/foo"))
5257 .is_ok()
5258 );
5259 assert!(
5260 resolve
5261 .select_world(&[distraction, multiworld], Some("bar"))
5262 .is_err()
5263 );
5264 assert!(
5265 resolve
5266 .select_world(&[distraction, multiworld], Some("example:multiworld/bar"))
5267 .is_ok()
5268 );
5269
5270 Ok(())
5271 }
5272
5273 #[test]
5275 fn select_world_packages() -> Result<()> {
5276 use wit_parser::Resolve;
5277
5278 let mut resolve = Resolve::default();
5279
5280 let wit1 = resolve.push_str(
5283 "./my-test.wit",
5284 r#"
5285 package example:wit1;
5286
5287 world foo {
5288 // ...
5289 }
5290 "#,
5291 )?;
5292 assert!(resolve.select_world(&[wit1], None).is_ok());
5293 assert!(resolve.select_world(&[wit1], Some("foo")).is_ok());
5294 assert!(
5295 resolve
5296 .select_world(&[wit1], Some("example:wit1/foo"))
5297 .is_ok()
5298 );
5299 assert!(resolve.select_world(&[wit1], Some("bar")).is_err());
5300 assert!(
5301 resolve
5302 .select_world(&[wit1], Some("example:wit2/foo"))
5303 .is_err()
5304 );
5305
5306 let wit2 = resolve.push_str(
5309 "./my-test.wit",
5310 r#"
5311 package example:wit2;
5312
5313 world foo { /* ... */ }
5314 "#,
5315 )?;
5316 assert!(resolve.select_world(&[wit1, wit2], None).is_err());
5317 assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
5318 assert!(
5319 resolve
5320 .select_world(&[wit1, wit2], Some("example:wit1/foo"))
5321 .is_ok()
5322 );
5323 assert!(resolve.select_world(&[wit2], None).is_ok());
5324 assert!(resolve.select_world(&[wit2], Some("foo")).is_ok());
5325 assert!(
5326 resolve
5327 .select_world(&[wit2], Some("example:wit1/foo"))
5328 .is_ok()
5329 );
5330 assert!(resolve.select_world(&[wit1, wit2], Some("bar")).is_err());
5331 assert!(
5332 resolve
5333 .select_world(&[wit1, wit2], Some("example:wit2/foo"))
5334 .is_ok()
5335 );
5336 assert!(resolve.select_world(&[wit2], Some("bar")).is_err());
5337 assert!(
5338 resolve
5339 .select_world(&[wit2], Some("example:wit2/foo"))
5340 .is_ok()
5341 );
5342
5343 Ok(())
5344 }
5345
5346 #[test]
5347 fn span_preservation() -> Result<()> {
5348 let mut resolve = Resolve::default();
5349 let pkg = resolve.push_str(
5350 "test.wit",
5351 r#"
5352 package foo:bar;
5353
5354 interface my-iface {
5355 type my-type = u32;
5356 my-func: func();
5357 }
5358
5359 world my-world {
5360 export my-export: func();
5361 }
5362 "#,
5363 )?;
5364
5365 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5366 assert!(resolve.interfaces[iface_id].span.is_known());
5367
5368 let type_id = resolve.interfaces[iface_id].types["my-type"];
5369 assert!(resolve.types[type_id].span.is_known());
5370
5371 assert!(
5372 resolve.interfaces[iface_id].functions["my-func"]
5373 .span
5374 .is_known()
5375 );
5376
5377 let world_id = resolve.packages[pkg].worlds["my-world"];
5378 assert!(resolve.worlds[world_id].span.is_known());
5379
5380 let WorldItem::Function(f) =
5381 &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5382 else {
5383 panic!("expected function");
5384 };
5385 assert!(f.span.is_known());
5386
5387 Ok(())
5388 }
5389
5390 #[test]
5391 fn span_preservation_through_merge() -> Result<()> {
5392 let mut resolve1 = Resolve::default();
5393 resolve1.push_str(
5394 "test1.wit",
5395 r#"
5396 package foo:bar;
5397
5398 interface iface1 {
5399 type type1 = u32;
5400 func1: func();
5401 }
5402 "#,
5403 )?;
5404
5405 let mut resolve2 = Resolve::default();
5406 let pkg2 = resolve2.push_str(
5407 "test2.wit",
5408 r#"
5409 package foo:baz;
5410
5411 interface iface2 {
5412 type type2 = string;
5413 func2: func();
5414 }
5415 "#,
5416 )?;
5417
5418 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5419 let remap = resolve1.merge(resolve2)?;
5420 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5421
5422 assert!(resolve1.interfaces[iface2_id].span.is_known());
5423
5424 let type2_id = resolve1.interfaces[iface2_id].types["type2"];
5425 assert!(resolve1.types[type2_id].span.is_known());
5426
5427 assert!(
5428 resolve1.interfaces[iface2_id].functions["func2"]
5429 .span
5430 .is_known()
5431 );
5432
5433 Ok(())
5434 }
5435
5436 #[test]
5437 fn span_preservation_through_include() -> Result<()> {
5438 let mut resolve = Resolve::default();
5439 let pkg = resolve.push_str(
5440 "test.wit",
5441 r#"
5442 package foo:bar;
5443
5444 world base {
5445 export my-func: func();
5446 }
5447
5448 world extended {
5449 include base;
5450 }
5451 "#,
5452 )?;
5453
5454 let base_id = resolve.packages[pkg].worlds["base"];
5455 let extended_id = resolve.packages[pkg].worlds["extended"];
5456
5457 let WorldItem::Function(base_func) =
5458 &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5459 else {
5460 panic!("expected function");
5461 };
5462 assert!(base_func.span.is_known());
5463
5464 let WorldItem::Function(extended_func) =
5465 &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5466 else {
5467 panic!("expected function");
5468 };
5469 assert!(extended_func.span.is_known());
5470
5471 Ok(())
5472 }
5473
5474 #[test]
5475 fn span_preservation_through_include_with_rename() -> Result<()> {
5476 let mut resolve = Resolve::default();
5477 let pkg = resolve.push_str(
5478 "test.wit",
5479 r#"
5480 package foo:bar;
5481
5482 world base {
5483 export original-name: func();
5484 }
5485
5486 world extended {
5487 include base with { original-name as renamed-func }
5488 }
5489 "#,
5490 )?;
5491
5492 let extended_id = resolve.packages[pkg].worlds["extended"];
5493
5494 let WorldItem::Function(f) =
5495 &resolve.worlds[extended_id].exports[&WorldKey::Name("renamed-func".to_string())]
5496 else {
5497 panic!("expected function");
5498 };
5499 assert!(f.span.is_known());
5500
5501 assert!(
5502 !resolve.worlds[extended_id]
5503 .exports
5504 .contains_key(&WorldKey::Name("original-name".to_string()))
5505 );
5506
5507 Ok(())
5508 }
5509
5510 #[test]
5512 fn span_preservation_through_include_reverse_order() -> Result<()> {
5513 let mut resolve = Resolve::default();
5514 let pkg = resolve.push_str(
5515 "test.wit",
5516 r#"
5517 package foo:bar;
5518
5519 world extended {
5520 include base;
5521 }
5522
5523 world base {
5524 export my-func: func();
5525 }
5526 "#,
5527 )?;
5528
5529 let base_id = resolve.packages[pkg].worlds["base"];
5530 let extended_id = resolve.packages[pkg].worlds["extended"];
5531
5532 let WorldItem::Function(base_func) =
5533 &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5534 else {
5535 panic!("expected function");
5536 };
5537 assert!(base_func.span.is_known());
5538
5539 let WorldItem::Function(extended_func) =
5540 &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5541 else {
5542 panic!("expected function");
5543 };
5544 assert!(extended_func.span.is_known());
5545
5546 Ok(())
5547 }
5548
5549 #[test]
5550 fn span_line_numbers() -> Result<()> {
5551 let mut resolve = Resolve::default();
5552 let pkg = resolve.push_source(
5553 "test.wit",
5554 "package foo:bar;
5555
5556interface my-iface {
5557 type my-type = u32;
5558 my-func: func();
5559}
5560
5561world my-world {
5562 export my-export: func();
5563}
5564",
5565 )?;
5566
5567 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5568 let iface_span = resolve.interfaces[iface_id].span;
5569 let iface_loc = resolve.render_location(iface_span);
5570 assert!(
5571 iface_loc.contains(":3:"),
5572 "interface location was {iface_loc}"
5573 );
5574
5575 let type_id = resolve.interfaces[iface_id].types["my-type"];
5576 let type_span = resolve.types[type_id].span;
5577 let type_loc = resolve.render_location(type_span);
5578 assert!(type_loc.contains(":4:"), "type location was {type_loc}");
5579
5580 let func_span = resolve.interfaces[iface_id].functions["my-func"].span;
5581 let func_loc = resolve.render_location(func_span);
5582 assert!(func_loc.contains(":5:"), "function location was {func_loc}");
5583
5584 let world_id = resolve.packages[pkg].worlds["my-world"];
5585 let world_span = resolve.worlds[world_id].span;
5586 let world_loc = resolve.render_location(world_span);
5587 assert!(world_loc.contains(":8:"), "world location was {world_loc}");
5588
5589 let WorldItem::Function(export_func) =
5590 &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5591 else {
5592 panic!("expected function");
5593 };
5594 let export_loc = resolve.render_location(export_func.span);
5595 assert!(
5596 export_loc.contains(":9:"),
5597 "export location was {export_loc}"
5598 );
5599
5600 Ok(())
5601 }
5602
5603 #[test]
5604 fn span_line_numbers_through_merge() -> Result<()> {
5605 let mut resolve1 = Resolve::default();
5606 resolve1.push_source(
5607 "first.wit",
5608 "package foo:first;
5609
5610interface iface1 {
5611 func1: func();
5612}
5613",
5614 )?;
5615
5616 let mut resolve2 = Resolve::default();
5617 let pkg2 = resolve2.push_source(
5618 "second.wit",
5619 "package foo:second;
5620
5621interface iface2 {
5622 func2: func();
5623}
5624",
5625 )?;
5626
5627 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5628 let remap = resolve1.merge(resolve2)?;
5629 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5630
5631 let iface2_span = resolve1.interfaces[iface2_id].span;
5632 let iface2_loc = resolve1.render_location(iface2_span);
5633 assert!(
5634 iface2_loc.contains("second.wit"),
5635 "should reference second.wit, got {iface2_loc}"
5636 );
5637 assert!(
5638 iface2_loc.contains(":3:"),
5639 "interface should be on line 3, got {iface2_loc}"
5640 );
5641
5642 let func2_span = resolve1.interfaces[iface2_id].functions["func2"].span;
5643 let func2_loc = resolve1.render_location(func2_span);
5644 assert!(
5645 func2_loc.contains("second.wit"),
5646 "should reference second.wit, got {func2_loc}"
5647 );
5648 assert!(
5649 func2_loc.contains(":4:"),
5650 "function should be on line 4, got {func2_loc}"
5651 );
5652
5653 Ok(())
5654 }
5655
5656 #[test]
5657 fn span_line_numbers_multiple_sources() -> Result<()> {
5658 let mut resolve = Resolve::default();
5659
5660 let pkg1 = resolve.push_source(
5661 "first.wit",
5662 "package test:first;
5663
5664interface first-iface {
5665 first-func: func();
5666}
5667",
5668 )?;
5669
5670 let pkg2 = resolve.push_source(
5671 "second.wit",
5672 "package test:second;
5673
5674interface second-iface {
5675 second-func: func();
5676}
5677",
5678 )?;
5679
5680 let iface1_id = resolve.packages[pkg1].interfaces["first-iface"];
5681 let iface1_span = resolve.interfaces[iface1_id].span;
5682 let iface1_loc = resolve.render_location(iface1_span);
5683 assert!(
5684 iface1_loc.contains("first.wit"),
5685 "should reference first.wit, got {iface1_loc}"
5686 );
5687 assert!(
5688 iface1_loc.contains(":3:"),
5689 "interface should be on line 3, got {iface1_loc}"
5690 );
5691
5692 let func1_span = resolve.interfaces[iface1_id].functions["first-func"].span;
5693 let func1_loc = resolve.render_location(func1_span);
5694 assert!(
5695 func1_loc.contains("first.wit"),
5696 "should reference first.wit, got {func1_loc}"
5697 );
5698 assert!(
5699 func1_loc.contains(":4:"),
5700 "function should be on line 4, got {func1_loc}"
5701 );
5702
5703 let iface2_id = resolve.packages[pkg2].interfaces["second-iface"];
5704 let iface2_span = resolve.interfaces[iface2_id].span;
5705 let iface2_loc = resolve.render_location(iface2_span);
5706 assert!(
5707 iface2_loc.contains("second.wit"),
5708 "should reference second.wit, got {iface2_loc}"
5709 );
5710 assert!(
5711 iface2_loc.contains(":3:"),
5712 "interface should be on line 3, got {iface2_loc}"
5713 );
5714
5715 let func2_span = resolve.interfaces[iface2_id].functions["second-func"].span;
5716 let func2_loc = resolve.render_location(func2_span);
5717 assert!(
5718 func2_loc.contains("second.wit"),
5719 "should reference second.wit, got {func2_loc}"
5720 );
5721 assert!(
5722 func2_loc.contains(":4:"),
5723 "function should be on line 4, got {func2_loc}"
5724 );
5725
5726 Ok(())
5727 }
5728
5729 #[test]
5730 fn span_preservation_for_fields_and_cases() -> Result<()> {
5731 use crate::TypeDefKind;
5732
5733 let mut resolve = Resolve::default();
5734 let pkg = resolve.push_str(
5735 "test.wit",
5736 r#"
5737 package foo:bar;
5738
5739 interface my-iface {
5740 record my-record {
5741 field1: u32,
5742 field2: string,
5743 }
5744
5745 flags my-flags {
5746 flag1,
5747 flag2,
5748 }
5749
5750 variant my-variant {
5751 case1,
5752 case2(u32),
5753 }
5754
5755 enum my-enum {
5756 val1,
5757 val2,
5758 }
5759 }
5760 "#,
5761 )?;
5762
5763 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5764
5765 let record_id = resolve.interfaces[iface_id].types["my-record"];
5767 let TypeDefKind::Record(record) = &resolve.types[record_id].kind else {
5768 panic!("expected record");
5769 };
5770 assert!(record.fields[0].span.is_known(), "field1 should have span");
5771 assert!(record.fields[1].span.is_known(), "field2 should have span");
5772
5773 let flags_id = resolve.interfaces[iface_id].types["my-flags"];
5775 let TypeDefKind::Flags(flags) = &resolve.types[flags_id].kind else {
5776 panic!("expected flags");
5777 };
5778 assert!(flags.flags[0].span.is_known(), "flag1 should have span");
5779 assert!(flags.flags[1].span.is_known(), "flag2 should have span");
5780
5781 let variant_id = resolve.interfaces[iface_id].types["my-variant"];
5783 let TypeDefKind::Variant(variant) = &resolve.types[variant_id].kind else {
5784 panic!("expected variant");
5785 };
5786 assert!(variant.cases[0].span.is_known(), "case1 should have span");
5787 assert!(variant.cases[1].span.is_known(), "case2 should have span");
5788
5789 let enum_id = resolve.interfaces[iface_id].types["my-enum"];
5791 let TypeDefKind::Enum(e) = &resolve.types[enum_id].kind else {
5792 panic!("expected enum");
5793 };
5794 assert!(e.cases[0].span.is_known(), "val1 should have span");
5795 assert!(e.cases[1].span.is_known(), "val2 should have span");
5796
5797 Ok(())
5798 }
5799
5800 #[test]
5801 fn span_preservation_for_fields_through_merge() -> Result<()> {
5802 use crate::TypeDefKind;
5803
5804 let mut resolve1 = Resolve::default();
5805 resolve1.push_str(
5806 "test1.wit",
5807 r#"
5808 package foo:bar;
5809
5810 interface iface1 {
5811 record rec1 {
5812 f1: u32,
5813 }
5814 }
5815 "#,
5816 )?;
5817
5818 let mut resolve2 = Resolve::default();
5819 let pkg2 = resolve2.push_str(
5820 "test2.wit",
5821 r#"
5822 package foo:baz;
5823
5824 interface iface2 {
5825 record rec2 {
5826 f2: string,
5827 }
5828
5829 variant var2 {
5830 c2,
5831 }
5832 }
5833 "#,
5834 )?;
5835
5836 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5837 let rec2_old_id = resolve2.interfaces[iface2_old_id].types["rec2"];
5838 let var2_old_id = resolve2.interfaces[iface2_old_id].types["var2"];
5839
5840 let remap = resolve1.merge(resolve2)?;
5841
5842 let rec2_id = remap.types[rec2_old_id.index()].unwrap();
5843 let TypeDefKind::Record(record) = &resolve1.types[rec2_id].kind else {
5844 panic!("expected record");
5845 };
5846 assert!(
5847 record.fields[0].span.is_known(),
5848 "field should have span after merge"
5849 );
5850
5851 let var2_id = remap.types[var2_old_id.index()].unwrap();
5852 let TypeDefKind::Variant(variant) = &resolve1.types[var2_id].kind else {
5853 panic!("expected variant");
5854 };
5855 assert!(
5856 variant.cases[0].span.is_known(),
5857 "case should have span after merge"
5858 );
5859
5860 Ok(())
5861 }
5862
5863 #[test]
5864 fn param_spans_point_to_names() -> Result<()> {
5865 let source = "\
5866package foo:bar;
5867
5868interface iface {
5869 my-func: func(a: u32, b: string);
5870}
5871";
5872 let mut resolve = Resolve::default();
5873 let pkg = resolve.push_str("test.wit", source)?;
5874
5875 let iface_id = resolve.packages[pkg].interfaces["iface"];
5876 let func = &resolve.interfaces[iface_id].functions["my-func"];
5877 assert_eq!(func.params.len(), 2);
5878 for param in &func.params {
5879 let start = param.span.start() as usize;
5880 let end = param.span.end() as usize;
5881 let snippet = &source[start..end];
5882 assert_eq!(
5883 snippet, param.name,
5884 "param `{}` span points to {:?}",
5885 param.name, snippet
5886 );
5887 }
5888
5889 Ok(())
5890 }
5891
5892 #[test]
5893 fn push_groups_resolves_dep_before_main() -> Result<()> {
5894 let dep = {
5897 let mut map = SourceMap::default();
5898 map.push_str(
5899 "file:///dep.wit",
5900 "package foo:dep;\ninterface i { type t = u32; }",
5901 );
5902 map.parse().map_err(|(_, e)| e)?
5903 };
5904 let main = {
5905 let mut map = SourceMap::default();
5906 map.push_str(
5907 "file:///main.wit",
5908 "package foo:main;\ninterface j { use foo:dep/i.{t}; type u = t; }",
5909 );
5910 map.parse().map_err(|(_, e)| e)?
5911 };
5912 let mut resolve = Resolve::default();
5913 resolve.push_groups(main, Vec::from([dep]))?;
5914 assert_eq!(resolve.packages.len(), 2);
5915 Ok(())
5916 }
5917
5918 #[test]
5919 fn push_groups_cycle_error_contains_location() {
5920 let a = {
5924 let mut map = SourceMap::default();
5925 map.push_str(
5926 "file:///a.wit",
5927 "package foo:a;\ninterface i { use foo:b/j.{}; }",
5928 );
5929 map.parse().unwrap()
5930 };
5931 let b = {
5932 let mut map = SourceMap::default();
5933 map.push_str(
5934 "file:///b.wit",
5935 "package foo:b;\ninterface j { use foo:a/i.{}; }",
5936 );
5937 map.parse().unwrap()
5938 };
5939 let mut resolve = Resolve::default();
5940 let err = resolve.push_groups(a, Vec::from([b])).unwrap_err();
5941 let msg = err.render(&resolve.source_map);
5942 assert!(
5943 msg.contains("file:///"),
5944 "cycle error should contain a file URI, got: {msg}"
5945 );
5946 }
5947
5948 #[test]
5949 fn param_spans_preserved_through_merge() -> Result<()> {
5950 let mut resolve1 = Resolve::default();
5951 resolve1.push_str(
5952 "test1.wit",
5953 r#"
5954 package foo:bar;
5955
5956 interface iface1 {
5957 f1: func(x: u32);
5958 }
5959 "#,
5960 )?;
5961
5962 let mut resolve2 = Resolve::default();
5963 let pkg2 = resolve2.push_str(
5964 "test2.wit",
5965 r#"
5966 package foo:baz;
5967
5968 interface iface2 {
5969 f2: func(y: string, z: bool);
5970 }
5971 "#,
5972 )?;
5973
5974 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5975
5976 let remap = resolve1.merge(resolve2)?;
5977
5978 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5979 let func = &resolve1.interfaces[iface2_id].functions["f2"];
5980 for param in &func.params {
5981 assert!(
5982 param.span.is_known(),
5983 "param `{}` should have span after merge",
5984 param.name
5985 );
5986 }
5987
5988 Ok(())
5989 }
5990
5991 #[test]
5996 fn exportize_importize_roundtrip() -> Result<()> {
5997 let mut resolve = Resolve::default();
5998 let pkg = resolve.push_str(
5999 "test.wit",
6000 r#"
6001 package foo:bar;
6002
6003 interface types {
6004 type my-type = u32;
6005 }
6006
6007 interface api {
6008 use types.{my-type};
6009 do-something: func(a: my-type) -> my-type;
6010 }
6011
6012 world w {
6013 export api;
6014 }
6015 "#,
6016 )?;
6017 let world_id = resolve.packages[pkg].worlds["w"];
6018
6019 let original_export_keys: Vec<String> = resolve.worlds[world_id]
6021 .exports
6022 .keys()
6023 .map(|k| resolve.name_world_key(k))
6024 .collect();
6025 assert!(!original_export_keys.is_empty());
6026 assert!(resolve.worlds[world_id].imports.iter().all(|(_, item)| {
6027 matches!(item, WorldItem::Interface { .. })
6030 }));
6031
6032 resolve.importize(world_id, Some("w-temp".to_string()))?;
6034 assert!(
6035 resolve.worlds[world_id].exports.is_empty(),
6036 "importize should leave no exports"
6037 );
6038 for key in &original_export_keys {
6040 assert!(
6041 resolve.worlds[world_id]
6042 .imports
6043 .keys()
6044 .any(|k| resolve.name_world_key(k) == *key),
6045 "expected `{key}` to be an import after importize"
6046 );
6047 }
6048
6049 resolve.exportize(world_id, Some("w-final".to_string()), None)?;
6051 assert!(
6052 !resolve.worlds[world_id].exports.is_empty(),
6053 "exportize should produce exports"
6054 );
6055 let final_export_keys: Vec<String> = resolve.worlds[world_id]
6057 .exports
6058 .keys()
6059 .map(|k| resolve.name_world_key(k))
6060 .collect();
6061 for key in &original_export_keys {
6062 assert!(
6063 final_export_keys.contains(key),
6064 "expected `{key}` to be an export after round-trip, got exports: {final_export_keys:?}"
6065 );
6066 }
6067
6068 Ok(())
6069 }
6070}