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 = map
423 .parse()
424 .map_err(|(map, e)| anyhow::anyhow!("{}", e.highlight(&map)))?;
425 Ok(self.push_group(group)?)
426 }
427
428 pub fn render_location(&self, span: Span) -> String {
430 self.source_map.render_location(span)
431 }
432
433 pub fn all_bits_valid(&self, ty: &Type) -> bool {
434 match ty {
435 Type::U8
436 | Type::S8
437 | Type::U16
438 | Type::S16
439 | Type::U32
440 | Type::S32
441 | Type::U64
442 | Type::S64
443 | Type::F32
444 | Type::F64 => true,
445
446 Type::Bool | Type::Char | Type::String | Type::ErrorContext => false,
447
448 Type::Id(id) => match &self.types[*id].kind {
449 TypeDefKind::List(_)
450 | TypeDefKind::Map(_, _)
451 | TypeDefKind::Variant(_)
452 | TypeDefKind::Enum(_)
453 | TypeDefKind::Option(_)
454 | TypeDefKind::Result(_)
455 | TypeDefKind::Future(_)
456 | TypeDefKind::Stream(_) => false,
457 TypeDefKind::Type(t) | TypeDefKind::FixedLengthList(t, ..) => {
458 self.all_bits_valid(t)
459 }
460
461 TypeDefKind::Handle(h) => match h {
462 crate::Handle::Own(_) => true,
463 crate::Handle::Borrow(_) => true,
464 },
465
466 TypeDefKind::Resource => false,
467 TypeDefKind::Record(r) => r.fields.iter().all(|f| self.all_bits_valid(&f.ty)),
468 TypeDefKind::Tuple(t) => t.types.iter().all(|t| self.all_bits_valid(t)),
469
470 TypeDefKind::Flags(_) => false,
474
475 TypeDefKind::Unknown => unreachable!(),
476 },
477 }
478 }
479
480 pub fn merge(&mut self, resolve: Resolve) -> anyhow::Result<Remap> {
492 log::trace!(
493 "merging {} packages into {} packages",
494 resolve.packages.len(),
495 self.packages.len()
496 );
497
498 let mut map = MergeMap::new(&resolve, &self);
499 map.build()?;
500 let MergeMap {
501 package_map,
502 interface_map,
503 type_map,
504 world_map,
505 interfaces_to_add,
506 worlds_to_add,
507 ..
508 } = map;
509
510 let mut remap = Remap::default();
529 let Resolve {
530 types,
531 worlds,
532 interfaces,
533 packages,
534 package_names,
535 features: _,
536 source_map,
537 ..
538 } = resolve;
539
540 let span_offset = self.source_map.append(source_map);
541
542 let mut moved_types = Vec::new();
543 for (id, mut ty) in types {
544 let new_id = match type_map.get(&id).copied() {
545 Some(id) => {
546 update_stability(&ty.stability, &mut self.types[id].stability, ty.span)?;
547 id
548 }
549 None => {
550 log::debug!("moving type {:?}", ty.name);
551 moved_types.push(id);
552 remap.update_typedef(self, &mut ty, Default::default())?;
553 ty.adjust_spans(span_offset);
554 self.types.alloc(ty)
555 }
556 };
557 assert_eq!(remap.types.len(), id.index());
558 remap.types.push(Some(new_id));
559 }
560
561 let mut moved_interfaces = Vec::new();
562 for (id, mut iface) in interfaces {
563 let new_id = match interface_map.get(&id).copied() {
564 Some(into_id) => {
565 update_stability(
566 &iface.stability,
567 &mut self.interfaces[into_id].stability,
568 iface.span,
569 )?;
570
571 for (name, from_type_id) in iface.types.iter() {
577 if self.interfaces[into_id].types.contains_key(name) {
578 continue;
579 }
580 let new_type_id = remap.map_type(*from_type_id, Default::default())?;
581 self.interfaces[into_id]
582 .types
583 .insert(name.clone(), new_type_id);
584 }
585
586 let extra_funcs: Vec<_> = iface
590 .functions
591 .into_iter()
592 .filter(|(name, _)| {
593 !self.interfaces[into_id]
594 .functions
595 .contains_key(name.as_str())
596 })
597 .collect();
598 for (name, mut func) in extra_funcs {
599 remap.update_function(self, &mut func, Default::default())?;
600 func.adjust_spans(span_offset);
601 self.interfaces[into_id].functions.insert(name, func);
602 }
603
604 into_id
605 }
606 None => {
607 log::debug!("moving interface {:?}", iface.name);
608 moved_interfaces.push(id);
609 remap.update_interface(self, &mut iface)?;
610 iface.adjust_spans(span_offset);
611 self.interfaces.alloc(iface)
612 }
613 };
614 assert_eq!(remap.interfaces.len(), id.index());
615 remap.interfaces.push(Some(new_id));
616 }
617
618 let mut moved_worlds = Vec::new();
619 for (id, mut world) in worlds {
620 let new_id = match world_map.get(&id).copied() {
621 Some(world_id) => {
622 update_stability(
623 &world.stability,
624 &mut self.worlds[world_id].stability,
625 world.span,
626 )?;
627 for from_import in world.imports.iter() {
628 Resolve::update_world_imports_stability(
629 from_import,
630 &mut self.worlds[world_id].imports,
631 &interface_map,
632 )?;
633 }
634 for from_export in world.exports.iter() {
635 Resolve::update_world_imports_stability(
636 from_export,
637 &mut self.worlds[world_id].exports,
638 &interface_map,
639 )?;
640 }
641 world_id
642 }
643 None => {
644 log::debug!("moving world {}", world.name);
645 moved_worlds.push(id);
646 let mut update =
647 |map: &mut IndexMap<WorldKey, WorldItem>| -> anyhow::Result<_> {
648 for (mut name, mut item) in mem::take(map) {
649 remap.update_world_key(&mut name, Default::default())?;
650 match &mut item {
651 WorldItem::Function(f) => {
652 remap.update_function(self, f, Default::default())?
653 }
654 WorldItem::Interface { id, .. } => {
655 *id = remap.map_interface(*id, Default::default())?;
656 }
657 WorldItem::Type { id, .. } => {
658 *id = remap.map_type(*id, Default::default())?
659 }
660 }
661 map.insert(name, item);
662 }
663 Ok(())
664 };
665 update(&mut world.imports)?;
666 update(&mut world.exports)?;
667 world.adjust_spans(span_offset);
668 self.worlds.alloc(world)
669 }
670 };
671 assert_eq!(remap.worlds.len(), id.index());
672 remap.worlds.push(Some(new_id));
673 }
674
675 for (id, mut pkg) in packages {
676 let new_id = match package_map.get(&id).copied() {
677 Some(id) => id,
678 None => {
679 for (_, id) in pkg.interfaces.iter_mut() {
680 *id = remap.map_interface(*id, Default::default())?;
681 }
682 for (_, id) in pkg.worlds.iter_mut() {
683 *id = remap.map_world(*id, Default::default())?;
684 }
685 self.packages.alloc(pkg)
686 }
687 };
688 assert_eq!(remap.packages.len(), id.index());
689 remap.packages.push(new_id);
690 }
691
692 for (name, id) in package_names {
693 let id = remap.packages[id.index()];
694 if let Some(prev) = self.package_names.insert(name, id) {
695 assert_eq!(prev, id);
696 }
697 }
698
699 for id in moved_worlds {
707 let id = remap.map_world(id, Default::default())?;
708 if let Some(pkg) = self.worlds[id].package.as_mut() {
709 *pkg = remap.packages[pkg.index()];
710 }
711 }
712 for id in moved_interfaces {
713 let id = remap.map_interface(id, Default::default())?;
714 if let Some(pkg) = self.interfaces[id].package.as_mut() {
715 *pkg = remap.packages[pkg.index()];
716 }
717 if let Some(clone_of) = self.interfaces[id].clone_of.as_mut() {
718 *clone_of = remap.map_interface(*clone_of, Default::default())?;
719 }
720 }
721 for id in moved_types {
722 let id = remap.map_type(id, Default::default())?;
723 match &mut self.types[id].owner {
724 TypeOwner::Interface(id) => *id = remap.map_interface(*id, Default::default())?,
725 TypeOwner::World(id) => *id = remap.map_world(*id, Default::default())?,
726 TypeOwner::None => {}
727 }
728 }
729
730 for (name, pkg, iface) in interfaces_to_add {
735 let prev = self.packages[pkg]
736 .interfaces
737 .insert(name, remap.map_interface(iface, Default::default())?);
738 assert!(prev.is_none());
739 }
740 for (name, pkg, world) in worlds_to_add {
741 let prev = self.packages[pkg]
742 .worlds
743 .insert(name, remap.map_world(world, Default::default())?);
744 assert!(prev.is_none());
745 }
746
747 log::trace!("now have {} packages", self.packages.len());
748
749 let world_ids: Vec<_> = self.worlds.iter().map(|(id, _)| id).collect();
753 for world_id in world_ids {
754 let world_span = self.worlds[world_id].span;
755 self.elaborate_world(world_id, world_span)?;
756 }
757
758 #[cfg(debug_assertions)]
759 self.assert_valid();
760 Ok(remap)
761 }
762
763 fn update_world_imports_stability(
764 from_item: (&WorldKey, &WorldItem),
765 into_items: &mut IndexMap<WorldKey, WorldItem>,
766 interface_map: &HashMap<Id<Interface>, Id<Interface>>,
767 ) -> anyhow::Result<()> {
768 match from_item.0 {
769 WorldKey::Name(_) => {
770 Ok(())
772 }
773 key @ WorldKey::Interface(_) => {
774 let new_key = MergeMap::map_name(key, interface_map);
775 if let Some(into) = into_items.get_mut(&new_key) {
776 match (from_item.1, into) {
777 (
778 WorldItem::Interface {
779 id: aid,
780 stability: astability,
781 span: aspan,
782 ..
783 },
784 WorldItem::Interface {
785 id: bid,
786 stability: bstability,
787 ..
788 },
789 ) => {
790 let aid = interface_map.get(aid).copied().unwrap_or(*aid);
791 assert_eq!(aid, *bid);
792 update_stability(astability, bstability, *aspan)?;
793 Ok(())
794 }
795 _ => unreachable!(),
796 }
797 } else {
798 unreachable!()
801 }
802 }
803 }
804 }
805
806 pub fn merge_worlds(
821 &mut self,
822 from: WorldId,
823 into: WorldId,
824 clone_maps: &mut CloneMaps,
825 ) -> anyhow::Result<()> {
826 let mut new_imports = Vec::new();
827 let mut new_exports = Vec::new();
828
829 let from_world = &self.worlds[from];
830 let into_world = &self.worlds[into];
831
832 log::trace!("merging {} into {}", from_world.name, into_world.name);
833
834 for (name, from_import) in from_world.imports.iter() {
842 let name_str = self.name_world_key(name);
843 match into_world.imports.get(name) {
844 Some(into_import) => {
845 log::trace!("info/from shared import on `{name_str}`");
846 self.merge_world_item(from_import, into_import)
847 .with_context(|| format!("failed to merge world import {name_str}"))?;
848 }
849 None => {
850 log::trace!("new import: `{name_str}`");
851 new_imports.push((name.clone(), from_import.clone()));
852 }
853 }
854 }
855
856 let mut must_be_imported = HashMap::new();
863 for (key, export) in into_world.exports.iter() {
864 for dep in self.world_item_direct_deps(export) {
865 if into_world.exports.contains_key(&WorldKey::Interface(dep)) {
866 continue;
867 }
868 self.foreach_interface_dep(dep, &mut |id| {
869 must_be_imported.insert(id, key.clone());
870 });
871 }
872 }
873
874 for (name, from_export) in from_world.exports.iter() {
877 let name_str = self.name_world_key(name);
878 match into_world.exports.get(name) {
879 Some(into_export) => {
880 log::trace!("info/from shared export on `{name_str}`");
881 self.merge_world_item(from_export, into_export)
882 .with_context(|| format!("failed to merge world export {name_str}"))?;
883 }
884 None => {
885 log::trace!("new export `{name_str}`");
886 self.ensure_can_add_world_export(
889 into_world,
890 name,
891 from_export,
892 &must_be_imported,
893 )
894 .with_context(|| {
895 format!("failed to add export `{}`", self.name_world_key(name))
896 })?;
897 new_exports.push((name.clone(), from_export.clone()));
898 }
899 }
900 }
901
902 let mut cloner = clone::Cloner::new(
916 self,
917 clone_maps,
918 TypeOwner::World(from),
919 TypeOwner::World(into),
920 );
921 cloner.register_world_type_overlap(from, into);
922 for (name, item) in new_imports.iter_mut().chain(&mut new_exports) {
923 cloner.world_item(name, item);
924 }
925
926 let into_world = &mut self.worlds[into];
928 for (name, import) in new_imports {
929 let prev = into_world.imports.insert(name, import);
930 assert!(prev.is_none());
931 }
932 for (name, export) in new_exports {
933 let prev = into_world.exports.insert(name, export);
934 assert!(prev.is_none());
935 }
936
937 #[cfg(debug_assertions)]
938 self.assert_valid();
939 Ok(())
940 }
941
942 fn merge_world_item(&self, from: &WorldItem, into: &WorldItem) -> anyhow::Result<()> {
943 let mut map = MergeMap::new(self, self);
944 match (from, into) {
945 (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
946 if from == into {
951 return Ok(());
952 }
953
954 map.build_interface(*from, *into)
964 .context("failed to merge interfaces")?;
965 }
966
967 (WorldItem::Function(from), WorldItem::Function(into)) => {
970 map.build_function(from, into)
971 .context("failed to merge functions")?;
972 }
973 (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
974 map.build_type_id(*from, *into)
975 .context("failed to merge types")?;
976 }
977
978 (WorldItem::Interface { .. }, _)
980 | (WorldItem::Function { .. }, _)
981 | (WorldItem::Type { .. }, _) => {
982 bail!("different kinds of items");
983 }
984 }
985 assert!(map.interfaces_to_add.is_empty());
986 assert!(map.worlds_to_add.is_empty());
987 Ok(())
988 }
989
990 fn ensure_can_add_world_export(
1002 &self,
1003 into: &World,
1004 name: &WorldKey,
1005 item: &WorldItem,
1006 must_be_imported: &HashMap<InterfaceId, WorldKey>,
1007 ) -> anyhow::Result<()> {
1008 assert!(!into.exports.contains_key(name));
1009 let name = self.name_world_key(name);
1010
1011 for dep in self.world_item_direct_deps(item) {
1015 if into.exports.contains_key(&WorldKey::Interface(dep)) {
1016 continue;
1017 }
1018 self.ensure_not_exported(into, dep)
1019 .with_context(|| format!("failed validating export of `{name}`"))?;
1020 }
1021
1022 if let WorldItem::Interface { id, .. } = item {
1026 if let Some(export) = must_be_imported.get(id) {
1027 let export_name = self.name_world_key(export);
1028 bail!(
1029 "export `{export_name}` depends on `{name}` \
1030 previously as an import which will change meaning \
1031 if `{name}` is added as an export"
1032 );
1033 }
1034 }
1035
1036 Ok(())
1037 }
1038
1039 fn ensure_not_exported(&self, world: &World, id: InterfaceId) -> anyhow::Result<()> {
1040 let key = WorldKey::Interface(id);
1041 let name = self.name_world_key(&key);
1042 if world.exports.contains_key(&key) {
1043 bail!(
1044 "world exports `{name}` but it's also transitively used by an \
1045 import \
1046 which means that this is not valid"
1047 )
1048 }
1049 for dep in self.interface_direct_deps(id) {
1050 self.ensure_not_exported(world, dep)
1051 .with_context(|| format!("failed validating transitive import dep `{name}`"))?;
1052 }
1053 Ok(())
1054 }
1055
1056 fn world_item_direct_deps(&self, item: &WorldItem) -> impl Iterator<Item = InterfaceId> + '_ {
1062 let mut interface = None;
1063 let mut ty = None;
1064 match item {
1065 WorldItem::Function(_) => {}
1066 WorldItem::Type { id, .. } => ty = Some(*id),
1067 WorldItem::Interface { id, .. } => interface = Some(*id),
1068 }
1069
1070 interface
1071 .into_iter()
1072 .flat_map(move |id| self.interface_direct_deps(id))
1073 .chain(ty.and_then(|t| self.type_interface_dep(t)))
1074 }
1075
1076 fn foreach_interface_dep(&self, id: InterfaceId, f: &mut dyn FnMut(InterfaceId)) {
1080 self._foreach_interface_dep(id, f, &mut HashSet::new())
1081 }
1082
1083 fn _foreach_interface_dep(
1087 &self,
1088 id: InterfaceId,
1089 f: &mut dyn FnMut(InterfaceId),
1090 visited: &mut HashSet<InterfaceId>,
1091 ) {
1092 if !visited.insert(id) {
1093 return;
1094 }
1095 f(id);
1096 for dep in self.interface_direct_deps(id) {
1097 self._foreach_interface_dep(dep, f, visited);
1098 }
1099 }
1100
1101 pub fn id_of(&self, interface: InterfaceId) -> Option<String> {
1105 let interface = &self.interfaces[interface];
1106 Some(self.id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1107 }
1108
1109 pub fn canonicalized_id_of(&self, interface: InterfaceId) -> Option<String> {
1114 let interface = &self.interfaces[interface];
1115 Some(self.canonicalized_id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1116 }
1117
1118 fn rename_world(
1123 &mut self,
1124 world_id: WorldId,
1125 out_world_name: Option<String>,
1126 default_suffix: &str,
1127 ) {
1128 let world = &mut self.worlds[world_id];
1129 let pkg = &mut self.packages[world.package.unwrap()];
1130 pkg.worlds.shift_remove(&world.name);
1131 if let Some(name) = out_world_name {
1132 world.name = name.clone();
1133 pkg.worlds.insert(name, world_id);
1134 } else {
1135 world.name.push_str(default_suffix);
1136 pkg.worlds.insert(world.name.clone(), world_id);
1137 }
1138 }
1139
1140 pub fn importize(
1156 &mut self,
1157 world_id: WorldId,
1158 out_world_name: Option<String>,
1159 ) -> anyhow::Result<()> {
1160 self.rename_world(world_id, out_world_name, "-importized");
1161
1162 let world = &mut self.worlds[world_id];
1165 world.imports.retain(|_, item| match item {
1166 WorldItem::Type { .. } => true,
1167 _ => false,
1168 });
1169
1170 for (name, export) in mem::take(&mut world.exports) {
1171 match (name.clone(), world.imports.insert(name, export)) {
1172 (_, None) => {}
1174
1175 (WorldKey::Name(name), Some(_)) => {
1177 bail!("world export `{name}` conflicts with import of same name");
1178 }
1179
1180 (WorldKey::Interface(_), _) => unreachable!(),
1183 }
1184 }
1185
1186 let world_span = world.span;
1189 self.elaborate_world(world_id, world_span)?;
1190
1191 #[cfg(debug_assertions)]
1192 self.assert_valid();
1193 Ok(())
1194 }
1195
1196 pub fn exportize(
1215 &mut self,
1216 world_id: WorldId,
1217 out_world_name: Option<String>,
1218 filter: Option<&dyn Fn(&WorldKey, &WorldItem) -> bool>,
1219 ) -> anyhow::Result<()> {
1220 self.rename_world(world_id, out_world_name, "-exportized");
1221
1222 let world = &mut self.worlds[world_id];
1223 world.exports.clear();
1224
1225 let old_imports = mem::take(&mut world.imports);
1226 for (name, import) in old_imports {
1227 let should_move = match &filter {
1228 Some(f) => f(&name, &import),
1229 None => true,
1230 };
1231 if should_move {
1232 world.exports.insert(name, import);
1233 } else {
1234 world.imports.insert(name, import);
1235 }
1236 }
1237
1238 let world_span = world.span;
1241 self.elaborate_world(world_id, world_span)?;
1242
1243 #[cfg(debug_assertions)]
1244 self.assert_valid();
1245 Ok(())
1246 }
1247
1248 pub fn id_of_name(&self, pkg: PackageId, name: &str) -> String {
1250 let package = &self.packages[pkg];
1251 let mut base = String::new();
1252 base.push_str(&package.name.namespace);
1253 base.push_str(":");
1254 base.push_str(&package.name.name);
1255 base.push_str("/");
1256 base.push_str(name);
1257 if let Some(version) = &package.name.version {
1258 base.push_str(&format!("@{version}"));
1259 }
1260 base
1261 }
1262
1263 pub fn canonicalized_id_of_name(&self, pkg: PackageId, name: &str) -> String {
1269 let package = &self.packages[pkg];
1270 let mut base = String::new();
1271 base.push_str(&package.name.namespace);
1272 base.push_str(":");
1273 base.push_str(&package.name.name);
1274 base.push_str("/");
1275 base.push_str(name);
1276 if let Some(version) = &package.name.version {
1277 base.push_str("@");
1278 let string = PackageName::version_compat_track_string(version);
1279 base.push_str(&string);
1280 }
1281 base
1282 }
1283
1284 pub fn select_world(
1399 &self,
1400 main_packages: &[PackageId],
1401 world: Option<&str>,
1402 ) -> anyhow::Result<WorldId> {
1403 let world_path = match world {
1405 Some(world) => Some(
1406 parse_use_path(world)
1407 .with_context(|| format!("failed to parse world specifier `{world}`"))?,
1408 ),
1409 None => None,
1410 };
1411
1412 match world_path {
1413 Some(world_path) => {
1415 let (pkg, world_name) = match (main_packages, world_path) {
1416 ([], _) => bail!("No main packages defined"),
1418
1419 ([main_package], ParsedUsePath::Name(name)) => (*main_package, name),
1421
1422 (_, ParsedUsePath::Name(_name)) => {
1424 bail!(
1425 "There are multiple main packages; a world must be explicitly chosen:{}",
1426 self.worlds
1427 .iter()
1428 .map(|world| format!(
1429 "\n {}",
1430 self.id_of_name(world.1.package.unwrap(), &world.1.name)
1431 ))
1432 .collect::<String>()
1433 )
1434 }
1435
1436 (_, ParsedUsePath::Package(pkg, world_name)) => {
1438 let pkg = match self.package_names.get(&pkg) {
1439 Some(pkg) => *pkg,
1440 None => {
1441 let mut candidates =
1442 self.package_names.iter().filter(|(name, _)| {
1443 pkg.version.is_none()
1444 && pkg.name == name.name
1445 && pkg.namespace == name.namespace
1446 && name.version.is_some()
1447 });
1448 let candidate = candidates.next();
1449 if let Some((c2, _)) = candidates.next() {
1450 let (c1, _) = candidate.unwrap();
1451 bail!(
1452 "package name `{pkg}` is available at both \
1453 versions {} and {} but which is not specified",
1454 c1.version.as_ref().unwrap(),
1455 c2.version.as_ref().unwrap(),
1456 );
1457 }
1458 match candidate {
1459 Some((_, id)) => *id,
1460 None => bail!("unknown package `{pkg}`"),
1461 }
1462 }
1463 };
1464 (pkg, world_name.to_string())
1465 }
1466 };
1467
1468 let pkg = &self.packages[pkg];
1470 pkg.worlds.get(&world_name).copied().ok_or_else(|| {
1471 anyhow!("World `{world_name}` not found in package `{}`", pkg.name)
1472 })
1473 }
1474
1475 None => match main_packages {
1477 [] => bail!("No main packages defined"),
1478
1479 [main_package] => {
1481 let pkg = &self.packages[*main_package];
1482 match pkg.worlds.len() {
1483 0 => bail!("The main package `{}` contains no worlds", pkg.name),
1484 1 => Ok(pkg.worlds[0]),
1485 _ => bail!(
1486 "There are multiple worlds in `{}`; one must be explicitly chosen:{}",
1487 pkg.name,
1488 pkg.worlds
1489 .values()
1490 .map(|world| format!(
1491 "\n {}",
1492 self.id_of_name(*main_package, &self.worlds[*world].name)
1493 ))
1494 .collect::<String>()
1495 ),
1496 }
1497 }
1498
1499 _ => {
1501 bail!(
1502 "There are multiple main packages; a world must be explicitly chosen:{}",
1503 self.worlds
1504 .iter()
1505 .map(|world| format!(
1506 "\n {}",
1507 self.id_of_name(world.1.package.unwrap(), &world.1.name)
1508 ))
1509 .collect::<String>()
1510 )
1511 }
1512 },
1513 }
1514 }
1515
1516 pub fn name_world_key(&self, key: &WorldKey) -> String {
1518 match key {
1519 WorldKey::Name(s) => s.to_string(),
1520 WorldKey::Interface(i) => self.id_of(*i).expect("unexpected anonymous interface"),
1521 }
1522 }
1523
1524 pub fn name_canonicalized_world_key(&self, key: &WorldKey) -> String {
1527 match key {
1528 WorldKey::Name(s) => s.to_string(),
1529 WorldKey::Interface(i) => self
1530 .canonicalized_id_of(*i)
1531 .expect("unexpected anonymous interface"),
1532 }
1533 }
1534
1535 pub fn implements_value(&self, key: &WorldKey, item: &WorldItem) -> Option<String> {
1540 if let WorldKey::Name(_) = key {
1541 if let WorldItem::Interface { id, .. } = item {
1542 if self.interfaces[*id].name.is_some() {
1543 return Some(self.id_of(*id).unwrap().into());
1544 }
1545 }
1546 }
1547 None
1548 }
1549
1550 pub fn type_interface_dep(&self, id: TypeId) -> Option<InterfaceId> {
1556 let ty = &self.types[id];
1557 let dep = match ty.kind {
1558 TypeDefKind::Type(Type::Id(id)) => id,
1559 _ => return None,
1560 };
1561 let other = &self.types[dep];
1562 if ty.owner == other.owner {
1563 None
1564 } else {
1565 match other.owner {
1566 TypeOwner::Interface(id) => Some(id),
1567 _ => unreachable!(),
1568 }
1569 }
1570 }
1571
1572 pub fn interface_direct_deps(&self, id: InterfaceId) -> impl Iterator<Item = InterfaceId> + '_ {
1582 self.interfaces[id]
1583 .types
1584 .iter()
1585 .filter_map(move |(_name, ty)| self.type_interface_dep(*ty))
1586 }
1587
1588 pub fn package_direct_deps(&self, id: PackageId) -> impl Iterator<Item = PackageId> + '_ {
1598 let pkg = &self.packages[id];
1599
1600 pkg.interfaces
1601 .iter()
1602 .flat_map(move |(_name, id)| self.interface_direct_deps(*id))
1603 .chain(pkg.worlds.iter().flat_map(move |(_name, id)| {
1604 let world = &self.worlds[*id];
1605 world
1606 .imports
1607 .iter()
1608 .chain(world.exports.iter())
1609 .filter_map(move |(_name, item)| match item {
1610 WorldItem::Interface { id, .. } => Some(*id),
1611 WorldItem::Function(_) => None,
1612 WorldItem::Type { id, .. } => self.type_interface_dep(*id),
1613 })
1614 }))
1615 .filter_map(move |iface_id| {
1616 let pkg = self.interfaces[iface_id].package?;
1617 if pkg == id { None } else { Some(pkg) }
1618 })
1619 }
1620
1621 pub fn topological_packages(&self) -> Vec<PackageId> {
1627 let mut pushed = vec![false; self.packages.len()];
1628 let mut order = Vec::new();
1629 for (id, _) in self.packages.iter() {
1630 self.build_topological_package_ordering(id, &mut pushed, &mut order);
1631 }
1632 order
1633 }
1634
1635 fn build_topological_package_ordering(
1636 &self,
1637 id: PackageId,
1638 pushed: &mut Vec<bool>,
1639 order: &mut Vec<PackageId>,
1640 ) {
1641 if pushed[id.index()] {
1642 return;
1643 }
1644 for dep in self.package_direct_deps(id) {
1645 self.build_topological_package_ordering(dep, pushed, order);
1646 }
1647 order.push(id);
1648 pushed[id.index()] = true;
1649 }
1650
1651 #[doc(hidden)]
1652 pub fn assert_valid(&self) {
1653 let mut package_interfaces = Vec::new();
1654 let mut package_worlds = Vec::new();
1655 for (id, pkg) in self.packages.iter() {
1656 let mut interfaces = HashSet::new();
1657 for (name, iface) in pkg.interfaces.iter() {
1658 assert!(interfaces.insert(*iface));
1659 let iface = &self.interfaces[*iface];
1660 assert_eq!(name, iface.name.as_ref().unwrap());
1661 assert_eq!(iface.package.unwrap(), id);
1662 }
1663 package_interfaces.push(pkg.interfaces.values().copied().collect::<HashSet<_>>());
1664 let mut worlds = HashSet::new();
1665 for (name, world) in pkg.worlds.iter() {
1666 assert!(worlds.insert(*world));
1667 assert_eq!(
1668 pkg.worlds.get_key_value(name),
1669 Some((name, world)),
1670 "`MutableKeys` impl may have been used to change a key's hash or equality"
1671 );
1672 let world = &self.worlds[*world];
1673 assert_eq!(*name, world.name);
1674 assert_eq!(world.package.unwrap(), id);
1675 }
1676 package_worlds.push(pkg.worlds.values().copied().collect::<HashSet<_>>());
1677 }
1678
1679 let mut interface_types = Vec::new();
1680 for (id, iface) in self.interfaces.iter() {
1681 assert!(self.packages.get(iface.package.unwrap()).is_some());
1682 if iface.name.is_some() {
1683 match iface.clone_of {
1684 Some(other) => {
1685 assert_eq!(iface.name, self.interfaces[other].name);
1686 }
1687 None => {
1688 assert!(package_interfaces[iface.package.unwrap().index()].contains(&id));
1689 }
1690 }
1691 }
1692
1693 for (name, ty) in iface.types.iter() {
1694 let ty = &self.types[*ty];
1695 assert_eq!(ty.name.as_ref(), Some(name));
1696 assert_eq!(ty.owner, TypeOwner::Interface(id));
1697 }
1698 interface_types.push(iface.types.values().copied().collect::<HashSet<_>>());
1699 for (name, f) in iface.functions.iter() {
1700 assert_eq!(*name, f.name);
1701 }
1702 }
1703
1704 let mut world_types = Vec::new();
1705 for (id, world) in self.worlds.iter() {
1706 log::debug!("validating world {}", &world.name);
1707 if let Some(package) = world.package {
1708 assert!(self.packages.get(package).is_some());
1709 assert!(package_worlds[package.index()].contains(&id));
1710 }
1711 assert!(world.includes.is_empty());
1712
1713 let mut types = HashSet::new();
1714 for (name, item) in world.imports.iter().chain(world.exports.iter()) {
1715 log::debug!("validating world item: {}", self.name_world_key(name));
1716 match item {
1717 WorldItem::Interface { id, .. } => {
1718 if matches!(name, WorldKey::Name(_)) {
1722 let iface = &self.interfaces[*id];
1723 if iface.name.is_none() {
1724 assert_eq!(iface.package, world.package);
1725 }
1726 }
1727 }
1728 WorldItem::Function(f) => {
1729 assert!(!matches!(name, WorldKey::Interface(_)));
1730 assert_eq!(f.name, name.clone().unwrap_name());
1731 }
1732 WorldItem::Type { id: ty, .. } => {
1733 assert!(!matches!(name, WorldKey::Interface(_)));
1734 assert!(types.insert(*ty));
1735 let ty = &self.types[*ty];
1736 assert_eq!(ty.name, Some(name.clone().unwrap_name()));
1737 assert_eq!(ty.owner, TypeOwner::World(id));
1738 }
1739 }
1740 }
1741 self.assert_world_elaborated(world);
1742 world_types.push(types);
1743 }
1744
1745 for (ty_id, ty) in self.types.iter() {
1746 match ty.owner {
1747 TypeOwner::Interface(id) => {
1748 assert!(self.interfaces.get(id).is_some());
1749 assert!(interface_types[id.index()].contains(&ty_id));
1750 }
1751 TypeOwner::World(id) => {
1752 assert!(self.worlds.get(id).is_some());
1753 assert!(world_types[id.index()].contains(&ty_id));
1754 }
1755 TypeOwner::None => {}
1756 }
1757 }
1758
1759 self.assert_topologically_sorted();
1760 }
1761
1762 fn assert_topologically_sorted(&self) {
1763 let mut positions = IndexMap::default();
1764 for id in self.topological_packages() {
1765 let pkg = &self.packages[id];
1766 log::debug!("pkg {}", pkg.name);
1767 let prev = positions.insert(Some(id), IndexSet::default());
1768 assert!(prev.is_none());
1769 }
1770 positions.insert(None, IndexSet::default());
1771
1772 for (id, iface) in self.interfaces.iter() {
1773 log::debug!("iface {:?}", iface.name);
1774 let ok = positions.get_mut(&iface.package).unwrap().insert(id);
1775 assert!(ok);
1776 }
1777
1778 for (_, world) in self.worlds.iter() {
1779 log::debug!("world {:?}", world.name);
1780
1781 let my_package = world.package;
1782 let my_package_pos = positions.get_index_of(&my_package).unwrap();
1783
1784 for (_, item) in world.imports.iter().chain(&world.exports) {
1785 let id = match item {
1786 WorldItem::Interface { id, .. } => *id,
1787 _ => continue,
1788 };
1789 let other_package = self.interfaces[id].package;
1790 let other_package_pos = positions.get_index_of(&other_package).unwrap();
1791
1792 assert!(other_package_pos <= my_package_pos);
1793 }
1794 }
1795
1796 for (_id, ty) in self.types.iter() {
1797 log::debug!("type {:?} {:?}", ty.name, ty.owner);
1798 let other_id = match ty.kind {
1799 TypeDefKind::Type(Type::Id(ty)) => ty,
1800 _ => continue,
1801 };
1802 let other = &self.types[other_id];
1803 if ty.kind == other.kind {
1804 continue;
1805 }
1806 let my_interface = match ty.owner {
1807 TypeOwner::Interface(id) => id,
1808 _ => continue,
1809 };
1810 let other_interface = match other.owner {
1811 TypeOwner::Interface(id) => id,
1812 _ => continue,
1813 };
1814
1815 let my_package = self.interfaces[my_interface].package;
1816 let other_package = self.interfaces[other_interface].package;
1817 let my_package_pos = positions.get_index_of(&my_package).unwrap();
1818 let other_package_pos = positions.get_index_of(&other_package).unwrap();
1819
1820 assert!(other_package_pos <= my_package_pos);
1821 }
1822 }
1823
1824 fn assert_world_elaborated(&self, world: &World) {
1825 for (key, item) in world.imports.iter() {
1826 log::debug!(
1827 "asserting elaborated world import {}",
1828 self.name_world_key(key)
1829 );
1830 match item {
1831 WorldItem::Type { id, .. } => self.assert_world_imports_type_deps(world, key, *id),
1832
1833 WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1835
1836 WorldItem::Interface { id, .. } => {
1838 for dep in self.interface_direct_deps(*id) {
1839 assert!(
1840 world.imports.contains_key(&WorldKey::Interface(dep)),
1841 "world import of {} is missing transitive dep of {}",
1842 self.name_world_key(key),
1843 self.id_of(dep).unwrap(),
1844 );
1845 }
1846 }
1847 }
1848 }
1849 for (key, item) in world.exports.iter() {
1850 log::debug!(
1851 "asserting elaborated world export {}",
1852 self.name_world_key(key)
1853 );
1854 match item {
1855 WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1857
1858 WorldItem::Interface { id, .. } => {
1862 for dep in self.interface_direct_deps(*id) {
1863 let dep_key = WorldKey::Interface(dep);
1864 if world.exports.contains_key(&dep_key) {
1865 continue;
1866 }
1867 self.foreach_interface_dep(dep, &mut |dep| {
1868 let dep_key = WorldKey::Interface(dep);
1869 assert!(
1870 world.imports.contains_key(&dep_key),
1871 "world should import {} (required by {})",
1872 self.name_world_key(&dep_key),
1873 self.name_world_key(key),
1874 );
1875 assert!(
1876 !world.exports.contains_key(&dep_key),
1877 "world should not export {} (required by {})",
1878 self.name_world_key(&dep_key),
1879 self.name_world_key(key),
1880 );
1881 });
1882 }
1883 }
1884
1885 WorldItem::Type { .. } => unreachable!(),
1887 }
1888 }
1889 }
1890
1891 fn assert_world_imports_type_deps(&self, world: &World, key: &WorldKey, ty: TypeId) {
1892 let ty = &self.types[ty];
1895 if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
1896 if let TypeOwner::Interface(id) = self.types[other].owner {
1897 let key = WorldKey::Interface(id);
1898 assert!(world.imports.contains_key(&key));
1899 return;
1900 }
1901 }
1902
1903 let mut visitor = MyVisit(self, Vec::new());
1907 visitor.visit_type_def(self, ty);
1908 for ty in visitor.1 {
1909 let ty = &self.types[ty];
1910 let Some(name) = ty.name.clone() else {
1911 continue;
1912 };
1913 let dep_key = WorldKey::Name(name);
1914 assert!(
1915 world.imports.contains_key(&dep_key),
1916 "world import `{}` should also force an import of `{}`",
1917 self.name_world_key(key),
1918 self.name_world_key(&dep_key),
1919 );
1920 }
1921
1922 struct MyVisit<'a>(&'a Resolve, Vec<TypeId>);
1923
1924 impl TypeIdVisitor for MyVisit<'_> {
1925 fn before_visit_type_id(&mut self, id: TypeId) -> bool {
1926 self.1.push(id);
1927 self.0.types[id].name.is_none()
1929 }
1930 }
1931 }
1932
1933 fn assert_world_function_imports_types(&self, world: &World, key: &WorldKey, func: &Function) {
1937 for ty in func
1938 .parameter_and_result_types()
1939 .chain(func.kind.resource().map(Type::Id))
1940 {
1941 let Type::Id(id) = ty else {
1942 continue;
1943 };
1944 self.assert_world_imports_type_deps(world, key, id);
1945 }
1946 }
1947
1948 fn include_stability(
1964 &self,
1965 stability: &Stability,
1966 pkg_id: &PackageId,
1967 span: Span,
1968 ) -> ResolveResult<bool> {
1969 Ok(match stability {
1970 Stability::Unknown => true,
1971 Stability::Stable { since, .. } => {
1974 let Some(p) = self.packages.get(*pkg_id) else {
1975 return Ok(true);
1983 };
1984
1985 let package_version = p.name.version.as_ref().ok_or_else(|| {
1988 ResolveError::new_semantic(
1989 span,
1990 format!(
1991 "package [{}] contains a feature gate with a version \
1992 specifier, so it must have a version",
1993 p.name
1994 ),
1995 )
1996 })?;
1997
1998 if since > package_version {
2002 return Err(ResolveError::new_semantic(
2003 span,
2004 format!(
2005 "feature gate cannot reference unreleased version \
2006 {since} of package [{}] (current version {package_version})",
2007 p.name
2008 ),
2009 ));
2010 }
2011
2012 true
2013 }
2014 Stability::Unstable { feature, .. } => {
2015 self.features.contains(feature) || self.all_features
2016 }
2017 })
2018 }
2019
2020 fn elaborate_world(&mut self, world_id: WorldId, span: Span) -> ResolveResult<()> {
2032 let mut new_imports = IndexMap::default();
2036 let world = &self.worlds[world_id];
2037
2038 let sort_key = |resolve: &Resolve, item: &WorldItem| match item {
2061 WorldItem::Interface { .. } => 0,
2062 WorldItem::Type { id, .. } => {
2063 let ty = &resolve.types[*id];
2064 match ty.kind {
2065 TypeDefKind::Type(Type::Id(t)) if resolve.types[t].owner != ty.owner => 1,
2066 _ => 2,
2067 }
2068 }
2069 WorldItem::Function(f) => {
2070 if f.kind.resource().is_none() {
2071 3
2072 } else {
2073 4
2074 }
2075 }
2076 };
2077
2078 let mut world_imports = world.imports.iter().collect::<Vec<_>>();
2081 world_imports.sort_by_key(|(_name, import)| sort_key(self, import));
2082 for (name, item) in world_imports {
2083 match item {
2084 WorldItem::Interface {
2087 id,
2088 stability,
2089 docs,
2090 ..
2091 } => {
2092 self.elaborate_world_import(
2093 &mut new_imports,
2094 name.clone(),
2095 *id,
2096 &stability,
2097 docs,
2098 );
2099 }
2100
2101 WorldItem::Function(_) => {
2104 let prev = new_imports.insert(name.clone(), item.clone());
2105 assert!(prev.is_none());
2106 }
2107
2108 WorldItem::Type { id, .. } => {
2112 if let Some(dep) = self.type_interface_dep(*id) {
2113 self.elaborate_world_import(
2114 &mut new_imports,
2115 WorldKey::Interface(dep),
2116 dep,
2117 &self.types[*id].stability,
2118 &Docs::default(),
2119 );
2120 }
2121 let prev = new_imports.insert(name.clone(), item.clone());
2122 assert!(prev.is_none());
2123 }
2124 }
2125 }
2126
2127 let mut new_exports = IndexMap::default();
2133 let mut export_interfaces = IndexMap::default();
2134 for (name, item) in world.exports.iter() {
2135 match item {
2136 WorldItem::Interface { .. } => {
2137 let prev = export_interfaces.insert(name.clone(), item.clone());
2138 assert!(prev.is_none());
2139 }
2140 WorldItem::Function(_) => {
2141 let prev = new_exports.insert(name.clone(), item.clone());
2142 assert!(prev.is_none());
2143 }
2144 WorldItem::Type { .. } => unreachable!(),
2145 }
2146 }
2147
2148 self.elaborate_world_exports(&export_interfaces, &mut new_imports, &mut new_exports, span)?;
2149
2150 new_imports.sort_by_cached_key(|_name, import| sort_key(self, import));
2154
2155 log::trace!("imports = {new_imports:?}");
2158 log::trace!("exports = {new_exports:?}");
2159 let world = &mut self.worlds[world_id];
2160 world.imports = new_imports;
2161 world.exports = new_exports;
2162
2163 Ok(())
2164 }
2165
2166 fn elaborate_world_import(
2167 &self,
2168 imports: &mut IndexMap<WorldKey, WorldItem>,
2169 key: WorldKey,
2170 id: InterfaceId,
2171 stability: &Stability,
2172 docs: &Docs,
2173 ) {
2174 if imports.contains_key(&key) {
2175 return;
2176 }
2177 for dep in self.interface_direct_deps(id) {
2180 self.elaborate_world_import(
2181 imports,
2182 WorldKey::Interface(dep),
2183 dep,
2184 stability,
2185 &Docs::default(),
2186 );
2187 }
2188 let prev = imports.insert(
2189 key,
2190 WorldItem::Interface {
2191 id,
2192 stability: stability.clone(),
2193 docs: docs.clone(),
2194 span: Default::default(),
2195 },
2196 );
2197 assert!(prev.is_none());
2198 }
2199
2200 fn elaborate_world_exports(
2247 &self,
2248 export_interfaces: &IndexMap<WorldKey, WorldItem>,
2249 imports: &mut IndexMap<WorldKey, WorldItem>,
2250 exports: &mut IndexMap<WorldKey, WorldItem>,
2251 span: Span,
2252 ) -> ResolveResult<()> {
2253 let mut required_imports = HashSet::new();
2254 for (key, item) in export_interfaces.iter() {
2255 let name = self.name_world_key(&key);
2256 let ok = add_world_export(
2257 self,
2258 imports,
2259 exports,
2260 &export_interfaces,
2261 &mut required_imports,
2262 key.clone(),
2263 item.clone(),
2264 true,
2265 );
2266 if !ok {
2267 return Err(ResolveError::from(
2285 ResolveErrorKind::InvalidTransitiveDependency { name, span },
2286 ));
2287 }
2288 }
2289 return Ok(());
2290
2291 fn add_world_export(
2292 resolve: &Resolve,
2293 imports: &mut IndexMap<WorldKey, WorldItem>,
2294 exports: &mut IndexMap<WorldKey, WorldItem>,
2295 export_interfaces: &IndexMap<WorldKey, WorldItem>,
2296 required_imports: &mut HashSet<InterfaceId>,
2297 key: WorldKey,
2298 item: WorldItem,
2299 add_export: bool,
2300 ) -> bool {
2301 if exports.contains_key(&key) {
2302 if add_export {
2303 return true;
2304 } else {
2305 return false;
2306 }
2307 }
2308 let (id, stability) = match &item {
2309 WorldItem::Interface { id, stability, .. } => (*id, stability),
2310 _ => unreachable!(),
2311 };
2312 if !add_export && required_imports.contains(&id) {
2315 return true;
2316 }
2317 let ok = resolve.interface_direct_deps(id).all(|dep| {
2318 let item = WorldItem::Interface {
2319 id: dep,
2320 stability: stability.clone(),
2321 docs: Default::default(),
2322 span: Default::default(),
2323 };
2324 let key = WorldKey::Interface(dep);
2325 let add_export = add_export && export_interfaces.contains_key(&key);
2326 add_world_export(
2327 resolve,
2328 imports,
2329 exports,
2330 export_interfaces,
2331 required_imports,
2332 key,
2333 item,
2334 add_export,
2335 )
2336 });
2337 if !ok {
2338 return false;
2339 }
2340 if add_export {
2341 if required_imports.contains(&id) {
2342 return false;
2343 }
2344 let prev = exports.insert(key.clone(), item);
2345 assert!(prev.is_none());
2346 } else {
2347 required_imports.insert(id);
2348 if !imports.contains_key(&key) {
2349 imports.insert(key.clone(), item);
2350 }
2351 }
2352 true
2353 }
2354 }
2355
2356 pub fn merge_world_imports_based_on_semver(&mut self, world_id: WorldId) -> anyhow::Result<()> {
2368 let world = &self.worlds[world_id];
2369
2370 let mut semver_tracks = HashMap::new();
2379 let mut to_remove = HashSet::new();
2380 for (key, _) in world.imports.iter() {
2381 let iface_id = match key {
2382 WorldKey::Interface(id) => *id,
2383 WorldKey::Name(_) => continue,
2384 };
2385 let (track, version) = match self.semver_track(iface_id) {
2386 Some(track) => track,
2387 None => continue,
2388 };
2389 log::debug!(
2390 "{} is on track {}/{}",
2391 self.id_of(iface_id).unwrap(),
2392 track.0,
2393 track.1,
2394 );
2395 match semver_tracks.entry(track.clone()) {
2396 Entry::Vacant(e) => {
2397 e.insert((version, iface_id));
2398 }
2399 Entry::Occupied(mut e) => match version.cmp(&e.get().0) {
2400 Ordering::Greater => {
2401 to_remove.insert(e.get().1);
2402 e.insert((version, iface_id));
2403 }
2404 Ordering::Equal => {}
2405 Ordering::Less => {
2406 to_remove.insert(iface_id);
2407 }
2408 },
2409 }
2410 }
2411
2412 let mut replacements = HashMap::new();
2415 for id in to_remove {
2416 let (track, _) = self.semver_track(id).unwrap();
2417 let (_, latest) = semver_tracks[&track];
2418 let prev = replacements.insert(id, latest);
2419 assert!(prev.is_none());
2420 }
2421 drop(semver_tracks);
2424
2425 for (to_replace, replace_with) in replacements.iter() {
2430 self.merge_world_item(
2431 &WorldItem::Interface {
2432 id: *to_replace,
2433 stability: Default::default(),
2434 docs: Default::default(),
2435 span: Default::default(),
2436 },
2437 &WorldItem::Interface {
2438 id: *replace_with,
2439 stability: Default::default(),
2440 docs: Default::default(),
2441 span: Default::default(),
2442 },
2443 )
2444 .with_context(|| {
2445 let old_name = self.id_of(*to_replace).unwrap();
2446 let new_name = self.id_of(*replace_with).unwrap();
2447 format!(
2448 "failed to upgrade `{old_name}` to `{new_name}`, was \
2449 this semver-compatible update not semver compatible?"
2450 )
2451 })?;
2452 }
2453
2454 for (to_replace, replace_with) in replacements.iter() {
2455 log::debug!(
2456 "REPLACE {} => {}",
2457 self.id_of(*to_replace).unwrap(),
2458 self.id_of(*replace_with).unwrap(),
2459 );
2460 }
2461
2462 for (key, item) in mem::take(&mut self.worlds[world_id].imports) {
2471 if let WorldItem::Interface { id, .. } = item {
2472 if replacements.contains_key(&id) {
2473 continue;
2474 }
2475 }
2476
2477 self.update_interface_deps_of_world_item(&item, &replacements);
2478
2479 let prev = self.worlds[world_id].imports.insert(key, item);
2480 assert!(prev.is_none());
2481 }
2482 for (key, item) in mem::take(&mut self.worlds[world_id].exports) {
2483 self.update_interface_deps_of_world_item(&item, &replacements);
2484 let prev = self.worlds[world_id].exports.insert(key, item);
2485 assert!(prev.is_none());
2486 }
2487
2488 let ids = self.worlds.iter().map(|(id, _)| id).collect::<Vec<_>>();
2494 for world_id in ids {
2495 let world_span = self.worlds[world_id].span;
2496 self.elaborate_world(world_id, world_span)?;
2497 }
2498
2499 #[cfg(debug_assertions)]
2500 self.assert_valid();
2501
2502 Ok(())
2503 }
2504
2505 fn update_interface_deps_of_world_item(
2506 &mut self,
2507 item: &WorldItem,
2508 replacements: &HashMap<InterfaceId, InterfaceId>,
2509 ) {
2510 match *item {
2511 WorldItem::Type { id, .. } => self.update_interface_dep_of_type(id, &replacements),
2512 WorldItem::Interface { id, .. } => {
2513 let types = self.interfaces[id]
2514 .types
2515 .values()
2516 .copied()
2517 .collect::<Vec<_>>();
2518 for ty in types {
2519 self.update_interface_dep_of_type(ty, &replacements);
2520 }
2521 }
2522 WorldItem::Function(_) => {}
2523 }
2524 }
2525
2526 fn semver_track(&self, id: InterfaceId) -> Option<((PackageName, String), &Version)> {
2537 let iface = &self.interfaces[id];
2538 let pkg = &self.packages[iface.package?];
2539 let version = pkg.name.version.as_ref()?;
2540 let mut name = pkg.name.clone();
2541 name.version = Some(PackageName::version_compat_track(version));
2542 Some(((name, iface.name.clone()?), version))
2543 }
2544
2545 fn update_interface_dep_of_type(
2549 &mut self,
2550 ty: TypeId,
2551 replacements: &HashMap<InterfaceId, InterfaceId>,
2552 ) {
2553 let to_replace = match self.type_interface_dep(ty) {
2554 Some(id) => id,
2555 None => return,
2556 };
2557 let replace_with = match replacements.get(&to_replace) {
2558 Some(id) => id,
2559 None => return,
2560 };
2561 let dep = match self.types[ty].kind {
2562 TypeDefKind::Type(Type::Id(id)) => id,
2563 _ => return,
2564 };
2565 let name = self.types[dep].name.as_ref().unwrap();
2566 let replacement_id = self.interfaces[*replace_with].types[name];
2569 self.types[ty].kind = TypeDefKind::Type(Type::Id(replacement_id));
2570 }
2571
2572 pub fn wasm_import_name(
2579 &self,
2580 mangling: ManglingAndAbi,
2581 import: WasmImport<'_>,
2582 ) -> (String, String) {
2583 match mangling {
2584 ManglingAndAbi::Standard32 => match import {
2585 WasmImport::Func { interface, func } => {
2586 let module = match interface {
2587 Some(key) => format!("cm32p2|{}", self.name_canonicalized_world_key(key)),
2588 None => format!("cm32p2"),
2589 };
2590 (module, func.name.clone())
2591 }
2592 WasmImport::ResourceIntrinsic {
2593 interface,
2594 resource,
2595 intrinsic,
2596 } => {
2597 let name = self.types[resource].name.as_ref().unwrap();
2598 let (prefix, name) = match intrinsic {
2599 ResourceIntrinsic::ImportedDrop => ("", format!("{name}_drop")),
2600 ResourceIntrinsic::ExportedDrop => ("_ex_", format!("{name}_drop")),
2601 ResourceIntrinsic::ExportedNew => ("_ex_", format!("{name}_new")),
2602 ResourceIntrinsic::ExportedRep => ("_ex_", format!("{name}_rep")),
2603 };
2604 let module = match interface {
2605 Some(key) => {
2606 format!("cm32p2|{prefix}{}", self.name_canonicalized_world_key(key))
2607 }
2608 None => {
2609 assert_eq!(prefix, "");
2610 format!("cm32p2")
2611 }
2612 };
2613 (module, name)
2614 }
2615 WasmImport::FutureIntrinsic { .. } | WasmImport::StreamIntrinsic { .. } => {
2616 panic!(
2617 "at the time of writing, standard32 name mangling only supports the \
2618 synchronous ABI and does not define future/stream intrinsic imports; \
2619 use legacy mangling for these imports"
2620 )
2621 }
2622 },
2623 ManglingAndAbi::Legacy(abi) => match import {
2624 WasmImport::Func { interface, func } => {
2625 let module = match interface {
2626 Some(key) => self.name_world_key(key),
2627 None => format!("$root"),
2628 };
2629 (module, format!("{}{}", abi.import_prefix(), func.name))
2630 }
2631 WasmImport::ResourceIntrinsic {
2632 interface,
2633 resource,
2634 intrinsic,
2635 } => {
2636 let name = self.types[resource].name.as_ref().unwrap();
2637 let (prefix, name) = match intrinsic {
2638 ResourceIntrinsic::ImportedDrop => ("", format!("[resource-drop]{name}")),
2639 ResourceIntrinsic::ExportedDrop => {
2640 ("[export]", format!("[resource-drop]{name}"))
2641 }
2642 ResourceIntrinsic::ExportedNew => {
2643 ("[export]", format!("[resource-new]{name}"))
2644 }
2645 ResourceIntrinsic::ExportedRep => {
2646 ("[export]", format!("[resource-rep]{name}"))
2647 }
2648 };
2649 let module = match interface {
2650 Some(key) => format!("{prefix}{}", self.name_world_key(key)),
2651 None => {
2652 assert_eq!(prefix, "");
2653 format!("$root")
2654 }
2655 };
2656 (module, format!("{}{name}", abi.import_prefix()))
2657 }
2658 WasmImport::FutureIntrinsic {
2659 interface,
2660 func,
2661 ty,
2662 intrinsic,
2663 exported,
2664 async_,
2665 } => {
2666 let module_prefix = if exported { "[export]" } else { "" };
2667 let module = match interface {
2668 Some(key) => format!("{module_prefix}{}", self.name_world_key(key)),
2669 None => format!("{module_prefix}$root"),
2670 };
2671 let type_index = match ty {
2672 Some(ty) => func
2673 .find_futures_and_streams(self)
2674 .into_iter()
2675 .position(|candidate| candidate == ty)
2676 .unwrap_or_else(|| {
2677 panic!(
2678 "future type {ty:?} not found in `find_futures_and_streams` for `{}`",
2679 func.name
2680 )
2681 })
2682 .to_string(),
2683 None => "unit".to_string(),
2684 };
2685 let (async_prefix, name) = match intrinsic {
2686 FutureIntrinsic::New => {
2687 assert!(!async_, "future.new cannot be async-lowered");
2688 ("", "new")
2689 }
2690 FutureIntrinsic::Read => {
2691 (if async_ { "[async-lower]" } else { "" }, "read")
2692 }
2693 FutureIntrinsic::Write => {
2694 (if async_ { "[async-lower]" } else { "" }, "write")
2695 }
2696 FutureIntrinsic::CancelRead => {
2697 (if async_ { "[async-lower]" } else { "" }, "cancel-read")
2698 }
2699 FutureIntrinsic::CancelWrite => {
2700 (if async_ { "[async-lower]" } else { "" }, "cancel-write")
2701 }
2702 FutureIntrinsic::DropReadable => {
2703 assert!(!async_, "future.drop-readable cannot be async-lowered");
2704 ("", "drop-readable")
2705 }
2706 FutureIntrinsic::DropWritable => {
2707 assert!(!async_, "future.drop-writable cannot be async-lowered");
2708 ("", "drop-writable")
2709 }
2710 };
2711 (
2712 module,
2713 format!("{async_prefix}[future-{name}-{type_index}]{}", func.name),
2714 )
2715 }
2716 WasmImport::StreamIntrinsic {
2717 interface,
2718 func,
2719 ty,
2720 intrinsic,
2721 exported,
2722 async_,
2723 } => {
2724 let module_prefix = if exported { "[export]" } else { "" };
2725 let module = match interface {
2726 Some(key) => format!("{module_prefix}{}", self.name_world_key(key)),
2727 None => format!("{module_prefix}$root"),
2728 };
2729 let type_index = match ty {
2730 Some(ty) => func
2731 .find_futures_and_streams(self)
2732 .into_iter()
2733 .position(|candidate| candidate == ty)
2734 .unwrap_or_else(|| {
2735 panic!(
2736 "stream type {ty:?} not found in `find_futures_and_streams` for `{}`",
2737 func.name
2738 )
2739 })
2740 .to_string(),
2741 None => "unit".to_string(),
2742 };
2743 let (async_prefix, name) = match intrinsic {
2744 StreamIntrinsic::New => {
2745 assert!(!async_, "stream.new cannot be async-lowered");
2746 ("", "new")
2747 }
2748 StreamIntrinsic::Read => {
2749 (if async_ { "[async-lower]" } else { "" }, "read")
2750 }
2751 StreamIntrinsic::Write => {
2752 (if async_ { "[async-lower]" } else { "" }, "write")
2753 }
2754 StreamIntrinsic::CancelRead => {
2755 (if async_ { "[async-lower]" } else { "" }, "cancel-read")
2756 }
2757 StreamIntrinsic::CancelWrite => {
2758 (if async_ { "[async-lower]" } else { "" }, "cancel-write")
2759 }
2760 StreamIntrinsic::DropReadable => {
2761 assert!(!async_, "stream.drop-readable cannot be async-lowered");
2762 ("", "drop-readable")
2763 }
2764 StreamIntrinsic::DropWritable => {
2765 assert!(!async_, "stream.drop-writable cannot be async-lowered");
2766 ("", "drop-writable")
2767 }
2768 };
2769 (
2770 module,
2771 format!("{async_prefix}[stream-{name}-{type_index}]{}", func.name),
2772 )
2773 }
2774 },
2775 }
2776 }
2777
2778 pub fn wasm_export_name(&self, mangling: ManglingAndAbi, export: WasmExport<'_>) -> String {
2782 match mangling {
2783 ManglingAndAbi::Standard32 => match export {
2784 WasmExport::Func {
2785 interface,
2786 func,
2787 kind,
2788 } => {
2789 let mut name = String::from("cm32p2|");
2790 if let Some(interface) = interface {
2791 let s = self.name_canonicalized_world_key(interface);
2792 name.push_str(&s);
2793 }
2794 name.push_str("|");
2795 name.push_str(&func.name);
2796 match kind {
2797 WasmExportKind::Normal => {}
2798 WasmExportKind::PostReturn => name.push_str("_post"),
2799 WasmExportKind::Callback => todo!(
2800 "not yet supported: \
2801 async callback functions using standard name mangling"
2802 ),
2803 }
2804 name
2805 }
2806 WasmExport::ResourceDtor {
2807 interface,
2808 resource,
2809 } => {
2810 let name = self.types[resource].name.as_ref().unwrap();
2811 let interface = self.name_canonicalized_world_key(interface);
2812 format!("cm32p2|{interface}|{name}_dtor")
2813 }
2814 WasmExport::Memory => "cm32p2_memory".to_string(),
2815 WasmExport::Initialize => "cm32p2_initialize".to_string(),
2816 WasmExport::Realloc => "cm32p2_realloc".to_string(),
2817 },
2818 ManglingAndAbi::Legacy(abi) => match export {
2819 WasmExport::Func {
2820 interface,
2821 func,
2822 kind,
2823 } => {
2824 let mut name = abi.export_prefix().to_string();
2825 match kind {
2826 WasmExportKind::Normal => {}
2827 WasmExportKind::PostReturn => name.push_str("cabi_post_"),
2828 WasmExportKind::Callback => {
2829 assert!(matches!(abi, LiftLowerAbi::AsyncCallback));
2830 name = format!("[callback]{name}")
2831 }
2832 }
2833 if let Some(interface) = interface {
2834 let s = self.name_world_key(interface);
2835 name.push_str(&s);
2836 name.push_str("#");
2837 }
2838 name.push_str(&func.name);
2839 name
2840 }
2841 WasmExport::ResourceDtor {
2842 interface,
2843 resource,
2844 } => {
2845 let name = self.types[resource].name.as_ref().unwrap();
2846 let interface = self.name_world_key(interface);
2847 format!("{}{interface}#[dtor]{name}", abi.export_prefix())
2848 }
2849 WasmExport::Memory => "memory".to_string(),
2850 WasmExport::Initialize => "_initialize".to_string(),
2851 WasmExport::Realloc => "cabi_realloc".to_string(),
2852 },
2853 }
2854 }
2855
2856 pub fn generate_nominal_type_ids(&mut self, world_id: WorldId) {
2896 let mut seen = HashSet::new();
2897 let mut interface_keys_rewritten = HashSet::new();
2898 let mut maps = CloneMaps::default();
2899
2900 let world = &mut self.worlds[world_id];
2903 let mut imports = mem::take(&mut world.imports);
2904 let mut exports = mem::take(&mut world.exports);
2905
2906 log::trace!("nominalizing world imports");
2910 self.nominalize_world_items(
2911 &mut maps,
2912 world_id,
2913 &mut imports,
2914 &mut seen,
2915 &mut interface_keys_rewritten,
2916 );
2917 log::trace!("nominalizing world exports");
2918 self.nominalize_world_items(
2919 &mut maps,
2920 world_id,
2921 &mut exports,
2922 &mut seen,
2923 &mut interface_keys_rewritten,
2924 );
2925
2926 let world = &mut self.worlds[world_id];
2928 assert!(world.imports.is_empty());
2929 assert!(world.exports.is_empty());
2930 world.imports = imports;
2931 world.exports = exports;
2932
2933 #[cfg(debug_assertions)]
2934 self.assert_valid();
2935 }
2936
2937 fn nominalize_world_items(
2960 &mut self,
2961 maps: &mut CloneMaps,
2962 world: WorldId,
2963 items: &mut IndexMap<WorldKey, WorldItem>,
2964 seen: &mut HashSet<InterfaceId>,
2965 interface_keys_rewritten: &mut HashSet<InterfaceId>,
2966 ) {
2967 let mut order = items.iter().enumerate().collect::<Vec<_>>();
3065 order.sort_by_key(|(_, (key, item))| match (key, item) {
3066 (WorldKey::Name(_), WorldItem::Interface { .. }) => 1,
3067 _ => 0,
3068 });
3069 let mut to_rewrite = IndexMap::default();
3070 for (i, (key, item)) in order {
3071 let id = match item {
3072 WorldItem::Interface { id, .. } => *id,
3073
3074 WorldItem::Function(_) | WorldItem::Type { .. } => continue,
3077 };
3078
3079 let duplicated = !seen.insert(id);
3085 let any_dep_rewritten = self
3086 .interface_direct_deps(id)
3087 .any(|dep| interface_keys_rewritten.contains(&dep));
3088 if !(duplicated || any_dep_rewritten) {
3089 log::trace!("{} already nominal", self.name_world_key(key));
3090 continue;
3091 }
3092 log::trace!("{} getting rewritten nominal", self.name_world_key(key));
3093
3094 let is_name = matches!(key, WorldKey::Name(_));
3099 if !is_name {
3100 assert!(interface_keys_rewritten.insert(id));
3101 }
3102
3103 to_rewrite
3104 .entry(id)
3105 .or_insert(Vec::new())
3106 .push((i, is_name));
3107 }
3108
3109 for (id, mut list) in to_rewrite {
3140 list.sort_by_key(|(_, is_name)| if *is_name { 0 } else { 1 });
3141 for (i, is_name) in list {
3142 let prev_maps = if is_name { Some(maps.clone()) } else { None };
3143
3144 let mut cloner = clone::Cloner::new(
3145 self,
3146 maps,
3147 TypeOwner::World(world),
3148 TypeOwner::World(world),
3149 );
3150
3151 let mut new_id = id;
3152 cloner.new_package = cloner.resolve.interfaces[id].package;
3153 cloner.interface(&mut new_id);
3154 let (key, prev) = items.get_index_mut(i).unwrap();
3155 match prev {
3156 WorldItem::Interface { id, .. } => *id = new_id,
3157 _ => unreachable!(),
3158 }
3159
3160 match key {
3161 WorldKey::Interface(_) => {
3167 items.replace_index(i, WorldKey::Interface(new_id)).unwrap();
3168 }
3169
3170 WorldKey::Name(_) => {}
3173 }
3174
3175 if let Some(prev) = prev_maps {
3176 *maps = prev;
3177 }
3178 }
3179 }
3180 }
3181}
3182
3183#[derive(Debug)]
3185pub enum WasmImport<'a> {
3186 Func {
3188 interface: Option<&'a WorldKey>,
3193
3194 func: &'a Function,
3196 },
3197
3198 ResourceIntrinsic {
3200 interface: Option<&'a WorldKey>,
3202
3203 resource: TypeId,
3205
3206 intrinsic: ResourceIntrinsic,
3208 },
3209
3210 FutureIntrinsic {
3212 interface: Option<&'a WorldKey>,
3214
3215 func: &'a Function,
3217
3218 ty: Option<TypeId>,
3222
3223 intrinsic: FutureIntrinsic,
3225
3226 exported: bool,
3230
3231 async_: bool,
3235 },
3236
3237 StreamIntrinsic {
3239 interface: Option<&'a WorldKey>,
3241
3242 func: &'a Function,
3244
3245 ty: Option<TypeId>,
3249
3250 intrinsic: StreamIntrinsic,
3252
3253 exported: bool,
3257
3258 async_: bool,
3262 },
3263}
3264
3265#[derive(Debug)]
3268pub enum ResourceIntrinsic {
3269 ImportedDrop,
3270 ExportedDrop,
3271 ExportedNew,
3272 ExportedRep,
3273}
3274
3275#[derive(Debug)]
3278pub enum FutureIntrinsic {
3279 New,
3280 Read,
3281 Write,
3282 CancelRead,
3283 CancelWrite,
3284 DropReadable,
3285 DropWritable,
3286}
3287
3288#[derive(Debug)]
3291pub enum StreamIntrinsic {
3292 New,
3293 Read,
3294 Write,
3295 CancelRead,
3296 CancelWrite,
3297 DropReadable,
3298 DropWritable,
3299}
3300
3301#[derive(Debug)]
3304pub enum WasmExportKind {
3305 Normal,
3307
3308 PostReturn,
3310
3311 Callback,
3313}
3314
3315#[derive(Debug)]
3318pub enum WasmExport<'a> {
3319 Func {
3321 interface: Option<&'a WorldKey>,
3324
3325 func: &'a Function,
3327
3328 kind: WasmExportKind,
3330 },
3331
3332 ResourceDtor {
3334 interface: &'a WorldKey,
3336 resource: TypeId,
3338 },
3339
3340 Memory,
3342
3343 Initialize,
3345
3346 Realloc,
3348}
3349
3350#[derive(Default)]
3353pub struct Remap {
3354 pub types: Vec<Option<TypeId>>,
3355 pub interfaces: Vec<Option<InterfaceId>>,
3356 pub worlds: Vec<Option<WorldId>>,
3357 pub packages: Vec<PackageId>,
3358
3359 own_handles: HashMap<TypeId, TypeId>,
3369
3370 type_has_borrow: Vec<Option<bool>>,
3371}
3372
3373fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Span) -> ResolveResult<Id<T>> {
3374 match map.get(id.index()) {
3375 Some(Some(id)) => Ok(*id),
3376 Some(None) => {
3377 let msg = format!(
3378 "found a reference to a {desc} which is excluded \
3379 due to its feature not being activated"
3380 );
3381 Err(ResolveError::new_semantic(span, msg))
3382 }
3383 None => panic!("request to remap a {desc} that has not yet been registered"),
3384 }
3385}
3386
3387fn rename(original_name: &str, include_name: &IncludeName) -> Option<String> {
3388 if original_name == include_name.name {
3389 return Some(include_name.as_.to_string());
3390 }
3391 let (kind, rest) = original_name.split_once(']')?;
3392 match rest.split_once('.') {
3393 Some((name, rest)) if name == include_name.name => {
3394 Some(format!("{kind}]{}.{rest}", include_name.as_))
3395 }
3396 _ if rest == include_name.name => Some(format!("{kind}]{}", include_name.as_)),
3397 _ => None,
3398 }
3399}
3400
3401impl Remap {
3402 pub fn map_type(&self, id: TypeId, span: Span) -> ResolveResult<TypeId> {
3403 apply_map(&self.types, id, "type", span)
3404 }
3405
3406 pub fn map_interface(&self, id: InterfaceId, span: Span) -> ResolveResult<InterfaceId> {
3407 apply_map(&self.interfaces, id, "interface", span)
3408 }
3409
3410 pub fn map_world(&self, id: WorldId, span: Span) -> ResolveResult<WorldId> {
3411 apply_map(&self.worlds, id, "world", span)
3412 }
3413
3414 pub fn map_world_for_type(&self, id: WorldId, span: Span) -> ResolveResult<WorldId> {
3415 self.map_world(id, span).map_err(|e| {
3416 ResolveError::new_semantic(
3417 span,
3418 format!("{e}; this type is not gated by a feature but its world is"),
3419 )
3420 })
3421 }
3422
3423 pub fn map_interface_for_type(
3424 &self,
3425 id: InterfaceId,
3426 span: Span,
3427 ) -> ResolveResult<InterfaceId> {
3428 self.map_interface(id, span).map_err(|e| {
3429 ResolveError::new_semantic(
3430 span,
3431 format!("{e}; this type is not gated by a feature but its interface is"),
3432 )
3433 })
3434 }
3435
3436 fn append(
3437 &mut self,
3438 resolve: &mut Resolve,
3439 unresolved: UnresolvedPackage,
3440 ) -> ResolveResult<PackageId> {
3441 let pkgid = resolve.packages.alloc(Package {
3442 name: unresolved.name.clone(),
3443 docs: unresolved.docs.clone(),
3444 interfaces: Default::default(),
3445 worlds: Default::default(),
3446 });
3447 assert!(
3448 !resolve.package_names.contains_key(&unresolved.name),
3449 "attempting to re-add package `{}` when it's already present in this `Resolve`",
3450 unresolved.name,
3451 );
3452 resolve.package_names.insert(unresolved.name.clone(), pkgid);
3453 self.process_foreign_deps(resolve, pkgid, &unresolved)?;
3454
3455 let foreign_types = self.types.len();
3456 let foreign_interfaces = self.interfaces.len();
3457 let foreign_worlds = self.worlds.len();
3458
3459 for (id, mut ty) in unresolved.types.into_iter().skip(foreign_types) {
3465 let span = ty.span;
3466 if !resolve.include_stability(&ty.stability, &pkgid, span)? {
3467 self.types.push(None);
3468 continue;
3469 }
3470
3471 self.update_typedef(resolve, &mut ty, span)?;
3472 let new_id = resolve.types.alloc(ty);
3473 assert_eq!(self.types.len(), id.index());
3474
3475 let new_id = match resolve.types[new_id] {
3476 TypeDef {
3481 name: None,
3482 owner: TypeOwner::None,
3483 kind: TypeDefKind::Handle(Handle::Own(id)),
3484 docs: _,
3485 stability: _,
3486 span: _,
3487 } => *self.own_handles.entry(id).or_insert(new_id),
3488
3489 _ => new_id,
3492 };
3493 self.types.push(Some(new_id));
3494 }
3495
3496 for (id, mut iface) in unresolved.interfaces.into_iter().skip(foreign_interfaces) {
3499 let span = iface.span;
3500 if !resolve.include_stability(&iface.stability, &pkgid, span)? {
3501 self.interfaces.push(None);
3502 continue;
3503 }
3504 assert!(iface.package.is_none());
3505 iface.package = Some(pkgid);
3506 self.update_interface(resolve, &mut iface)?;
3507 let new_id = resolve.interfaces.alloc(iface);
3508 assert_eq!(self.interfaces.len(), id.index());
3509 self.interfaces.push(Some(new_id));
3510 }
3511
3512 for id in self.types.iter().skip(foreign_types) {
3515 let id = match id {
3516 Some(id) => *id,
3517 None => continue,
3518 };
3519 let span = resolve.types[id].span;
3520 match &mut resolve.types[id].owner {
3521 TypeOwner::Interface(iface_id) => {
3522 *iface_id = self.map_interface_for_type(*iface_id, span)?;
3523 }
3524 TypeOwner::World(_) | TypeOwner::None => {}
3525 }
3526 }
3527
3528 for (id, mut world) in unresolved.worlds.into_iter().skip(foreign_worlds) {
3536 let world_span = world.span;
3537 if !resolve.include_stability(&world.stability, &pkgid, world_span)? {
3538 self.worlds.push(None);
3539 continue;
3540 }
3541 self.update_world(&mut world, resolve, &pkgid)?;
3542
3543 let new_id = resolve.worlds.alloc(world);
3544 assert_eq!(self.worlds.len(), id.index());
3545 self.worlds.push(Some(new_id));
3546 }
3547
3548 for id in self.types.iter().skip(foreign_types) {
3550 let id = match id {
3551 Some(id) => *id,
3552 None => continue,
3553 };
3554 let span = resolve.types[id].span;
3555 match &mut resolve.types[id].owner {
3556 TypeOwner::World(world_id) => {
3557 *world_id = self.map_world_for_type(*world_id, span)?;
3558 }
3559 TypeOwner::Interface(_) | TypeOwner::None => {}
3560 }
3561 }
3562
3563 for id in self.worlds.iter().skip(foreign_worlds) {
3580 let Some(id) = *id else {
3581 continue;
3582 };
3583 self.process_world_includes(id, resolve, &pkgid)?;
3584
3585 let world_span = resolve.worlds[id].span;
3586 resolve.elaborate_world(id, world_span)?;
3587 }
3588
3589 for id in self.interfaces.iter().skip(foreign_interfaces) {
3591 let id = match id {
3592 Some(id) => *id,
3593 None => continue,
3594 };
3595 let iface = &mut resolve.interfaces[id];
3596 iface.package = Some(pkgid);
3597 if let Some(name) = &iface.name {
3598 let prev = resolve.packages[pkgid].interfaces.insert(name.clone(), id);
3599 assert!(prev.is_none());
3600 }
3601 }
3602 for id in self.worlds.iter().skip(foreign_worlds) {
3603 let id = match id {
3604 Some(id) => *id,
3605 None => continue,
3606 };
3607 let world = &mut resolve.worlds[id];
3608 world.package = Some(pkgid);
3609 let prev = resolve.packages[pkgid]
3610 .worlds
3611 .insert(world.name.clone(), id);
3612 assert!(prev.is_none());
3613 }
3614 Ok(pkgid)
3615 }
3616
3617 fn process_foreign_deps(
3618 &mut self,
3619 resolve: &mut Resolve,
3620 pkgid: PackageId,
3621 unresolved: &UnresolvedPackage,
3622 ) -> ResolveResult<()> {
3623 let mut world_to_package = HashMap::new();
3626 let mut interface_to_package = HashMap::new();
3627 for (i, (pkg_name, worlds_or_ifaces)) in unresolved.foreign_deps.iter().enumerate() {
3628 for (name, (item, stabilities)) in worlds_or_ifaces {
3629 match item {
3630 AstItem::Interface(unresolved_interface_id) => {
3631 let prev = interface_to_package.insert(
3632 *unresolved_interface_id,
3633 (pkg_name, name, unresolved.foreign_dep_spans[i], stabilities),
3634 );
3635 assert!(prev.is_none());
3636 }
3637 AstItem::World(unresolved_world_id) => {
3638 let prev = world_to_package.insert(
3639 *unresolved_world_id,
3640 (pkg_name, name, unresolved.foreign_dep_spans[i], stabilities),
3641 );
3642 assert!(prev.is_none());
3643 }
3644 }
3645 }
3646 }
3647
3648 self.process_foreign_interfaces(unresolved, &interface_to_package, resolve, &pkgid)?;
3652
3653 self.process_foreign_worlds(unresolved, &world_to_package, resolve, &pkgid)?;
3657
3658 self.process_foreign_types(unresolved, pkgid, resolve)?;
3661
3662 for (id, span) in unresolved.required_resource_types.iter() {
3663 let Ok(mut id) = self.map_type(*id, *span) else {
3668 continue;
3669 };
3670 loop {
3671 match resolve.types[id].kind {
3672 TypeDefKind::Type(Type::Id(i)) => id = i,
3673 TypeDefKind::Resource => break,
3674 _ => {
3675 return Err(ResolveError::new_semantic(
3676 *span,
3677 "type used in a handle must be a resource",
3678 ));
3679 }
3680 }
3681 }
3682 }
3683
3684 #[cfg(debug_assertions)]
3685 resolve.assert_valid();
3686
3687 Ok(())
3688 }
3689
3690 fn process_foreign_interfaces(
3691 &mut self,
3692 unresolved: &UnresolvedPackage,
3693 interface_to_package: &HashMap<InterfaceId, (&PackageName, &String, Span, &Vec<Stability>)>,
3694 resolve: &mut Resolve,
3695 parent_pkg_id: &PackageId,
3696 ) -> ResolveResult<()> {
3697 for (unresolved_iface_id, unresolved_iface) in unresolved.interfaces.iter() {
3698 let (pkg_name, interface, span, stabilities) =
3699 match interface_to_package.get(&unresolved_iface_id) {
3700 Some(items) => *items,
3701 None => break,
3705 };
3706
3707 let pkgid = resolve
3708 .package_names
3709 .get(pkg_name)
3710 .copied()
3711 .ok_or_else(|| {
3712 ResolveError::from(ResolveErrorKind::PackageNotFound {
3713 span,
3714 requested: pkg_name.clone(),
3715 known: resolve.package_names.keys().cloned().collect(),
3716 })
3717 })?;
3718
3719 assert!(unresolved_iface.functions.is_empty());
3721
3722 let pkg = &resolve.packages[pkgid];
3723 let iface_span = unresolved_iface.span;
3724
3725 let mut enabled = false;
3726 for stability in stabilities {
3727 if resolve.include_stability(stability, parent_pkg_id, iface_span)? {
3728 enabled = true;
3729 break;
3730 }
3731 }
3732
3733 if !enabled {
3734 self.interfaces.push(None);
3735 continue;
3736 }
3737
3738 let iface_id = pkg.interfaces.get(interface).copied().ok_or_else(|| {
3739 ResolveError::new_semantic(iface_span, "interface not found in package")
3740 })?;
3741 assert_eq!(self.interfaces.len(), unresolved_iface_id.index());
3742 self.interfaces.push(Some(iface_id));
3743 }
3744 for (id, _) in unresolved.interfaces.iter().skip(self.interfaces.len()) {
3745 assert!(
3746 interface_to_package.get(&id).is_none(),
3747 "found foreign interface after local interface"
3748 );
3749 }
3750 Ok(())
3751 }
3752
3753 fn process_foreign_worlds(
3754 &mut self,
3755 unresolved: &UnresolvedPackage,
3756 world_to_package: &HashMap<WorldId, (&PackageName, &String, Span, &Vec<Stability>)>,
3757 resolve: &mut Resolve,
3758 parent_pkg_id: &PackageId,
3759 ) -> ResolveResult<()> {
3760 for (unresolved_world_id, unresolved_world) in unresolved.worlds.iter() {
3761 let (pkg_name, world, span, stabilities) =
3762 match world_to_package.get(&unresolved_world_id) {
3763 Some(items) => *items,
3764 None => break,
3767 };
3768
3769 let pkgid = resolve
3770 .package_names
3771 .get(pkg_name)
3772 .copied()
3773 .ok_or_else(|| {
3774 ResolveError::from(ResolveErrorKind::PackageNotFound {
3775 span,
3776 requested: pkg_name.clone(),
3777 known: resolve.package_names.keys().cloned().collect(),
3778 })
3779 })?;
3780 let pkg = &resolve.packages[pkgid];
3781 let world_span = unresolved_world.span;
3782
3783 let mut enabled = false;
3784 for stability in stabilities {
3785 if resolve.include_stability(stability, parent_pkg_id, world_span)? {
3786 enabled = true;
3787 break;
3788 }
3789 }
3790
3791 if !enabled {
3792 self.worlds.push(None);
3793 continue;
3794 }
3795
3796 let world_id = pkg.worlds.get(world).copied().ok_or_else(|| {
3797 ResolveError::new_semantic(world_span, "world not found in package")
3798 })?;
3799 assert_eq!(self.worlds.len(), unresolved_world_id.index());
3800 self.worlds.push(Some(world_id));
3801 }
3802 for (id, _) in unresolved.worlds.iter().skip(self.worlds.len()) {
3803 assert!(
3804 world_to_package.get(&id).is_none(),
3805 "found foreign world after local world"
3806 );
3807 }
3808 Ok(())
3809 }
3810
3811 fn process_foreign_types(
3812 &mut self,
3813 unresolved: &UnresolvedPackage,
3814 pkgid: PackageId,
3815 resolve: &mut Resolve,
3816 ) -> ResolveResult<()> {
3817 for (unresolved_type_id, unresolved_ty) in unresolved.types.iter() {
3818 match unresolved_ty.kind {
3822 TypeDefKind::Unknown => {}
3823 _ => break,
3824 }
3825
3826 let span = unresolved_ty.span;
3827 if !resolve.include_stability(&unresolved_ty.stability, &pkgid, span)? {
3828 self.types.push(None);
3829 continue;
3830 }
3831
3832 let unresolved_iface_id = match unresolved_ty.owner {
3833 TypeOwner::Interface(id) => id,
3834 _ => unreachable!(),
3835 };
3836 let iface_id = self.map_interface(unresolved_iface_id, Default::default())?;
3837 let name = unresolved_ty.name.as_ref().unwrap();
3838 let span = unresolved.unknown_type_spans[unresolved_type_id.index()];
3839 let type_id = *resolve.interfaces[iface_id]
3840 .types
3841 .get(name)
3842 .ok_or_else(|| {
3843 ResolveError::new_semantic(
3844 span,
3845 format!("type `{name}` not defined in interface"),
3846 )
3847 })?;
3848 assert_eq!(self.types.len(), unresolved_type_id.index());
3849 self.types.push(Some(type_id));
3850 }
3851 for (_, ty) in unresolved.types.iter().skip(self.types.len()) {
3852 if let TypeDefKind::Unknown = ty.kind {
3853 panic!("unknown type after defined type");
3854 }
3855 }
3856 Ok(())
3857 }
3858
3859 fn update_typedef(
3860 &mut self,
3861 resolve: &mut Resolve,
3862 ty: &mut TypeDef,
3863 span: Span,
3864 ) -> ResolveResult<()> {
3865 use crate::TypeDefKind::*;
3868 match &mut ty.kind {
3869 Handle(handle) => match handle {
3870 crate::Handle::Own(ty) | crate::Handle::Borrow(ty) => {
3871 self.update_type_id(ty, span)?
3872 }
3873 },
3874 Resource => {}
3875 Record(r) => {
3876 for field in r.fields.iter_mut() {
3877 self.update_ty(resolve, &mut field.ty, field.span)?
3878 }
3879 }
3880 Tuple(t) => {
3881 for ty in t.types.iter_mut() {
3882 self.update_ty(resolve, ty, span)?;
3883 }
3884 }
3885 Variant(v) => {
3886 for case in v.cases.iter_mut() {
3887 if let Some(t) = &mut case.ty {
3888 self.update_ty(resolve, t, span)?;
3889 }
3890 }
3891 }
3892 Option(t)
3893 | List(t, ..)
3894 | FixedLengthList(t, ..)
3895 | Future(Some(t))
3896 | Stream(Some(t)) => self.update_ty(resolve, t, span)?,
3897 Map(k, v) => {
3898 self.update_ty(resolve, k, span)?;
3899 self.update_ty(resolve, v, span)?;
3900 }
3901 Result(r) => {
3902 if let Some(ty) = &mut r.ok {
3903 self.update_ty(resolve, ty, span)?;
3904 }
3905 if let Some(ty) = &mut r.err {
3906 self.update_ty(resolve, ty, span)?;
3907 }
3908 }
3909
3910 Type(crate::Type::Id(id)) => self.update_type_id(id, span)?,
3915 Type(_) => {}
3916
3917 Flags(_) | Enum(_) | Future(None) | Stream(None) => {}
3919
3920 Unknown => unreachable!(),
3921 }
3922
3923 Ok(())
3924 }
3925
3926 fn update_ty(&mut self, resolve: &mut Resolve, ty: &mut Type, span: Span) -> ResolveResult<()> {
3927 let id = match ty {
3928 Type::Id(id) => id,
3929 _ => return Ok(()),
3930 };
3931 self.update_type_id(id, span)?;
3932
3933 let mut cur = *id;
3938 let points_to_resource = loop {
3939 match resolve.types[cur].kind {
3940 TypeDefKind::Type(Type::Id(id)) => cur = id,
3941 TypeDefKind::Resource => break true,
3942 _ => break false,
3943 }
3944 };
3945
3946 if points_to_resource {
3947 *id = *self.own_handles.entry(*id).or_insert_with(|| {
3948 resolve.types.alloc(TypeDef {
3949 name: None,
3950 owner: TypeOwner::None,
3951 kind: TypeDefKind::Handle(Handle::Own(*id)),
3952 docs: Default::default(),
3953 stability: Default::default(),
3954 span: Default::default(),
3955 })
3956 });
3957 }
3958 Ok(())
3959 }
3960
3961 fn update_type_id(&self, id: &mut TypeId, span: Span) -> ResolveResult<()> {
3962 *id = self.map_type(*id, span)?;
3963 Ok(())
3964 }
3965
3966 fn update_interface(
3967 &mut self,
3968 resolve: &mut Resolve,
3969 iface: &mut Interface,
3970 ) -> ResolveResult<()> {
3971 iface.types.retain(|_, ty| self.types[ty.index()].is_some());
3972 let iface_pkg_id = iface.package.as_ref().unwrap_or_else(|| {
3973 panic!(
3974 "unexpectedly missing package on interface [{}]",
3975 iface
3976 .name
3977 .as_ref()
3978 .map(String::as_str)
3979 .unwrap_or("<unknown>"),
3980 )
3981 });
3982
3983 for (_name, ty) in iface.types.iter_mut() {
3986 self.update_type_id(ty, iface.span)?;
3987 }
3988 for (_, func) in iface.functions.iter_mut() {
3989 let span = func.span;
3990 if !resolve.include_stability(&func.stability, iface_pkg_id, span)? {
3991 continue;
3992 }
3993 self.update_function(resolve, func, span)?
3994 }
3995
3996 for (name, func) in mem::take(&mut iface.functions) {
3999 if resolve.include_stability(&func.stability, iface_pkg_id, func.span)? {
4000 iface.functions.insert(name, func);
4001 }
4002 }
4003
4004 Ok(())
4005 }
4006
4007 fn update_function(
4008 &mut self,
4009 resolve: &mut Resolve,
4010 func: &mut Function,
4011 span: Span,
4012 ) -> ResolveResult<()> {
4013 if let Some(id) = func.kind.resource_mut() {
4014 self.update_type_id(id, span)?;
4015 }
4016 for param in func.params.iter_mut() {
4017 self.update_ty(resolve, &mut param.ty, span)?;
4018 }
4019 if let Some(ty) = &mut func.result {
4020 self.update_ty(resolve, ty, span)?;
4021 }
4022
4023 if let Some(ty) = &func.result {
4024 if self.type_has_borrow(resolve, ty) {
4025 return Err(ResolveError::new_semantic(
4026 span,
4027 format!(
4028 "function `{}` returns a type which contains a `borrow<T>` which is not supported",
4029 func.name,
4030 ),
4031 ));
4032 }
4033 }
4034
4035 Ok(())
4036 }
4037
4038 fn update_world(
4039 &mut self,
4040 world: &mut World,
4041 resolve: &mut Resolve,
4042 pkg_id: &PackageId,
4043 ) -> ResolveResult<()> {
4044 let imports = mem::take(&mut world.imports).into_iter().map(|p| (p, true));
4048 let exports = mem::take(&mut world.exports)
4049 .into_iter()
4050 .map(|p| (p, false));
4051 for ((mut name, mut item), import) in imports.chain(exports) {
4052 let span = item.span();
4053 if let WorldItem::Type { id, .. } = &mut item {
4056 *id = self.map_type(*id, span)?;
4057 }
4058 let stability = item.stability(resolve);
4059 if !resolve.include_stability(stability, pkg_id, span)? {
4060 continue;
4061 }
4062 self.update_world_key(&mut name, span)?;
4063 match &mut item {
4064 WorldItem::Interface { id, .. } => {
4065 *id = self.map_interface(*id, span)?;
4066 }
4067 WorldItem::Function(f) => {
4068 self.update_function(resolve, f, span)?;
4069 }
4070 WorldItem::Type { .. } => {
4071 }
4073 }
4074
4075 let dst = if import {
4076 &mut world.imports
4077 } else {
4078 &mut world.exports
4079 };
4080 let prev = dst.insert(name, item);
4081 assert!(prev.is_none());
4082 }
4083
4084 Ok(())
4085 }
4086
4087 fn process_world_includes(
4088 &self,
4089 id: WorldId,
4090 resolve: &mut Resolve,
4091 pkg_id: &PackageId,
4092 ) -> ResolveResult<()> {
4093 let world = &mut resolve.worlds[id];
4094 let includes = mem::take(&mut world.includes);
4097 for include in includes {
4098 if !resolve.include_stability(&include.stability, pkg_id, include.span)? {
4099 continue;
4100 }
4101 self.resolve_include(
4102 id,
4103 include.id,
4104 &include.names,
4105 include.span,
4106 pkg_id,
4107 resolve,
4108 )?;
4109 }
4110
4111 Self::validate_world_case_insensitive_names(resolve, id)?;
4113
4114 Ok(())
4115 }
4116
4117 fn validate_world_case_insensitive_names(
4121 resolve: &Resolve,
4122 world_id: WorldId,
4123 ) -> ResolveResult<()> {
4124 let world = &resolve.worlds[world_id];
4125
4126 let validate_names =
4128 |items: &IndexMap<WorldKey, WorldItem>, item_type: &str| -> ResolveResult<()> {
4129 let mut seen_lowercase: HashMap<String, String> = HashMap::new();
4130
4131 for key in items.keys() {
4132 if let WorldKey::Name(name) = key {
4134 let lowercase_name = name.to_lowercase();
4135
4136 if let Some(existing_name) = seen_lowercase.get(&lowercase_name) {
4137 if existing_name != name {
4140 return Err(ResolveError::new_semantic(
4144 Span::default(),
4145 format!(
4146 "{item_type} `{name}` in world `{}` conflicts with \
4147 {item_type} `{existing_name}` \
4148 (kebab-case identifiers are case-insensitive)",
4149 world.name,
4150 ),
4151 ));
4152 }
4153 }
4154
4155 seen_lowercase.insert(lowercase_name, name.clone());
4156 }
4157 }
4158
4159 Ok(())
4160 };
4161
4162 validate_names(&world.imports, "import")?;
4163 validate_names(&world.exports, "export")?;
4164
4165 Ok(())
4166 }
4167
4168 fn update_world_key(&self, key: &mut WorldKey, span: Span) -> ResolveResult<()> {
4169 match key {
4170 WorldKey::Name(_) => {}
4171 WorldKey::Interface(id) => {
4172 *id = self.map_interface(*id, span)?;
4173 }
4174 }
4175 Ok(())
4176 }
4177
4178 fn resolve_include(
4179 &self,
4180 id: WorldId,
4181 include_world_id_orig: WorldId,
4182 names: &[IncludeName],
4183 span: Span,
4184 pkg_id: &PackageId,
4185 resolve: &mut Resolve,
4186 ) -> ResolveResult<()> {
4187 let world = &resolve.worlds[id];
4188 let include_world_id = self.map_world(include_world_id_orig, span)?;
4189 let include_world = resolve.worlds[include_world_id].clone();
4190 let mut names_ = names.to_owned();
4191 let is_external_include = world.package != include_world.package;
4192
4193 for import in include_world.imports.iter() {
4195 self.remove_matching_name(import, &mut names_);
4196 }
4197 for export in include_world.exports.iter() {
4198 self.remove_matching_name(export, &mut names_);
4199 }
4200 if !names_.is_empty() {
4201 return Err(ResolveError::new_semantic(
4202 span,
4203 format!(
4204 "no import or export kebab-name `{}`. Note that an ID does not support renaming",
4205 names_[0].name
4206 ),
4207 ));
4208 }
4209
4210 let mut maps = Default::default();
4211 let mut cloner = clone::Cloner::new(
4212 resolve,
4213 &mut maps,
4214 TypeOwner::World(if is_external_include {
4215 include_world_id
4216 } else {
4217 include_world_id
4218 }),
4220 TypeOwner::World(id),
4221 );
4222 cloner.new_package = Some(*pkg_id);
4223
4224 for import in include_world.imports.iter() {
4226 self.resolve_include_item(
4227 &mut cloner,
4228 names,
4229 |resolve| &mut resolve.worlds[id].imports,
4230 import,
4231 span,
4232 "import",
4233 is_external_include,
4234 )?;
4235 }
4236
4237 for export in include_world.exports.iter() {
4238 self.resolve_include_item(
4239 &mut cloner,
4240 names,
4241 |resolve| &mut resolve.worlds[id].exports,
4242 export,
4243 span,
4244 "export",
4245 is_external_include,
4246 )?;
4247 }
4248 Ok(())
4249 }
4250
4251 fn resolve_include_item(
4252 &self,
4253 cloner: &mut clone::Cloner<'_>,
4254 names: &[IncludeName],
4255 get_items: impl Fn(&mut Resolve) -> &mut IndexMap<WorldKey, WorldItem>,
4256 item: (&WorldKey, &WorldItem),
4257 span: Span,
4258 item_type: &str,
4259 is_external_include: bool,
4260 ) -> ResolveResult<()> {
4261 match item.0 {
4262 WorldKey::Name(n) => {
4263 let n = names
4264 .into_iter()
4265 .find_map(|include_name| rename(n, include_name))
4266 .unwrap_or(n.clone());
4267
4268 let mut new_item = item.1.clone();
4274 let key = WorldKey::Name(n.clone());
4275 cloner.world_item(&key, &mut new_item);
4276 match &mut new_item {
4277 WorldItem::Function(f) => f.name = n.clone(),
4278 WorldItem::Type { id, .. } => cloner.resolve.types[*id].name = Some(n.clone()),
4279 WorldItem::Interface { .. } => {}
4280 }
4281
4282 let prev = get_items(cloner.resolve).insert(key, new_item);
4283 if prev.is_some() {
4284 return Err(ResolveError::from(ResolveErrorKind::ItemShadowing {
4285 span,
4286 item_type: item_type.to_owned(),
4287 name: n,
4288 }));
4289 }
4290 }
4291 key @ WorldKey::Interface(_) => {
4292 let prev = get_items(cloner.resolve)
4293 .entry(key.clone())
4294 .or_insert(item.1.clone());
4295 match (&item.1, prev) {
4296 (
4297 WorldItem::Interface {
4298 id: aid,
4299 stability: astability,
4300 span: aspan,
4301 ..
4302 },
4303 WorldItem::Interface {
4304 id: bid,
4305 stability: bstability,
4306 ..
4307 },
4308 ) => {
4309 assert_eq!(*aid, *bid);
4310 merge_include_stability(
4311 astability,
4312 bstability,
4313 is_external_include,
4314 *aspan,
4315 )?;
4316 }
4317 (WorldItem::Interface { .. }, _) => unreachable!(),
4318 (WorldItem::Function(_), _) => unreachable!(),
4319 (WorldItem::Type { .. }, _) => unreachable!(),
4320 }
4321 }
4322 };
4323
4324 Ok(())
4325 }
4326
4327 fn remove_matching_name(&self, item: (&WorldKey, &WorldItem), names: &mut Vec<IncludeName>) {
4328 match item.0 {
4329 WorldKey::Name(n) => {
4330 names.retain(|name| rename(n, name).is_none());
4331 }
4332 _ => {}
4333 }
4334 }
4335
4336 fn type_has_borrow(&mut self, resolve: &Resolve, ty: &Type) -> bool {
4337 let id = match ty {
4338 Type::Id(id) => *id,
4339 _ => return false,
4340 };
4341
4342 if let Some(Some(has_borrow)) = self.type_has_borrow.get(id.index()) {
4343 return *has_borrow;
4344 }
4345
4346 let result = self.typedef_has_borrow(resolve, &resolve.types[id]);
4347 if self.type_has_borrow.len() <= id.index() {
4348 self.type_has_borrow.resize(id.index() + 1, None);
4349 }
4350 self.type_has_borrow[id.index()] = Some(result);
4351 result
4352 }
4353
4354 fn typedef_has_borrow(&mut self, resolve: &Resolve, ty: &TypeDef) -> bool {
4355 match &ty.kind {
4356 TypeDefKind::Type(t) => self.type_has_borrow(resolve, t),
4357 TypeDefKind::Variant(v) => v
4358 .cases
4359 .iter()
4360 .filter_map(|case| case.ty.as_ref())
4361 .any(|ty| self.type_has_borrow(resolve, ty)),
4362 TypeDefKind::Handle(Handle::Borrow(_)) => true,
4363 TypeDefKind::Handle(Handle::Own(_)) => false,
4364 TypeDefKind::Resource => false,
4365 TypeDefKind::Record(r) => r
4366 .fields
4367 .iter()
4368 .any(|case| self.type_has_borrow(resolve, &case.ty)),
4369 TypeDefKind::Flags(_) => false,
4370 TypeDefKind::Tuple(t) => t.types.iter().any(|t| self.type_has_borrow(resolve, t)),
4371 TypeDefKind::Enum(_) => false,
4372 TypeDefKind::List(ty)
4373 | TypeDefKind::FixedLengthList(ty, ..)
4374 | TypeDefKind::Future(Some(ty))
4375 | TypeDefKind::Stream(Some(ty))
4376 | TypeDefKind::Option(ty) => self.type_has_borrow(resolve, ty),
4377 TypeDefKind::Map(k, v) => {
4378 self.type_has_borrow(resolve, k) || self.type_has_borrow(resolve, v)
4379 }
4380 TypeDefKind::Result(r) => [&r.ok, &r.err]
4381 .iter()
4382 .filter_map(|t| t.as_ref())
4383 .any(|t| self.type_has_borrow(resolve, t)),
4384 TypeDefKind::Future(None) | TypeDefKind::Stream(None) => false,
4385 TypeDefKind::Unknown => unreachable!(),
4386 }
4387 }
4388}
4389
4390struct MergeMap<'a> {
4391 package_map: HashMap<PackageId, PackageId>,
4394
4395 interface_map: HashMap<InterfaceId, InterfaceId>,
4398
4399 type_map: HashMap<TypeId, TypeId>,
4402
4403 world_map: HashMap<WorldId, WorldId>,
4406
4407 interfaces_to_add: Vec<(String, PackageId, InterfaceId)>,
4415 worlds_to_add: Vec<(String, PackageId, WorldId)>,
4416
4417 from: &'a Resolve,
4419
4420 into: &'a Resolve,
4422}
4423
4424impl<'a> MergeMap<'a> {
4425 fn new(from: &'a Resolve, into: &'a Resolve) -> MergeMap<'a> {
4426 MergeMap {
4427 package_map: Default::default(),
4428 interface_map: Default::default(),
4429 type_map: Default::default(),
4430 world_map: Default::default(),
4431 interfaces_to_add: Default::default(),
4432 worlds_to_add: Default::default(),
4433 from,
4434 into,
4435 }
4436 }
4437
4438 fn build(&mut self) -> anyhow::Result<()> {
4439 for from_id in self.from.topological_packages() {
4440 let from = &self.from.packages[from_id];
4441 let into_id = match self.into.package_names.get(&from.name) {
4442 Some(id) => *id,
4443
4444 None => {
4447 log::trace!("adding unique package {}", from.name);
4448 continue;
4449 }
4450 };
4451 log::trace!("merging duplicate package {}", from.name);
4452
4453 self.build_package(from_id, into_id).with_context(|| {
4454 format!("failed to merge package `{}` into existing copy", from.name)
4455 })?;
4456 }
4457
4458 Ok(())
4459 }
4460
4461 fn build_package(&mut self, from_id: PackageId, into_id: PackageId) -> anyhow::Result<()> {
4462 let prev = self.package_map.insert(from_id, into_id);
4463 assert!(prev.is_none());
4464
4465 let from = &self.from.packages[from_id];
4466 let into = &self.into.packages[into_id];
4467
4468 for (name, from_interface_id) in from.interfaces.iter() {
4472 let into_interface_id = match into.interfaces.get(name) {
4473 Some(id) => *id,
4474 None => {
4475 log::trace!("adding unique interface {name}");
4476 self.interfaces_to_add
4477 .push((name.clone(), into_id, *from_interface_id));
4478 continue;
4479 }
4480 };
4481
4482 log::trace!("merging duplicate interfaces {name}");
4483 self.build_interface(*from_interface_id, into_interface_id)
4484 .with_context(|| format!("failed to merge interface `{name}`"))?;
4485 }
4486
4487 for (name, from_world_id) in from.worlds.iter() {
4488 let into_world_id = match into.worlds.get(name) {
4489 Some(id) => *id,
4490 None => {
4491 log::trace!("adding unique world {name}");
4492 self.worlds_to_add
4493 .push((name.clone(), into_id, *from_world_id));
4494 continue;
4495 }
4496 };
4497
4498 log::trace!("merging duplicate worlds {name}");
4499 self.build_world(*from_world_id, into_world_id)
4500 .with_context(|| format!("failed to merge world `{name}`"))?;
4501 }
4502
4503 Ok(())
4504 }
4505
4506 fn build_interface(
4507 &mut self,
4508 from_id: InterfaceId,
4509 into_id: InterfaceId,
4510 ) -> anyhow::Result<()> {
4511 let prev = self.interface_map.insert(from_id, into_id);
4512 assert!(prev.is_none());
4513
4514 let from_interface = &self.from.interfaces[from_id];
4515 let into_interface = &self.into.interfaces[into_id];
4516
4517 for (name, from_type_id) in from_interface.types.iter() {
4525 let into_type_id = match into_interface.types.get(name) {
4526 Some(id) => *id,
4527 None => continue,
4530 };
4531 let prev = self.type_map.insert(*from_type_id, into_type_id);
4532 assert!(prev.is_none());
4533
4534 self.build_type_id(*from_type_id, into_type_id)
4535 .with_context(|| format!("mismatch in type `{name}`"))?;
4536 }
4537
4538 for (name, from_func) in from_interface.functions.iter() {
4539 let into_func = match into_interface.functions.get(name) {
4540 Some(func) => func,
4541 None => continue,
4544 };
4545 self.build_function(from_func, into_func)
4546 .with_context(|| format!("mismatch in function `{name}`"))?;
4547 }
4548
4549 Ok(())
4550 }
4551
4552 fn build_type_id(&mut self, from_id: TypeId, into_id: TypeId) -> anyhow::Result<()> {
4553 let _ = from_id;
4557 let _ = into_id;
4558 Ok(())
4559 }
4560
4561 fn build_type(&mut self, from_ty: &Type, into_ty: &Type) -> anyhow::Result<()> {
4562 match (from_ty, into_ty) {
4563 (Type::Id(from), Type::Id(into)) => {
4564 self.build_type_id(*from, *into)?;
4565 }
4566 (from, into) if from != into => bail!("different kinds of types"),
4567 _ => {}
4568 }
4569 Ok(())
4570 }
4571
4572 fn build_function(&mut self, from_func: &Function, into_func: &Function) -> anyhow::Result<()> {
4573 if from_func.name != into_func.name {
4574 bail!(
4575 "different function names `{}` and `{}`",
4576 from_func.name,
4577 into_func.name
4578 );
4579 }
4580 match (&from_func.kind, &into_func.kind) {
4581 (FunctionKind::Freestanding, FunctionKind::Freestanding) => {}
4582 (FunctionKind::AsyncFreestanding, FunctionKind::AsyncFreestanding) => {}
4583
4584 (FunctionKind::Method(from), FunctionKind::Method(into))
4585 | (FunctionKind::Static(from), FunctionKind::Static(into))
4586 | (FunctionKind::AsyncMethod(from), FunctionKind::AsyncMethod(into))
4587 | (FunctionKind::AsyncStatic(from), FunctionKind::AsyncStatic(into))
4588 | (FunctionKind::Constructor(from), FunctionKind::Constructor(into)) => {
4589 self.build_type_id(*from, *into)
4590 .context("different function kind types")?;
4591 }
4592
4593 (FunctionKind::Method(_), _)
4594 | (FunctionKind::Constructor(_), _)
4595 | (FunctionKind::Static(_), _)
4596 | (FunctionKind::Freestanding, _)
4597 | (FunctionKind::AsyncFreestanding, _)
4598 | (FunctionKind::AsyncMethod(_), _)
4599 | (FunctionKind::AsyncStatic(_), _) => {
4600 bail!("different function kind types")
4601 }
4602 }
4603
4604 if from_func.params.len() != into_func.params.len() {
4605 bail!("different number of function parameters");
4606 }
4607 for (from_param, into_param) in from_func.params.iter().zip(&into_func.params) {
4608 if from_param.name != into_param.name {
4609 bail!(
4610 "different function parameter names: {} != {}",
4611 from_param.name,
4612 into_param.name
4613 );
4614 }
4615 self.build_type(&from_param.ty, &into_param.ty)
4616 .with_context(|| {
4617 format!(
4618 "different function parameter types for `{}`",
4619 from_param.name
4620 )
4621 })?;
4622 }
4623 match (&from_func.result, &into_func.result) {
4624 (Some(from_ty), Some(into_ty)) => {
4625 self.build_type(from_ty, into_ty)
4626 .context("different function result types")?;
4627 }
4628 (None, None) => {}
4629 (Some(_), None) | (None, Some(_)) => bail!("different number of function results"),
4630 }
4631 Ok(())
4632 }
4633
4634 fn build_world(&mut self, from_id: WorldId, into_id: WorldId) -> anyhow::Result<()> {
4635 let prev = self.world_map.insert(from_id, into_id);
4636 assert!(prev.is_none());
4637
4638 let from_world = &self.from.worlds[from_id];
4639 let into_world = &self.into.worlds[into_id];
4640
4641 if from_world.imports.len() != into_world.imports.len() {
4650 bail!("world contains different number of imports than expected");
4651 }
4652 if from_world.exports.len() != into_world.exports.len() {
4653 bail!("world contains different number of exports than expected");
4654 }
4655
4656 for (from_name, from) in from_world.imports.iter() {
4657 let into_name = MergeMap::map_name(from_name, &self.interface_map);
4658 let name_str = self.from.name_world_key(from_name);
4659 let into = into_world
4660 .imports
4661 .get(&into_name)
4662 .ok_or_else(|| anyhow!("import `{name_str}` not found in target world"))?;
4663 self.match_world_item(from, into)
4664 .with_context(|| format!("import `{name_str}` didn't match target world"))?;
4665 }
4666
4667 for (from_name, from) in from_world.exports.iter() {
4668 let into_name = MergeMap::map_name(from_name, &self.interface_map);
4669 let name_str = self.from.name_world_key(from_name);
4670 let into = into_world
4671 .exports
4672 .get(&into_name)
4673 .ok_or_else(|| anyhow!("export `{name_str}` not found in target world"))?;
4674 self.match_world_item(from, into)
4675 .with_context(|| format!("export `{name_str}` didn't match target world"))?;
4676 }
4677
4678 Ok(())
4679 }
4680
4681 fn map_name(
4682 from_name: &WorldKey,
4683 interface_map: &HashMap<InterfaceId, InterfaceId>,
4684 ) -> WorldKey {
4685 match from_name {
4686 WorldKey::Name(s) => WorldKey::Name(s.clone()),
4687 WorldKey::Interface(id) => {
4688 WorldKey::Interface(interface_map.get(id).copied().unwrap_or(*id))
4689 }
4690 }
4691 }
4692
4693 fn match_world_item(&mut self, from: &WorldItem, into: &WorldItem) -> anyhow::Result<()> {
4694 match (from, into) {
4695 (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
4696 match (
4697 &self.from.interfaces[*from].name,
4698 &self.into.interfaces[*into].name,
4699 ) {
4700 (None, None) => self.build_interface(*from, *into)?,
4704
4705 _ => {
4710 if self.interface_map.get(from) != Some(into) {
4711 bail!("interfaces are not the same");
4712 }
4713 }
4714 }
4715 }
4716 (WorldItem::Function(from), WorldItem::Function(into)) => {
4717 let _ = (from, into);
4718 }
4721 (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
4722 let prev = self.type_map.insert(*from, *into);
4725 assert!(prev.is_none());
4726 }
4727
4728 (WorldItem::Interface { .. }, _)
4729 | (WorldItem::Function(_), _)
4730 | (WorldItem::Type { .. }, _) => {
4731 bail!("world items do not have the same type")
4732 }
4733 }
4734 Ok(())
4735 }
4736}
4737
4738fn update_stability(from: &Stability, into: &mut Stability, span: Span) -> ResolveResult<()> {
4744 if from == into || from.is_unknown() {
4747 return Ok(());
4748 }
4749 if into.is_unknown() {
4752 *into = from.clone();
4753 return Ok(());
4754 }
4755
4756 Err(ResolveError::from(ResolveErrorKind::StabilityMismatch {
4759 span,
4760 from: from.clone(),
4761 into: into.clone(),
4762 }))
4763}
4764
4765fn merge_include_stability(
4766 from: &Stability,
4767 into: &mut Stability,
4768 is_external_include: bool,
4769 span: Span,
4770) -> ResolveResult<()> {
4771 if is_external_include && from.is_stable() {
4772 log::trace!("dropped stability from external package");
4773 *into = Stability::Unknown;
4774 return Ok(());
4775 }
4776
4777 update_stability(from, into, span)
4778}
4779
4780#[cfg(test)]
4781mod tests {
4782 use crate::alloc::format;
4783 use crate::alloc::string::{String, ToString};
4784 use crate::alloc::vec::Vec;
4785 use crate::{Resolve, SourceMap, WorldItem, WorldKey};
4786 use anyhow::Result;
4787
4788 #[test]
4789 fn select_world() -> Result<()> {
4790 let mut resolve = Resolve::default();
4791 resolve.push_str(
4792 "test.wit",
4793 r#"
4794 package foo:bar@0.1.0;
4795
4796 world foo {}
4797 "#,
4798 )?;
4799 resolve.push_str(
4800 "test.wit",
4801 r#"
4802 package foo:baz@0.1.0;
4803
4804 world foo {}
4805 "#,
4806 )?;
4807 resolve.push_str(
4808 "test.wit",
4809 r#"
4810 package foo:baz@0.2.0;
4811
4812 world foo {}
4813 "#,
4814 )?;
4815
4816 let dummy = resolve.push_str(
4817 "test.wit",
4818 r#"
4819 package foo:dummy;
4820
4821 world foo {}
4822 "#,
4823 )?;
4824
4825 assert!(resolve.select_world(&[dummy], None).is_ok());
4826 assert!(resolve.select_world(&[dummy], Some("xx")).is_err());
4827 assert!(resolve.select_world(&[dummy], Some("")).is_err());
4828 assert!(resolve.select_world(&[dummy], Some("foo:bar/foo")).is_ok());
4829 assert!(
4830 resolve
4831 .select_world(&[dummy], Some("foo:bar/foo@0.1.0"))
4832 .is_ok()
4833 );
4834 assert!(resolve.select_world(&[dummy], Some("foo:baz/foo")).is_err());
4835 assert!(
4836 resolve
4837 .select_world(&[dummy], Some("foo:baz/foo@0.1.0"))
4838 .is_ok()
4839 );
4840 assert!(
4841 resolve
4842 .select_world(&[dummy], Some("foo:baz/foo@0.2.0"))
4843 .is_ok()
4844 );
4845 Ok(())
4846 }
4847
4848 #[test]
4849 fn wasm_import_name_future_and_stream_intrinsics() -> Result<()> {
4850 use crate::{FutureIntrinsic, LiftLowerAbi, ManglingAndAbi, StreamIntrinsic, WasmImport};
4851
4852 let mut resolve = Resolve::default();
4853 let pkg = resolve.push_str(
4854 "test.wit",
4855 r#"
4856 package foo:bar;
4857
4858 interface iface {
4859 iface-func: func(x: future<u32>) -> stream<u32>;
4860 }
4861
4862 world w {
4863 import import-func: func(x: future<future<u32>>, y: u32) -> stream<string>;
4864 export export-func: func(x: future, y: stream);
4865 import iface;
4866 export iface;
4867 }
4868 "#,
4869 )?;
4870 let world = resolve.packages[pkg].worlds["w"];
4871 let world = &resolve.worlds[world];
4872 let mangling = ManglingAndAbi::Legacy(LiftLowerAbi::AsyncStackful);
4873
4874 let WorldItem::Function(import_func) =
4875 &world.imports[&WorldKey::Name("import-func".to_string())]
4876 else {
4877 panic!("expected `import-func` to be a top-level world import");
4878 };
4879 let WorldItem::Function(export_func) =
4880 &world.exports[&WorldKey::Name("export-func".to_string())]
4881 else {
4882 panic!("expected `export-func` to be a top-level world export");
4883 };
4884 let import_types = import_func.find_futures_and_streams(&resolve);
4885 assert_eq!(import_types.len(), 3);
4886
4887 let (interface_key, interface_func) = world
4888 .imports
4889 .iter()
4890 .find_map(|(key, item)| match item {
4891 WorldItem::Interface { id, .. } => Some((
4892 key.clone(),
4893 &resolve.interfaces[*id].functions["iface-func"],
4894 )),
4895 _ => None,
4896 })
4897 .expect("expected interface import");
4898 let interface_types = interface_func.find_futures_and_streams(&resolve);
4899 assert_eq!(interface_types.len(), 2);
4900
4901 let (module, name) = resolve.wasm_import_name(
4902 mangling,
4903 WasmImport::FutureIntrinsic {
4904 interface: None,
4905 func: import_func,
4906 ty: Some(import_types[0]),
4907 intrinsic: FutureIntrinsic::New,
4908 exported: false,
4909 async_: false,
4910 },
4911 );
4912 assert_eq!(module, "$root");
4913 assert_eq!(name, "[future-new-0]import-func");
4914
4915 let (module, name) = resolve.wasm_import_name(
4916 mangling,
4917 WasmImport::FutureIntrinsic {
4918 interface: None,
4919 func: import_func,
4920 ty: Some(import_types[1]),
4921 intrinsic: FutureIntrinsic::Read,
4922 exported: false,
4923 async_: true,
4924 },
4925 );
4926 assert_eq!(module, "$root");
4927 assert_eq!(name, "[async-lower][future-read-1]import-func");
4928
4929 let (module, name) = resolve.wasm_import_name(
4930 mangling,
4931 WasmImport::StreamIntrinsic {
4932 interface: None,
4933 func: import_func,
4934 ty: Some(import_types[2]),
4935 intrinsic: StreamIntrinsic::CancelRead,
4936 exported: false,
4937 async_: true,
4938 },
4939 );
4940 assert_eq!(module, "$root");
4941 assert_eq!(name, "[async-lower][stream-cancel-read-2]import-func");
4942
4943 let (module, name) = resolve.wasm_import_name(
4944 mangling,
4945 WasmImport::FutureIntrinsic {
4946 interface: None,
4947 func: export_func,
4948 ty: None,
4949 intrinsic: FutureIntrinsic::DropReadable,
4950 exported: true,
4951 async_: false,
4952 },
4953 );
4954 assert_eq!(module, "[export]$root");
4955 assert_eq!(name, "[future-drop-readable-unit]export-func");
4956
4957 let (module, name) = resolve.wasm_import_name(
4958 mangling,
4959 WasmImport::StreamIntrinsic {
4960 interface: None,
4961 func: export_func,
4962 ty: None,
4963 intrinsic: StreamIntrinsic::Write,
4964 exported: true,
4965 async_: true,
4966 },
4967 );
4968 assert_eq!(module, "[export]$root");
4969 assert_eq!(name, "[async-lower][stream-write-unit]export-func");
4970
4971 let (module, name) = resolve.wasm_import_name(
4972 mangling,
4973 WasmImport::StreamIntrinsic {
4974 interface: Some(&interface_key),
4975 func: interface_func,
4976 ty: Some(interface_types[1]),
4977 intrinsic: StreamIntrinsic::Read,
4978 exported: true,
4979 async_: false,
4980 },
4981 );
4982 assert_eq!(
4983 module,
4984 format!("[export]{}", resolve.name_world_key(&interface_key))
4985 );
4986 assert_eq!(name, "[stream-read-1]iface-func");
4987
4988 Ok(())
4989 }
4990
4991 #[test]
4994 fn select_world_multiple_packages() -> Result<()> {
4995 use wit_parser::Resolve;
4996
4997 let mut resolve = Resolve::default();
4998
4999 let stuff = resolve.push_str(
5001 "./my-test.wit",
5002 r#"
5003 package test:stuff;
5004
5005 world foo {
5006 // ...
5007 }
5008 "#,
5009 )?;
5010 assert!(resolve.select_world(&[stuff], None).is_ok());
5011 assert!(resolve.select_world(&[stuff], Some("foo")).is_ok());
5012
5013 let empty = resolve.push_str(
5016 "./my-test.wit",
5017 r#"
5018 package test:empty;
5019 "#,
5020 )?;
5021 assert!(resolve.select_world(&[stuff, empty], None).is_err());
5022 assert!(resolve.select_world(&[stuff, empty], Some("foo")).is_err());
5023 assert!(resolve.select_world(&[empty], None).is_err());
5024 assert!(resolve.select_world(&[empty], Some("foo")).is_err());
5025
5026 Ok(())
5027 }
5028
5029 #[test]
5031 fn select_world_versions() -> Result<()> {
5032 use wit_parser::Resolve;
5033
5034 let mut resolve = Resolve::default();
5035
5036 let _id = resolve.push_str(
5037 "./my-test.wit",
5038 r#"
5039 package example:distraction;
5040 "#,
5041 )?;
5042
5043 let versions_1 = resolve.push_str(
5046 "./my-test.wit",
5047 r#"
5048 package example:versions@1.0.0;
5049
5050 world foo { /* ... */ }
5051 "#,
5052 )?;
5053 assert!(resolve.select_world(&[versions_1], Some("foo")).is_ok());
5054 assert!(
5055 resolve
5056 .select_world(&[versions_1], Some("foo@1.0.0"))
5057 .is_err()
5058 );
5059 assert!(
5060 resolve
5061 .select_world(&[versions_1], Some("example:versions/foo"))
5062 .is_ok()
5063 );
5064 assert!(
5065 resolve
5066 .select_world(&[versions_1], Some("example:versions/foo@1.0.0"))
5067 .is_ok()
5068 );
5069
5070 let versions_2 = resolve.push_str(
5073 "./my-test.wit",
5074 r#"
5075 package example:versions@2.0.0;
5076
5077 world foo { /* ... */ }
5078 "#,
5079 )?;
5080 assert!(
5081 resolve
5082 .select_world(&[versions_1, versions_2], Some("foo"))
5083 .is_err()
5084 );
5085 assert!(
5086 resolve
5087 .select_world(&[versions_1, versions_2], Some("foo@1.0.0"))
5088 .is_err()
5089 );
5090 assert!(
5091 resolve
5092 .select_world(&[versions_1, versions_2], Some("foo@2.0.0"))
5093 .is_err()
5094 );
5095 assert!(
5096 resolve
5097 .select_world(&[versions_1, versions_2], Some("example:versions/foo"))
5098 .is_err()
5099 );
5100 assert!(
5101 resolve
5102 .select_world(
5103 &[versions_1, versions_2],
5104 Some("example:versions/foo@1.0.0")
5105 )
5106 .is_ok()
5107 );
5108 assert!(
5109 resolve
5110 .select_world(
5111 &[versions_1, versions_2],
5112 Some("example:versions/foo@2.0.0")
5113 )
5114 .is_ok()
5115 );
5116
5117 Ok(())
5118 }
5119
5120 #[test]
5122 fn select_world_override_qualification() -> Result<()> {
5123 use wit_parser::Resolve;
5124
5125 let mut resolve = Resolve::default();
5126
5127 let other = resolve.push_str(
5128 "./my-test.wit",
5129 r#"
5130 package example:other;
5131
5132 world foo { }
5133 "#,
5134 )?;
5135
5136 let fq = resolve.push_str(
5138 "./my-test.wit",
5139 r#"
5140 package example:fq;
5141
5142 world bar { }
5143 "#,
5144 )?;
5145 assert!(resolve.select_world(&[other, fq], Some("foo")).is_err());
5146 assert!(resolve.select_world(&[other, fq], Some("bar")).is_err());
5147 assert!(
5148 resolve
5149 .select_world(&[other, fq], Some("example:other/foo"))
5150 .is_ok()
5151 );
5152 assert!(
5153 resolve
5154 .select_world(&[other, fq], Some("example:fq/bar"))
5155 .is_ok()
5156 );
5157 assert!(
5158 resolve
5159 .select_world(&[other, fq], Some("example:other/bar"))
5160 .is_err()
5161 );
5162 assert!(
5163 resolve
5164 .select_world(&[other, fq], Some("example:fq/foo"))
5165 .is_err()
5166 );
5167
5168 Ok(())
5169 }
5170
5171 #[test]
5173 fn select_world_fully_qualified() -> Result<()> {
5174 use wit_parser::Resolve;
5175
5176 let mut resolve = Resolve::default();
5177
5178 let distraction = resolve.push_str(
5179 "./my-test.wit",
5180 r#"
5181 package example:distraction;
5182 "#,
5183 )?;
5184
5185 let multiworld = resolve.push_str(
5188 "./my-test.wit",
5189 r#"
5190 package example:multiworld;
5191
5192 world foo { /* ... */ }
5193
5194 world bar { /* ... */ }
5195 "#,
5196 )?;
5197 assert!(
5198 resolve
5199 .select_world(&[distraction, multiworld], None)
5200 .is_err()
5201 );
5202 assert!(
5203 resolve
5204 .select_world(&[distraction, multiworld], Some("foo"))
5205 .is_err()
5206 );
5207 assert!(
5208 resolve
5209 .select_world(&[distraction, multiworld], Some("example:multiworld/foo"))
5210 .is_ok()
5211 );
5212 assert!(
5213 resolve
5214 .select_world(&[distraction, multiworld], Some("bar"))
5215 .is_err()
5216 );
5217 assert!(
5218 resolve
5219 .select_world(&[distraction, multiworld], Some("example:multiworld/bar"))
5220 .is_ok()
5221 );
5222
5223 Ok(())
5224 }
5225
5226 #[test]
5228 fn select_world_packages() -> Result<()> {
5229 use wit_parser::Resolve;
5230
5231 let mut resolve = Resolve::default();
5232
5233 let wit1 = resolve.push_str(
5236 "./my-test.wit",
5237 r#"
5238 package example:wit1;
5239
5240 world foo {
5241 // ...
5242 }
5243 "#,
5244 )?;
5245 assert!(resolve.select_world(&[wit1], None).is_ok());
5246 assert!(resolve.select_world(&[wit1], Some("foo")).is_ok());
5247 assert!(
5248 resolve
5249 .select_world(&[wit1], Some("example:wit1/foo"))
5250 .is_ok()
5251 );
5252 assert!(resolve.select_world(&[wit1], Some("bar")).is_err());
5253 assert!(
5254 resolve
5255 .select_world(&[wit1], Some("example:wit2/foo"))
5256 .is_err()
5257 );
5258
5259 let wit2 = resolve.push_str(
5262 "./my-test.wit",
5263 r#"
5264 package example:wit2;
5265
5266 world foo { /* ... */ }
5267 "#,
5268 )?;
5269 assert!(resolve.select_world(&[wit1, wit2], None).is_err());
5270 assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
5271 assert!(
5272 resolve
5273 .select_world(&[wit1, wit2], Some("example:wit1/foo"))
5274 .is_ok()
5275 );
5276 assert!(resolve.select_world(&[wit2], None).is_ok());
5277 assert!(resolve.select_world(&[wit2], Some("foo")).is_ok());
5278 assert!(
5279 resolve
5280 .select_world(&[wit2], Some("example:wit1/foo"))
5281 .is_ok()
5282 );
5283 assert!(resolve.select_world(&[wit1, wit2], Some("bar")).is_err());
5284 assert!(
5285 resolve
5286 .select_world(&[wit1, wit2], Some("example:wit2/foo"))
5287 .is_ok()
5288 );
5289 assert!(resolve.select_world(&[wit2], Some("bar")).is_err());
5290 assert!(
5291 resolve
5292 .select_world(&[wit2], Some("example:wit2/foo"))
5293 .is_ok()
5294 );
5295
5296 Ok(())
5297 }
5298
5299 #[test]
5300 fn span_preservation() -> Result<()> {
5301 let mut resolve = Resolve::default();
5302 let pkg = resolve.push_str(
5303 "test.wit",
5304 r#"
5305 package foo:bar;
5306
5307 interface my-iface {
5308 type my-type = u32;
5309 my-func: func();
5310 }
5311
5312 world my-world {
5313 export my-export: func();
5314 }
5315 "#,
5316 )?;
5317
5318 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5319 assert!(resolve.interfaces[iface_id].span.is_known());
5320
5321 let type_id = resolve.interfaces[iface_id].types["my-type"];
5322 assert!(resolve.types[type_id].span.is_known());
5323
5324 assert!(
5325 resolve.interfaces[iface_id].functions["my-func"]
5326 .span
5327 .is_known()
5328 );
5329
5330 let world_id = resolve.packages[pkg].worlds["my-world"];
5331 assert!(resolve.worlds[world_id].span.is_known());
5332
5333 let WorldItem::Function(f) =
5334 &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5335 else {
5336 panic!("expected function");
5337 };
5338 assert!(f.span.is_known());
5339
5340 Ok(())
5341 }
5342
5343 #[test]
5344 fn span_preservation_through_merge() -> Result<()> {
5345 let mut resolve1 = Resolve::default();
5346 resolve1.push_str(
5347 "test1.wit",
5348 r#"
5349 package foo:bar;
5350
5351 interface iface1 {
5352 type type1 = u32;
5353 func1: func();
5354 }
5355 "#,
5356 )?;
5357
5358 let mut resolve2 = Resolve::default();
5359 let pkg2 = resolve2.push_str(
5360 "test2.wit",
5361 r#"
5362 package foo:baz;
5363
5364 interface iface2 {
5365 type type2 = string;
5366 func2: func();
5367 }
5368 "#,
5369 )?;
5370
5371 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5372 let remap = resolve1.merge(resolve2)?;
5373 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5374
5375 assert!(resolve1.interfaces[iface2_id].span.is_known());
5376
5377 let type2_id = resolve1.interfaces[iface2_id].types["type2"];
5378 assert!(resolve1.types[type2_id].span.is_known());
5379
5380 assert!(
5381 resolve1.interfaces[iface2_id].functions["func2"]
5382 .span
5383 .is_known()
5384 );
5385
5386 Ok(())
5387 }
5388
5389 #[test]
5390 fn span_preservation_through_include() -> Result<()> {
5391 let mut resolve = Resolve::default();
5392 let pkg = resolve.push_str(
5393 "test.wit",
5394 r#"
5395 package foo:bar;
5396
5397 world base {
5398 export my-func: func();
5399 }
5400
5401 world extended {
5402 include base;
5403 }
5404 "#,
5405 )?;
5406
5407 let base_id = resolve.packages[pkg].worlds["base"];
5408 let extended_id = resolve.packages[pkg].worlds["extended"];
5409
5410 let WorldItem::Function(base_func) =
5411 &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5412 else {
5413 panic!("expected function");
5414 };
5415 assert!(base_func.span.is_known());
5416
5417 let WorldItem::Function(extended_func) =
5418 &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5419 else {
5420 panic!("expected function");
5421 };
5422 assert!(extended_func.span.is_known());
5423
5424 Ok(())
5425 }
5426
5427 #[test]
5428 fn span_preservation_through_include_with_rename() -> Result<()> {
5429 let mut resolve = Resolve::default();
5430 let pkg = resolve.push_str(
5431 "test.wit",
5432 r#"
5433 package foo:bar;
5434
5435 world base {
5436 export original-name: func();
5437 }
5438
5439 world extended {
5440 include base with { original-name as renamed-func }
5441 }
5442 "#,
5443 )?;
5444
5445 let extended_id = resolve.packages[pkg].worlds["extended"];
5446
5447 let WorldItem::Function(f) =
5448 &resolve.worlds[extended_id].exports[&WorldKey::Name("renamed-func".to_string())]
5449 else {
5450 panic!("expected function");
5451 };
5452 assert!(f.span.is_known());
5453
5454 assert!(
5455 !resolve.worlds[extended_id]
5456 .exports
5457 .contains_key(&WorldKey::Name("original-name".to_string()))
5458 );
5459
5460 Ok(())
5461 }
5462
5463 #[test]
5465 fn span_preservation_through_include_reverse_order() -> Result<()> {
5466 let mut resolve = Resolve::default();
5467 let pkg = resolve.push_str(
5468 "test.wit",
5469 r#"
5470 package foo:bar;
5471
5472 world extended {
5473 include base;
5474 }
5475
5476 world base {
5477 export my-func: func();
5478 }
5479 "#,
5480 )?;
5481
5482 let base_id = resolve.packages[pkg].worlds["base"];
5483 let extended_id = resolve.packages[pkg].worlds["extended"];
5484
5485 let WorldItem::Function(base_func) =
5486 &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5487 else {
5488 panic!("expected function");
5489 };
5490 assert!(base_func.span.is_known());
5491
5492 let WorldItem::Function(extended_func) =
5493 &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5494 else {
5495 panic!("expected function");
5496 };
5497 assert!(extended_func.span.is_known());
5498
5499 Ok(())
5500 }
5501
5502 #[test]
5503 fn span_line_numbers() -> Result<()> {
5504 let mut resolve = Resolve::default();
5505 let pkg = resolve.push_source(
5506 "test.wit",
5507 "package foo:bar;
5508
5509interface my-iface {
5510 type my-type = u32;
5511 my-func: func();
5512}
5513
5514world my-world {
5515 export my-export: func();
5516}
5517",
5518 )?;
5519
5520 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5521 let iface_span = resolve.interfaces[iface_id].span;
5522 let iface_loc = resolve.render_location(iface_span);
5523 assert!(
5524 iface_loc.contains(":3:"),
5525 "interface location was {iface_loc}"
5526 );
5527
5528 let type_id = resolve.interfaces[iface_id].types["my-type"];
5529 let type_span = resolve.types[type_id].span;
5530 let type_loc = resolve.render_location(type_span);
5531 assert!(type_loc.contains(":4:"), "type location was {type_loc}");
5532
5533 let func_span = resolve.interfaces[iface_id].functions["my-func"].span;
5534 let func_loc = resolve.render_location(func_span);
5535 assert!(func_loc.contains(":5:"), "function location was {func_loc}");
5536
5537 let world_id = resolve.packages[pkg].worlds["my-world"];
5538 let world_span = resolve.worlds[world_id].span;
5539 let world_loc = resolve.render_location(world_span);
5540 assert!(world_loc.contains(":8:"), "world location was {world_loc}");
5541
5542 let WorldItem::Function(export_func) =
5543 &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5544 else {
5545 panic!("expected function");
5546 };
5547 let export_loc = resolve.render_location(export_func.span);
5548 assert!(
5549 export_loc.contains(":9:"),
5550 "export location was {export_loc}"
5551 );
5552
5553 Ok(())
5554 }
5555
5556 #[test]
5557 fn span_line_numbers_through_merge() -> Result<()> {
5558 let mut resolve1 = Resolve::default();
5559 resolve1.push_source(
5560 "first.wit",
5561 "package foo:first;
5562
5563interface iface1 {
5564 func1: func();
5565}
5566",
5567 )?;
5568
5569 let mut resolve2 = Resolve::default();
5570 let pkg2 = resolve2.push_source(
5571 "second.wit",
5572 "package foo:second;
5573
5574interface iface2 {
5575 func2: func();
5576}
5577",
5578 )?;
5579
5580 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5581 let remap = resolve1.merge(resolve2)?;
5582 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5583
5584 let iface2_span = resolve1.interfaces[iface2_id].span;
5585 let iface2_loc = resolve1.render_location(iface2_span);
5586 assert!(
5587 iface2_loc.contains("second.wit"),
5588 "should reference second.wit, got {iface2_loc}"
5589 );
5590 assert!(
5591 iface2_loc.contains(":3:"),
5592 "interface should be on line 3, got {iface2_loc}"
5593 );
5594
5595 let func2_span = resolve1.interfaces[iface2_id].functions["func2"].span;
5596 let func2_loc = resolve1.render_location(func2_span);
5597 assert!(
5598 func2_loc.contains("second.wit"),
5599 "should reference second.wit, got {func2_loc}"
5600 );
5601 assert!(
5602 func2_loc.contains(":4:"),
5603 "function should be on line 4, got {func2_loc}"
5604 );
5605
5606 Ok(())
5607 }
5608
5609 #[test]
5610 fn span_line_numbers_multiple_sources() -> Result<()> {
5611 let mut resolve = Resolve::default();
5612
5613 let pkg1 = resolve.push_source(
5614 "first.wit",
5615 "package test:first;
5616
5617interface first-iface {
5618 first-func: func();
5619}
5620",
5621 )?;
5622
5623 let pkg2 = resolve.push_source(
5624 "second.wit",
5625 "package test:second;
5626
5627interface second-iface {
5628 second-func: func();
5629}
5630",
5631 )?;
5632
5633 let iface1_id = resolve.packages[pkg1].interfaces["first-iface"];
5634 let iface1_span = resolve.interfaces[iface1_id].span;
5635 let iface1_loc = resolve.render_location(iface1_span);
5636 assert!(
5637 iface1_loc.contains("first.wit"),
5638 "should reference first.wit, got {iface1_loc}"
5639 );
5640 assert!(
5641 iface1_loc.contains(":3:"),
5642 "interface should be on line 3, got {iface1_loc}"
5643 );
5644
5645 let func1_span = resolve.interfaces[iface1_id].functions["first-func"].span;
5646 let func1_loc = resolve.render_location(func1_span);
5647 assert!(
5648 func1_loc.contains("first.wit"),
5649 "should reference first.wit, got {func1_loc}"
5650 );
5651 assert!(
5652 func1_loc.contains(":4:"),
5653 "function should be on line 4, got {func1_loc}"
5654 );
5655
5656 let iface2_id = resolve.packages[pkg2].interfaces["second-iface"];
5657 let iface2_span = resolve.interfaces[iface2_id].span;
5658 let iface2_loc = resolve.render_location(iface2_span);
5659 assert!(
5660 iface2_loc.contains("second.wit"),
5661 "should reference second.wit, got {iface2_loc}"
5662 );
5663 assert!(
5664 iface2_loc.contains(":3:"),
5665 "interface should be on line 3, got {iface2_loc}"
5666 );
5667
5668 let func2_span = resolve.interfaces[iface2_id].functions["second-func"].span;
5669 let func2_loc = resolve.render_location(func2_span);
5670 assert!(
5671 func2_loc.contains("second.wit"),
5672 "should reference second.wit, got {func2_loc}"
5673 );
5674 assert!(
5675 func2_loc.contains(":4:"),
5676 "function should be on line 4, got {func2_loc}"
5677 );
5678
5679 Ok(())
5680 }
5681
5682 #[test]
5683 fn span_preservation_for_fields_and_cases() -> Result<()> {
5684 use crate::TypeDefKind;
5685
5686 let mut resolve = Resolve::default();
5687 let pkg = resolve.push_str(
5688 "test.wit",
5689 r#"
5690 package foo:bar;
5691
5692 interface my-iface {
5693 record my-record {
5694 field1: u32,
5695 field2: string,
5696 }
5697
5698 flags my-flags {
5699 flag1,
5700 flag2,
5701 }
5702
5703 variant my-variant {
5704 case1,
5705 case2(u32),
5706 }
5707
5708 enum my-enum {
5709 val1,
5710 val2,
5711 }
5712 }
5713 "#,
5714 )?;
5715
5716 let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5717
5718 let record_id = resolve.interfaces[iface_id].types["my-record"];
5720 let TypeDefKind::Record(record) = &resolve.types[record_id].kind else {
5721 panic!("expected record");
5722 };
5723 assert!(record.fields[0].span.is_known(), "field1 should have span");
5724 assert!(record.fields[1].span.is_known(), "field2 should have span");
5725
5726 let flags_id = resolve.interfaces[iface_id].types["my-flags"];
5728 let TypeDefKind::Flags(flags) = &resolve.types[flags_id].kind else {
5729 panic!("expected flags");
5730 };
5731 assert!(flags.flags[0].span.is_known(), "flag1 should have span");
5732 assert!(flags.flags[1].span.is_known(), "flag2 should have span");
5733
5734 let variant_id = resolve.interfaces[iface_id].types["my-variant"];
5736 let TypeDefKind::Variant(variant) = &resolve.types[variant_id].kind else {
5737 panic!("expected variant");
5738 };
5739 assert!(variant.cases[0].span.is_known(), "case1 should have span");
5740 assert!(variant.cases[1].span.is_known(), "case2 should have span");
5741
5742 let enum_id = resolve.interfaces[iface_id].types["my-enum"];
5744 let TypeDefKind::Enum(e) = &resolve.types[enum_id].kind else {
5745 panic!("expected enum");
5746 };
5747 assert!(e.cases[0].span.is_known(), "val1 should have span");
5748 assert!(e.cases[1].span.is_known(), "val2 should have span");
5749
5750 Ok(())
5751 }
5752
5753 #[test]
5754 fn span_preservation_for_fields_through_merge() -> Result<()> {
5755 use crate::TypeDefKind;
5756
5757 let mut resolve1 = Resolve::default();
5758 resolve1.push_str(
5759 "test1.wit",
5760 r#"
5761 package foo:bar;
5762
5763 interface iface1 {
5764 record rec1 {
5765 f1: u32,
5766 }
5767 }
5768 "#,
5769 )?;
5770
5771 let mut resolve2 = Resolve::default();
5772 let pkg2 = resolve2.push_str(
5773 "test2.wit",
5774 r#"
5775 package foo:baz;
5776
5777 interface iface2 {
5778 record rec2 {
5779 f2: string,
5780 }
5781
5782 variant var2 {
5783 c2,
5784 }
5785 }
5786 "#,
5787 )?;
5788
5789 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5790 let rec2_old_id = resolve2.interfaces[iface2_old_id].types["rec2"];
5791 let var2_old_id = resolve2.interfaces[iface2_old_id].types["var2"];
5792
5793 let remap = resolve1.merge(resolve2)?;
5794
5795 let rec2_id = remap.types[rec2_old_id.index()].unwrap();
5796 let TypeDefKind::Record(record) = &resolve1.types[rec2_id].kind else {
5797 panic!("expected record");
5798 };
5799 assert!(
5800 record.fields[0].span.is_known(),
5801 "field should have span after merge"
5802 );
5803
5804 let var2_id = remap.types[var2_old_id.index()].unwrap();
5805 let TypeDefKind::Variant(variant) = &resolve1.types[var2_id].kind else {
5806 panic!("expected variant");
5807 };
5808 assert!(
5809 variant.cases[0].span.is_known(),
5810 "case should have span after merge"
5811 );
5812
5813 Ok(())
5814 }
5815
5816 #[test]
5817 fn param_spans_point_to_names() -> Result<()> {
5818 let source = "\
5819package foo:bar;
5820
5821interface iface {
5822 my-func: func(a: u32, b: string);
5823}
5824";
5825 let mut resolve = Resolve::default();
5826 let pkg = resolve.push_str("test.wit", source)?;
5827
5828 let iface_id = resolve.packages[pkg].interfaces["iface"];
5829 let func = &resolve.interfaces[iface_id].functions["my-func"];
5830 assert_eq!(func.params.len(), 2);
5831 for param in &func.params {
5832 let start = param.span.start() as usize;
5833 let end = param.span.end() as usize;
5834 let snippet = &source[start..end];
5835 assert_eq!(
5836 snippet, param.name,
5837 "param `{}` span points to {:?}",
5838 param.name, snippet
5839 );
5840 }
5841
5842 Ok(())
5843 }
5844
5845 #[test]
5846 fn push_groups_resolves_dep_before_main() -> Result<()> {
5847 let dep = {
5850 let mut map = SourceMap::default();
5851 map.push_str(
5852 "file:///dep.wit",
5853 "package foo:dep;\ninterface i { type t = u32; }",
5854 );
5855 map.parse().map_err(|(_, e)| e)?
5856 };
5857 let main = {
5858 let mut map = SourceMap::default();
5859 map.push_str(
5860 "file:///main.wit",
5861 "package foo:main;\ninterface j { use foo:dep/i.{t}; type u = t; }",
5862 );
5863 map.parse().map_err(|(_, e)| e)?
5864 };
5865 let mut resolve = Resolve::default();
5866 resolve.push_groups(main, Vec::from([dep]))?;
5867 assert_eq!(resolve.packages.len(), 2);
5868 Ok(())
5869 }
5870
5871 #[test]
5872 fn push_groups_cycle_error_contains_location() {
5873 let a = {
5877 let mut map = SourceMap::default();
5878 map.push_str(
5879 "file:///a.wit",
5880 "package foo:a;\ninterface i { use foo:b/j.{}; }",
5881 );
5882 map.parse().unwrap()
5883 };
5884 let b = {
5885 let mut map = SourceMap::default();
5886 map.push_str(
5887 "file:///b.wit",
5888 "package foo:b;\ninterface j { use foo:a/i.{}; }",
5889 );
5890 map.parse().unwrap()
5891 };
5892 let mut resolve = Resolve::default();
5893 let err = resolve.push_groups(a, Vec::from([b])).unwrap_err();
5894 let msg = err.highlight(&resolve.source_map);
5895 assert!(
5896 msg.contains("file:///"),
5897 "cycle error should contain a file URI, got: {msg}"
5898 );
5899 }
5900
5901 #[test]
5902 fn param_spans_preserved_through_merge() -> Result<()> {
5903 let mut resolve1 = Resolve::default();
5904 resolve1.push_str(
5905 "test1.wit",
5906 r#"
5907 package foo:bar;
5908
5909 interface iface1 {
5910 f1: func(x: u32);
5911 }
5912 "#,
5913 )?;
5914
5915 let mut resolve2 = Resolve::default();
5916 let pkg2 = resolve2.push_str(
5917 "test2.wit",
5918 r#"
5919 package foo:baz;
5920
5921 interface iface2 {
5922 f2: func(y: string, z: bool);
5923 }
5924 "#,
5925 )?;
5926
5927 let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5928
5929 let remap = resolve1.merge(resolve2)?;
5930
5931 let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5932 let func = &resolve1.interfaces[iface2_id].functions["f2"];
5933 for param in &func.params {
5934 assert!(
5935 param.span.is_known(),
5936 "param `{}` should have span after merge",
5937 param.name
5938 );
5939 }
5940
5941 Ok(())
5942 }
5943
5944 #[test]
5949 fn exportize_importize_roundtrip() -> Result<()> {
5950 let mut resolve = Resolve::default();
5951 let pkg = resolve.push_str(
5952 "test.wit",
5953 r#"
5954 package foo:bar;
5955
5956 interface types {
5957 type my-type = u32;
5958 }
5959
5960 interface api {
5961 use types.{my-type};
5962 do-something: func(a: my-type) -> my-type;
5963 }
5964
5965 world w {
5966 export api;
5967 }
5968 "#,
5969 )?;
5970 let world_id = resolve.packages[pkg].worlds["w"];
5971
5972 let original_export_keys: Vec<String> = resolve.worlds[world_id]
5974 .exports
5975 .keys()
5976 .map(|k| resolve.name_world_key(k))
5977 .collect();
5978 assert!(!original_export_keys.is_empty());
5979 assert!(resolve.worlds[world_id].imports.iter().all(|(_, item)| {
5980 matches!(item, WorldItem::Interface { .. })
5983 }));
5984
5985 resolve.importize(world_id, Some("w-temp".to_string()))?;
5987 assert!(
5988 resolve.worlds[world_id].exports.is_empty(),
5989 "importize should leave no exports"
5990 );
5991 for key in &original_export_keys {
5993 assert!(
5994 resolve.worlds[world_id]
5995 .imports
5996 .keys()
5997 .any(|k| resolve.name_world_key(k) == *key),
5998 "expected `{key}` to be an import after importize"
5999 );
6000 }
6001
6002 resolve.exportize(world_id, Some("w-final".to_string()), None)?;
6004 assert!(
6005 !resolve.worlds[world_id].exports.is_empty(),
6006 "exportize should produce exports"
6007 );
6008 let final_export_keys: Vec<String> = resolve.worlds[world_id]
6010 .exports
6011 .keys()
6012 .map(|k| resolve.name_world_key(k))
6013 .collect();
6014 for key in &original_export_keys {
6015 assert!(
6016 final_export_keys.contains(key),
6017 "expected `{key}` to be an export after round-trip, got exports: {final_export_keys:?}"
6018 );
6019 }
6020
6021 Ok(())
6022 }
6023}