Coverage Report

Created: 2026-10-24 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wit-parser/src/resolve/mod.rs
Line
Count
Source
1
use alloc::borrow::ToOwned;
2
use alloc::collections::BTreeMap;
3
use alloc::string::{String, ToString};
4
use alloc::vec::Vec;
5
use alloc::{format, vec};
6
use core::cmp::Ordering;
7
use core::mem;
8
9
use crate::resolve::error::{ResolveError, ResolveErrorKind};
10
use crate::*;
11
use anyhow::{Context, anyhow, bail};
12
#[cfg(not(feature = "std"))]
13
use hashbrown::hash_map::Entry;
14
use id_arena::{Arena, Id};
15
use semver::Version;
16
#[cfg(feature = "serde")]
17
use serde_derive::Serialize;
18
#[cfg(feature = "std")]
19
use std::collections::hash_map::Entry;
20
21
use crate::ast::lex::Span;
22
use crate::ast::{ParsedUsePath, parse_use_path};
23
#[cfg(feature = "serde")]
24
use crate::serde_::{serialize_arena, serialize_id_map};
25
use 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
32
pub use clone::CloneMaps;
33
34
mod clone;
35
pub mod error;
36
37
#[cfg(feature = "std")]
38
mod fs;
39
#[cfg(feature = "std")]
40
pub use fs::PackageSourceMap;
41
42
/// Representation of a fully resolved set of WIT packages.
43
///
44
/// This structure contains a graph of WIT packages and all of their contents
45
/// merged together into the contained arenas. All items are sorted
46
/// topologically and everything here is fully resolved, so with a `Resolve` no
47
/// name lookups are necessary and instead everything is index-based.
48
///
49
/// Working with a WIT package requires inserting it into a `Resolve` to ensure
50
/// that all of its dependencies are satisfied. This will give the full picture
51
/// of that package's types and such.
52
///
53
/// Each item in a `Resolve` has a parent link to trace it back to the original
54
/// package as necessary.
55
#[derive(Default, Clone, Debug)]
56
#[cfg_attr(feature = "serde", derive(Serialize))]
57
pub struct Resolve {
58
    /// All known worlds within this `Resolve`.
59
    ///
60
    /// Each world points at a `PackageId` which is stored below. No ordering is
61
    /// guaranteed between this list of worlds.
62
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
63
    pub worlds: Arena<World>,
64
65
    /// All known interfaces within this `Resolve`.
66
    ///
67
    /// Each interface points at a `PackageId` which is stored below. No
68
    /// ordering is guaranteed between this list of interfaces.
69
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
70
    pub interfaces: Arena<Interface>,
71
72
    /// All known types within this `Resolve`.
73
    ///
74
    /// Types are topologically sorted such that any type referenced from one
75
    /// type is guaranteed to be defined previously. Otherwise though these are
76
    /// not sorted by interface for example.
77
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
78
    pub types: Arena<TypeDef>,
79
80
    /// All known packages within this `Resolve`.
81
    ///
82
    /// This list of packages is not sorted. Sorted packages can be queried
83
    /// through [`Resolve::topological_packages`].
84
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
85
    pub packages: Arena<Package>,
86
87
    /// A map of package names to the ID of the package with that name.
88
    #[cfg_attr(feature = "serde", serde(skip))]
89
    pub package_names: IndexMap<PackageName, PackageId>,
90
91
    /// Activated features for this [`Resolve`].
92
    ///
93
    /// This set of features is empty by default. This is consulted for
94
    /// `@unstable` annotations in loaded WIT documents. Any items with
95
    /// `@unstable` are filtered out unless their feature is present within this
96
    /// set.
97
    #[cfg_attr(feature = "serde", serde(skip))]
98
    pub features: IndexSet<String>,
99
100
    /// Activate all features for this [`Resolve`].
101
    #[cfg_attr(feature = "serde", serde(skip))]
102
    pub all_features: bool,
103
104
    /// Source map for converting spans to file locations.
105
    #[cfg_attr(feature = "serde", serde(skip))]
106
    pub source_map: SourceMap,
107
}
108
109
/// A WIT package within a `Resolve`.
110
///
111
/// A package is a collection of interfaces and worlds. Packages additionally
112
/// have a unique identifier that affects generated components and uniquely
113
/// identifiers this particular package.
114
#[derive(Clone, Debug)]
115
#[cfg_attr(feature = "serde", derive(Serialize))]
116
pub struct Package {
117
    /// A unique name corresponding to this package.
118
    pub name: PackageName,
119
120
    /// Documentation associated with this package.
121
    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
122
    pub docs: Docs,
123
124
    /// All interfaces contained in this packaged, keyed by the interface's
125
    /// name.
126
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
127
    pub interfaces: IndexMap<String, InterfaceId>,
128
129
    /// All worlds contained in this package, keyed by the world's name.
130
    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
131
    pub worlds: IndexMap<String, WorldId>,
132
}
133
134
pub type PackageId = Id<Package>;
135
136
/// Source name mappings for resolved packages (no_std compatible).
137
#[derive(Clone, Debug)]
138
pub struct PackageSources {
139
    sources: Vec<Vec<String>>,
140
    package_id_to_source_map_idx: BTreeMap<PackageId, usize>,
141
}
142
143
impl PackageSources {
144
0
    pub fn from_single_source(package_id: PackageId, source: &str) -> Self {
145
0
        Self {
146
0
            sources: vec![vec![source.to_owned()]],
147
0
            package_id_to_source_map_idx: BTreeMap::from([(package_id, 0)]),
148
0
        }
149
0
    }
150
151
11.0k
    pub fn from_source_maps(
152
11.0k
        source_maps: Vec<SourceMap>,
153
11.0k
        package_id_to_source_map_idx: BTreeMap<PackageId, usize>,
154
11.0k
    ) -> PackageSources {
155
11.8k
        for (package_id, idx) in &package_id_to_source_map_idx {
156
11.8k
            if *idx >= source_maps.len() {
157
0
                panic!(
158
                    "Invalid source map index: {}, package id: {:?}, source maps size: {}",
159
                    idx,
160
                    package_id,
161
0
                    source_maps.len()
162
                )
163
11.8k
            }
164
        }
165
166
        Self {
167
11.0k
            sources: source_maps
168
11.0k
                .into_iter()
169
20.1k
                .map(|source_map| source_map.source_names().map(|s| s.to_owned()).collect())
170
11.0k
                .collect(),
171
11.0k
            package_id_to_source_map_idx,
172
        }
173
11.0k
    }
174
175
    /// All unique source names.
176
0
    pub fn source_names(&self) -> impl Iterator<Item = &str> {
177
0
        self.sources
178
0
            .iter()
179
0
            .flatten()
180
0
            .map(|s| s.as_str())
181
0
            .collect::<IndexSet<&str>>()
182
0
            .into_iter()
183
0
    }
184
185
    /// Source names for a specific package.
186
0
    pub fn package_source_names(&self, id: PackageId) -> Option<impl Iterator<Item = &str>> {
187
0
        self.package_id_to_source_map_idx
188
0
            .get(&id)
189
0
            .map(|&idx| self.sources[idx].iter().map(|s| s.as_str()))
190
0
    }
191
}
192
193
/// Visitor helper for performing topological sort on a group of packages.
194
12.6k
fn visit<'a>(
195
12.6k
    pkg: &'a UnresolvedPackage,
196
12.6k
    pkg_details_map: &'a BTreeMap<PackageName, (UnresolvedPackage, usize)>,
197
12.6k
    order: &mut IndexSet<PackageName>,
198
12.6k
    visiting: &mut HashSet<&'a PackageName>,
199
12.6k
    source_map_offsets: &[u32],
200
12.6k
) -> ResolveResult<()> {
201
12.6k
    if order.contains(&pkg.name) {
202
870
        return Ok(());
203
11.8k
    }
204
205
11.8k
    let (_, source_map_index) = pkg_details_map
206
11.8k
        .get(&pkg.name)
207
11.8k
        .expect("No pkg_details found for package when doing topological sort");
208
11.8k
    let offset = source_map_offsets[*source_map_index];
209
11.8k
    for (i, (dep, _)) in pkg.foreign_deps.iter().enumerate() {
210
3.05k
        let mut span = pkg.foreign_dep_spans[i];
211
3.05k
        span.adjust(offset);
212
3.05k
        if !visiting.insert(dep) {
213
0
            return Err(ResolveError::from(ResolveErrorKind::PackageCycle {
214
0
                package: dep.clone(),
215
0
                span,
216
0
            }));
217
3.05k
        }
218
3.05k
        if let Some((dep_pkg, _)) = pkg_details_map.get(dep) {
219
870
            visit(
220
870
                dep_pkg,
221
870
                pkg_details_map,
222
870
                order,
223
870
                visiting,
224
870
                source_map_offsets,
225
0
            )?;
226
2.18k
        }
227
3.05k
        assert!(visiting.remove(dep));
228
    }
229
11.8k
    assert!(order.insert(pkg.name.clone()));
230
11.8k
    Ok(())
231
12.6k
}
232
233
impl Resolve {
234
    /// Creates a new [`Resolve`] with no packages/items inside of it.
235
0
    pub fn new() -> Resolve {
236
0
        Resolve::default()
237
0
    }
238
239
    /// Merge `main` and `deps` into this [`Resolve`], topologically sorting
240
    /// them internally. Returns the [`PackageId`] of `main` and a
241
    /// [`PackageSources`] covering all groups.
242
11.0k
    fn sort_unresolved_packages(
243
11.0k
        &mut self,
244
11.0k
        main: UnresolvedPackageGroup,
245
11.0k
        deps: Vec<UnresolvedPackageGroup>,
246
11.0k
    ) -> ResolveResult<(PackageId, PackageSources)> {
247
11.0k
        let mut source_maps: Vec<SourceMap> = Vec::new();
248
11.0k
        let mut all_packages: Vec<(UnresolvedPackage, usize)> = Vec::new();
249
250
11.0k
        let mut collect = |group: UnresolvedPackageGroup| {
251
            let UnresolvedPackageGroup {
252
11.0k
                main,
253
11.0k
                nested,
254
11.0k
                source_map,
255
11.0k
            } = group;
256
11.0k
            let i = source_maps.len();
257
11.0k
            source_maps.push(source_map);
258
11.8k
            for pkg in nested.into_iter().chain([main]) {
259
11.8k
                all_packages.push((pkg, i));
260
11.8k
            }
261
11.0k
        };
262
263
11.0k
        let main_name = main.main.name.clone();
264
11.0k
        collect(main);
265
11.0k
        for dep in deps {
266
0
            collect(dep);
267
0
        }
268
269
        // Merge all source maps into resolve.source_map upfront so that every
270
        // span produced during toposort and duplicate detection is valid in
271
        // resolve.source_map and can be located by rewrite_error below.
272
        // Each group has exactly one source map, so a Vec of offsets suffices.
273
11.0k
        let source_map_offsets: Vec<u32> = source_maps
274
11.0k
            .iter()
275
11.0k
            .map(|sm| self.push_source_map(sm.clone()))
276
11.0k
            .collect();
277
278
11.0k
        let mut pkg_details_map: BTreeMap<PackageName, (UnresolvedPackage, usize)> =
279
11.0k
            BTreeMap::new();
280
11.8k
        for (pkg, source_map_index) in all_packages {
281
11.8k
            let name = pkg.name.clone();
282
11.8k
            let my_span = pkg.package_name_span;
283
11.8k
            let offset = source_map_offsets[source_map_index];
284
0
            if let Some((prev_pkg, prev_source_map_index)) =
285
11.8k
                pkg_details_map.insert(name.clone(), (pkg, source_map_index))
286
            {
287
0
                let prev_offset = source_map_offsets[prev_source_map_index];
288
0
                let mut span1 = my_span;
289
0
                span1.adjust(offset);
290
0
                let mut span2 = prev_pkg.package_name_span;
291
0
                span2.adjust(prev_offset);
292
0
                return Err(ResolveError::from(ResolveErrorKind::DuplicatePackage {
293
0
                    name,
294
0
                    span1,
295
0
                    span2,
296
0
                }));
297
11.8k
            }
298
        }
299
300
        // Perform a simple topological sort which will bail out on cycles
301
        // and otherwise determine the order that packages must be added to
302
        // this `Resolve`.
303
11.0k
        let mut order = IndexSet::default();
304
        {
305
11.0k
            let mut visiting = HashSet::new();
306
11.8k
            for (pkg, _) in pkg_details_map.values() {
307
11.8k
                visit(
308
11.8k
                    pkg,
309
11.8k
                    &pkg_details_map,
310
11.8k
                    &mut order,
311
11.8k
                    &mut visiting,
312
11.8k
                    &source_map_offsets,
313
0
                )?;
314
            }
315
        }
316
317
11.0k
        let mut package_id_to_source_map_idx = BTreeMap::new();
318
11.0k
        let mut main_pkg_id = None;
319
11.8k
        for name in order {
320
11.8k
            let (pkg, source_map_index) = pkg_details_map.remove(&name).unwrap();
321
11.8k
            let span_offset = source_map_offsets[source_map_index];
322
11.8k
            let is_main = pkg.name == main_name;
323
11.8k
            let id = self.push(pkg, span_offset)?;
324
11.8k
            if is_main {
325
11.0k
                assert!(main_pkg_id.is_none());
326
11.0k
                main_pkg_id = Some(id);
327
766
            }
328
11.8k
            package_id_to_source_map_idx.insert(id, source_map_index);
329
        }
330
331
11.0k
        Ok((
332
11.0k
            main_pkg_id.unwrap(),
333
11.0k
            PackageSources::from_source_maps(source_maps, package_id_to_source_map_idx),
334
11.0k
        ))
335
11.0k
    }
336
337
    /// Appends a source map to this [`Resolve`]'s internal source map.
338
    ///
339
    /// Returns the byte offset that should be passed to [`Resolve::push`] for
340
    /// packages parsed from this source map. This offset ensures that spans
341
    /// in the resolved package point to the correct location in the combined
342
    /// source map.
343
11.0k
    pub fn push_source_map(&mut self, source_map: SourceMap) -> u32 {
344
11.0k
        self.source_map.append(source_map)
345
11.0k
    }
346
347
    /// Appends a new [`UnresolvedPackage`] to this [`Resolve`], creating a
348
    /// fully resolved package with no dangling references.
349
    ///
350
    /// All the dependencies of `unresolved` must already have been loaded
351
    /// within this `Resolve` via previous calls to `push` or other methods such
352
    /// as [`Resolve::push_path`].
353
    ///
354
    /// The `span_offset` should be the value returned by
355
    /// [`Resolve::push_source_map`] if the source map was appended to this
356
    /// resolve, or `0` if this is a standalone package.
357
    ///
358
    /// Any dependency resolution error or otherwise world-elaboration error
359
    /// will be returned here, if successful a package identifier is returned
360
    /// which corresponds to the package that was just inserted.
361
11.8k
    pub fn push(
362
11.8k
        &mut self,
363
11.8k
        mut unresolved: UnresolvedPackage,
364
11.8k
        span_offset: u32,
365
11.8k
    ) -> ResolveResult<PackageId> {
366
11.8k
        unresolved.adjust_spans(span_offset);
367
11.8k
        let ret = Remap::default().append(self, unresolved);
368
11.8k
        if ret.is_ok() {
369
11.8k
            #[cfg(debug_assertions)]
370
11.8k
            self.assert_valid();
371
11.8k
        }
372
11.8k
        ret
373
11.8k
    }
374
375
    /// Appends new [`UnresolvedPackageGroup`] to this [`Resolve`], creating a
376
    /// fully resolved package with no dangling references.
377
    ///
378
    /// Any dependency resolution error or otherwise world-elaboration error
379
    /// will be returned here, if successful a package identifier is returned
380
    /// which corresponds to the package that was just inserted.
381
    ///
382
    /// On error, `self` may be partially modified and should not be reused.
383
11.0k
    pub fn push_group(
384
11.0k
        &mut self,
385
11.0k
        unresolved_group: UnresolvedPackageGroup,
386
11.0k
    ) -> ResolveResult<PackageId> {
387
11.0k
        let (pkg_id, _) = self.sort_unresolved_packages(unresolved_group, Vec::new())?;
388
11.0k
        Ok(pkg_id)
389
11.0k
    }
390
391
    /// Appends a main [`UnresolvedPackageGroup`] and its dependencies to this
392
    /// [`Resolve`] in a single call, topologically sorting them internally.
393
    ///
394
    /// This is useful when you have a package and its local dependencies
395
    /// available as in-memory [`UnresolvedPackageGroup`]s and want dependency
396
    /// ordering and cycle detection handled automatically.
397
    ///
398
    /// The returned [`PackageId`] corresponds to `main`.
399
    ///
400
    /// On error, `self` may be partially modified and should not be reused.
401
0
    pub fn push_groups(
402
0
        &mut self,
403
0
        main: UnresolvedPackageGroup,
404
0
        deps: Vec<UnresolvedPackageGroup>,
405
0
    ) -> ResolveResult<PackageId> {
406
0
        let (pkg_id, _) = self.sort_unresolved_packages(main, deps)?;
407
0
        Ok(pkg_id)
408
0
    }
409
410
    /// Convenience method for combining [`SourceMap`] and [`Resolve::push_group`].
411
    ///
412
    /// The `path` provided is used for error messages but otherwise is not
413
    /// read. This method does not touch the filesystem. The `contents` provided
414
    /// are the contents of a WIT package.
415
4.13k
    pub fn push_source(&mut self, path: &str, contents: &str) -> anyhow::Result<PackageId> {
416
4.13k
        let mut map = SourceMap::default();
417
4.13k
        map.push_str(path, contents);
418
4.13k
        let group = self.parse_source_map(map)?;
419
4.13k
        Ok(self.push_group(group)?)
420
4.13k
    }
421
422
    /// Parses `map` into an [`UnresolvedPackageGroup`].
423
    ///
424
    /// On parse failure the local [`SourceMap`] is merged into
425
    /// [`Resolve::source_map`] (with the typed [`crate::ParseError`]'s spans
426
    /// adjusted) so the downcasted error remains renderable against
427
    /// `self.source_map`.
428
4.13k
    pub(crate) fn parse_source_map(
429
4.13k
        &mut self,
430
4.13k
        map: SourceMap,
431
4.13k
    ) -> anyhow::Result<UnresolvedPackageGroup> {
432
4.13k
        map.parse().map_err(|(map, mut e)| {
433
0
            let offset = self.source_map.append(map);
434
0
            e.adjust_spans(offset);
435
0
            e.into()
436
0
        })
437
4.13k
    }
438
439
    /// Renders a span as a human-readable location string (e.g., "file.wit:10:5").
440
0
    pub fn render_location(&self, span: Span) -> String {
441
0
        self.source_map.render_location(span)
442
0
    }
443
444
    /// Renders an error returned by this [`Resolve`]'s `push_*` methods with
445
    /// source context (file:line:col + snippet).
446
    #[cfg(feature = "std")]
447
0
    pub fn render_error(&self, err: &anyhow::Error) -> String {
448
0
        crate::render_anyhow_error(err, &self.source_map)
449
0
    }
450
451
0
    pub fn all_bits_valid(&self, ty: &Type) -> bool {
452
0
        match ty {
453
            Type::U8
454
            | Type::S8
455
            | Type::U16
456
            | Type::S16
457
            | Type::U32
458
            | Type::S32
459
            | Type::U64
460
            | Type::S64
461
            | Type::F32
462
0
            | Type::F64 => true,
463
464
0
            Type::Bool | Type::Char | Type::String | Type::ErrorContext => false,
465
466
0
            Type::Id(id) => match &self.types[*id].kind {
467
                TypeDefKind::List(_)
468
                | TypeDefKind::Map(_, _)
469
                | TypeDefKind::Variant(_)
470
                | TypeDefKind::Enum(_)
471
                | TypeDefKind::Option(_)
472
                | TypeDefKind::Result(_)
473
                | TypeDefKind::Future(_)
474
0
                | TypeDefKind::Stream(_) => false,
475
0
                TypeDefKind::Type(t) | TypeDefKind::FixedLengthList(t, ..) => {
476
0
                    self.all_bits_valid(t)
477
                }
478
479
0
                TypeDefKind::Handle(h) => match h {
480
0
                    crate::Handle::Own(_) => true,
481
0
                    crate::Handle::Borrow(_) => true,
482
                },
483
484
0
                TypeDefKind::Resource => false,
485
0
                TypeDefKind::Record(r) => r.fields.iter().all(|f| self.all_bits_valid(&f.ty)),
486
0
                TypeDefKind::Tuple(t) => t.types.iter().all(|t| self.all_bits_valid(t)),
487
488
                // FIXME: this could perhaps be `true` for multiples-of-32 but
489
                // seems better to probably leave this as unconditionally
490
                // `false` for now, may want to reconsider later?
491
0
                TypeDefKind::Flags(_) => false,
492
493
0
                TypeDefKind::Unknown => unreachable!(),
494
            },
495
        }
496
0
    }
497
498
    /// Merges all the contents of a different `Resolve` into this one. The
499
    /// `Remap` structure returned provides a mapping from all old indices to
500
    /// new indices
501
    ///
502
    /// This operation can fail if `resolve` disagrees with `self` about the
503
    /// packages being inserted. Otherwise though this will additionally attempt
504
    /// to "union" packages found in `resolve` with those found in `self`.
505
    /// Unioning packages is keyed on the name/url of packages for those with
506
    /// URLs present. If found then it's assumed that both `Resolve` instances
507
    /// were originally created from the same contents and are two views
508
    /// of the same package.
509
6.55k
    pub fn merge(&mut self, resolve: Resolve) -> anyhow::Result<Remap> {
510
6.55k
        log::trace!(
511
            "merging {} packages into {} packages",
512
0
            resolve.packages.len(),
513
0
            self.packages.len()
514
        );
515
516
6.55k
        let mut map = MergeMap::new(&resolve, &self);
517
6.55k
        map.build()?;
518
        let MergeMap {
519
6.55k
            package_map,
520
6.55k
            interface_map,
521
6.55k
            type_map,
522
6.55k
            world_map,
523
6.55k
            interfaces_to_add,
524
6.55k
            worlds_to_add,
525
            ..
526
6.55k
        } = map;
527
528
        // With a set of maps from ids in `resolve` to ids in `self` the next
529
        // operation is to start moving over items and building a `Remap` to
530
        // update ids.
531
        //
532
        // Each component field of `resolve` is moved into `self` so long as
533
        // its ID is not within one of the maps above. If it's present in a map
534
        // above then that means the item is already present in `self` so a new
535
        // one need not be added. If it's not present in a map that means it's
536
        // not present in `self` so it must be added to an arena.
537
        //
538
        // When adding an item to an arena one of the `remap.update_*` methods
539
        // is additionally called to update all identifiers from pointers within
540
        // `resolve` to becoming pointers within `self`.
541
        //
542
        // Altogether this should weave all the missing items in `self` from
543
        // `resolve` into one structure while updating all identifiers to
544
        // be local within `self`.
545
546
6.55k
        let mut remap = Remap::default();
547
        let Resolve {
548
6.55k
            types,
549
6.55k
            worlds,
550
6.55k
            interfaces,
551
6.55k
            packages,
552
6.55k
            package_names,
553
            features: _,
554
6.55k
            source_map,
555
            ..
556
6.55k
        } = resolve;
557
558
6.55k
        let span_offset = self.source_map.append(source_map);
559
560
6.55k
        let mut moved_types = Vec::new();
561
39.4k
        for (id, mut ty) in types {
562
39.4k
            let new_id = match type_map.get(&id).copied() {
563
119
                Some(id) => {
564
119
                    update_stability(&ty.stability, &mut self.types[id].stability, ty.span)?;
565
119
                    id
566
                }
567
                None => {
568
39.3k
                    log::debug!("moving type {:?}", ty.name);
569
39.3k
                    moved_types.push(id);
570
39.3k
                    remap.update_typedef(self, &mut ty, Default::default())?;
571
39.3k
                    ty.adjust_spans(span_offset);
572
39.3k
                    self.types.alloc(ty)
573
                }
574
            };
575
39.4k
            assert_eq!(remap.types.len(), id.index());
576
39.4k
            remap.types.push(Some(new_id));
577
        }
578
579
6.55k
        let mut moved_interfaces = Vec::new();
580
6.55k
        for (id, mut iface) in interfaces {
581
3.72k
            let new_id = match interface_map.get(&id).copied() {
582
35
                Some(into_id) => {
583
35
                    update_stability(
584
35
                        &iface.stability,
585
35
                        &mut self.interfaces[into_id].stability,
586
35
                        iface.span,
587
0
                    )?;
588
589
                    // Add any extra types from `from`'s interface that
590
                    // don't exist in `into`'s interface. These types were
591
                    // already moved as new types above (since they weren't
592
                    // in `type_map`), but they still need to be registered
593
                    // in the target interface's `types` map.
594
119
                    for (name, from_type_id) in iface.types.iter() {
595
119
                        if self.interfaces[into_id].types.contains_key(name) {
596
119
                            continue;
597
0
                        }
598
0
                        let new_type_id = remap.map_type(*from_type_id, Default::default())?;
599
0
                        self.interfaces[into_id]
600
0
                            .types
601
0
                            .insert(name.clone(), new_type_id);
602
                    }
603
604
                    // Add any extra functions from `from`'s interface that
605
                    // don't exist in `into`'s interface. These need their
606
                    // type references remapped and spans adjusted.
607
35
                    let extra_funcs: Vec<_> = iface
608
35
                        .functions
609
35
                        .into_iter()
610
35
                        .filter(|(name, _)| {
611
19
                            !self.interfaces[into_id]
612
19
                                .functions
613
19
                                .contains_key(name.as_str())
614
19
                        })
615
35
                        .collect();
616
35
                    for (name, mut func) in extra_funcs {
617
0
                        remap.update_function(self, &mut func, Default::default())?;
618
0
                        func.adjust_spans(span_offset);
619
0
                        self.interfaces[into_id].functions.insert(name, func);
620
                    }
621
622
35
                    into_id
623
                }
624
                None => {
625
3.69k
                    log::debug!("moving interface {:?}", iface.name);
626
3.69k
                    moved_interfaces.push(id);
627
3.69k
                    remap.update_interface(self, &mut iface)?;
628
3.69k
                    iface.adjust_spans(span_offset);
629
3.69k
                    self.interfaces.alloc(iface)
630
                }
631
            };
632
3.72k
            assert_eq!(remap.interfaces.len(), id.index());
633
3.72k
            remap.interfaces.push(Some(new_id));
634
        }
635
636
6.55k
        let mut moved_worlds = Vec::new();
637
9.79k
        for (id, mut world) in worlds {
638
9.79k
            let new_id = match world_map.get(&id).copied() {
639
0
                Some(world_id) => {
640
0
                    update_stability(
641
0
                        &world.stability,
642
0
                        &mut self.worlds[world_id].stability,
643
0
                        world.span,
644
0
                    )?;
645
0
                    for from_import in world.imports.iter() {
646
0
                        Resolve::update_world_imports_stability(
647
0
                            from_import,
648
0
                            &mut self.worlds[world_id].imports,
649
0
                            &interface_map,
650
0
                        )?;
651
                    }
652
0
                    for from_export in world.exports.iter() {
653
0
                        Resolve::update_world_imports_stability(
654
0
                            from_export,
655
0
                            &mut self.worlds[world_id].exports,
656
0
                            &interface_map,
657
0
                        )?;
658
                    }
659
0
                    world_id
660
                }
661
                None => {
662
9.79k
                    log::debug!("moving world {}", world.name);
663
9.79k
                    moved_worlds.push(id);
664
9.79k
                    let mut update =
665
19.5k
                        |map: &mut IndexMap<WorldKey, WorldItem>| -> anyhow::Result<_> {
666
22.5k
                            for (mut name, mut item) in mem::take(map) {
667
22.5k
                                remap.update_world_key(&mut name, Default::default())?;
668
22.5k
                                match &mut item {
669
2.67k
                                    WorldItem::Function(f) => {
670
2.67k
                                        remap.update_function(self, f, Default::default())?
671
                                    }
672
16.2k
                                    WorldItem::Interface { id, .. } => {
673
16.2k
                                        *id = remap.map_interface(*id, Default::default())?;
674
                                    }
675
3.58k
                                    WorldItem::Type { id, .. } => {
676
3.58k
                                        *id = remap.map_type(*id, Default::default())?
677
                                    }
678
                                }
679
22.5k
                                map.insert(name, item);
680
                            }
681
19.5k
                            Ok(())
682
19.5k
                        };
683
9.79k
                    update(&mut world.imports)?;
684
9.79k
                    update(&mut world.exports)?;
685
9.79k
                    world.adjust_spans(span_offset);
686
9.79k
                    self.worlds.alloc(world)
687
                }
688
            };
689
9.79k
            assert_eq!(remap.worlds.len(), id.index());
690
9.79k
            remap.worlds.push(Some(new_id));
691
        }
692
693
11.0k
        for (id, mut pkg) in packages {
694
11.0k
            let new_id = match package_map.get(&id).copied() {
695
35
                Some(id) => id,
696
                None => {
697
11.0k
                    for (_, id) in pkg.interfaces.iter_mut() {
698
2.51k
                        *id = remap.map_interface(*id, Default::default())?;
699
                    }
700
11.0k
                    for (_, id) in pkg.worlds.iter_mut() {
701
9.79k
                        *id = remap.map_world(*id, Default::default())?;
702
                    }
703
11.0k
                    self.packages.alloc(pkg)
704
                }
705
            };
706
11.0k
            assert_eq!(remap.packages.len(), id.index());
707
11.0k
            remap.packages.push(new_id);
708
        }
709
710
7.85k
        for (name, id) in package_names {
711
7.85k
            let id = remap.packages[id.index()];
712
7.85k
            if let Some(prev) = self.package_names.insert(name, id) {
713
35
                assert_eq!(prev, id);
714
7.81k
            }
715
        }
716
717
        // Fixup all "parent" links now.
718
        //
719
        // Note that this is only done for items that are actually moved from
720
        // `resolve` into `self`, which is tracked by the various `moved_*`
721
        // lists built incrementally above. The ids in the `moved_*` lists
722
        // are ids within `resolve`, so they're translated through `remap` to
723
        // ids within `self`.
724
9.79k
        for id in moved_worlds {
725
9.79k
            let id = remap.map_world(id, Default::default())?;
726
9.79k
            if let Some(pkg) = self.worlds[id].package.as_mut() {
727
9.79k
                *pkg = remap.packages[pkg.index()];
728
9.79k
            }
729
        }
730
6.55k
        for id in moved_interfaces {
731
3.69k
            let id = remap.map_interface(id, Default::default())?;
732
3.69k
            if let Some(pkg) = self.interfaces[id].package.as_mut() {
733
3.69k
                *pkg = remap.packages[pkg.index()];
734
3.69k
            }
735
3.69k
            if let Some(clone_of) = self.interfaces[id].clone_of.as_mut() {
736
392
                *clone_of = remap.map_interface(*clone_of, Default::default())?;
737
3.29k
            }
738
        }
739
39.3k
        for id in moved_types {
740
39.3k
            let id = remap.map_type(id, Default::default())?;
741
39.3k
            match &mut self.types[id].owner {
742
10.7k
                TypeOwner::Interface(id) => *id = remap.map_interface(*id, Default::default())?,
743
3.58k
                TypeOwner::World(id) => *id = remap.map_world(*id, Default::default())?,
744
25.0k
                TypeOwner::None => {}
745
            }
746
        }
747
748
        // And finally process items that were present in `resolve` but were
749
        // not present in `self`. This is only done for merged packages as
750
        // documents may be added to `self.documents` but wouldn't otherwise be
751
        // present in the `documents` field of the corresponding package.
752
6.55k
        for (name, pkg, iface) in interfaces_to_add {
753
3
            let prev = self.packages[pkg]
754
3
                .interfaces
755
3
                .insert(name, remap.map_interface(iface, Default::default())?);
756
3
            assert!(prev.is_none());
757
        }
758
6.55k
        for (name, pkg, world) in worlds_to_add {
759
0
            let prev = self.packages[pkg]
760
0
                .worlds
761
0
                .insert(name, remap.map_world(world, Default::default())?);
762
0
            assert!(prev.is_none());
763
        }
764
765
6.55k
        log::trace!("now have {} packages", self.packages.len());
766
767
        // Re-elaborate all worlds after the merge. Merging may have added
768
        // extra types to existing interfaces that introduce new interface
769
        // dependencies not yet present in the world's imports.
770
6.55k
        let world_ids: Vec<_> = self.worlds.iter().map(|(id, _)| id).collect();
771
16.3k
        for world_id in world_ids {
772
16.3k
            let world_span = self.worlds[world_id].span;
773
16.3k
            self.elaborate_world(world_id, world_span)?;
774
        }
775
776
        #[cfg(debug_assertions)]
777
        self.assert_valid();
778
6.55k
        Ok(remap)
779
6.55k
    }
780
781
0
    fn update_world_imports_stability(
782
0
        from_item: (&WorldKey, &WorldItem),
783
0
        into_items: &mut IndexMap<WorldKey, WorldItem>,
784
0
        interface_map: &HashMap<Id<Interface>, Id<Interface>>,
785
0
    ) -> anyhow::Result<()> {
786
0
        match from_item.0 {
787
            WorldKey::Name(_) => {
788
                // No stability info to update here, only updating import/include stability
789
0
                Ok(())
790
            }
791
0
            key @ WorldKey::Interface(_) => {
792
0
                let new_key = MergeMap::map_name(key, interface_map);
793
0
                if let Some(into) = into_items.get_mut(&new_key) {
794
0
                    match (from_item.1, into) {
795
                        (
796
                            WorldItem::Interface {
797
0
                                id: aid,
798
0
                                stability: astability,
799
0
                                span: aspan,
800
                                ..
801
                            },
802
                            WorldItem::Interface {
803
0
                                id: bid,
804
0
                                stability: bstability,
805
                                ..
806
                            },
807
                        ) => {
808
0
                            let aid = interface_map.get(aid).copied().unwrap_or(*aid);
809
0
                            assert_eq!(aid, *bid);
810
0
                            update_stability(astability, bstability, *aspan)?;
811
0
                            Ok(())
812
                        }
813
0
                        _ => unreachable!(),
814
                    }
815
                } else {
816
                    // we've already matched all the imports/exports by the time we are calling this
817
                    // so this is unreachable since we should always find the item
818
0
                    unreachable!()
819
                }
820
            }
821
        }
822
0
    }
823
824
    /// Merges the world `from` into the world `into`.
825
    ///
826
    /// This will attempt to merge one world into another, unioning all of its
827
    /// imports and exports together. This is an operation performed by
828
    /// `wit-component`, for example where two different worlds from two
829
    /// different libraries were linked into the same core wasm file and are
830
    /// producing a singular world that will be the final component's
831
    /// interface.
832
    ///
833
    /// During the merge operation, some of the types and/or interfaces in
834
    /// `from` might need to be cloned so that backreferences point to `into`
835
    /// instead of `from`.  Any such clones will be added to `clone_maps`.
836
    ///
837
    /// This operation can fail if the imports/exports overlap.
838
6.46k
    pub fn merge_worlds(
839
6.46k
        &mut self,
840
6.46k
        from: WorldId,
841
6.46k
        into: WorldId,
842
6.46k
        clone_maps: &mut CloneMaps,
843
6.46k
    ) -> anyhow::Result<()> {
844
6.46k
        let mut new_imports = Vec::new();
845
6.46k
        let mut new_exports = Vec::new();
846
847
6.46k
        let from_world = &self.worlds[from];
848
6.46k
        let into_world = &self.worlds[into];
849
850
6.46k
        log::trace!("merging {} into {}", from_world.name, into_world.name);
851
852
        // First walk over all the imports of `from` world and figure out what
853
        // to do with them.
854
        //
855
        // If the same item exists in `from` and `into` then merge it together
856
        // below with `merge_world_item` which basically asserts they're the
857
        // same. Otherwise queue up a new import since if `from` has more
858
        // imports than `into` then it's fine to add new imports.
859
6.46k
        for (name, from_import) in from_world.imports.iter() {
860
5.41k
            let name_str = self.name_world_key(name);
861
5.41k
            match into_world.imports.get(name) {
862
0
                Some(into_import) => {
863
0
                    log::trace!("info/from shared import on `{name_str}`");
864
0
                    self.merge_world_item(from_import, into_import)
865
0
                        .with_context(|| format!("failed to merge world import {name_str}"))?;
866
                }
867
                None => {
868
5.41k
                    log::trace!("new import: `{name_str}`");
869
5.41k
                    new_imports.push((name.clone(), from_import.clone()));
870
                }
871
            }
872
        }
873
874
        // Build a set of interfaces which are required to be imported because
875
        // of `into`'s exports. This set is then used below during
876
        // `ensure_can_add_world_export`.
877
        //
878
        // This is the set of interfaces which exports depend on that are
879
        // themselves not exports.
880
6.46k
        let mut must_be_imported = HashMap::new();
881
6.46k
        for (key, export) in into_world.exports.iter() {
882
0
            for dep in self.world_item_direct_deps(export) {
883
0
                if into_world.exports.contains_key(&WorldKey::Interface(dep)) {
884
0
                    continue;
885
0
                }
886
0
                self.foreach_interface_dep(dep, &mut |id| {
887
0
                    must_be_imported.insert(id, key.clone());
888
0
                });
889
            }
890
        }
891
892
        // Next walk over exports of `from` and process these similarly to
893
        // imports.
894
9.42k
        for (name, from_export) in from_world.exports.iter() {
895
9.42k
            let name_str = self.name_world_key(name);
896
9.42k
            match into_world.exports.get(name) {
897
0
                Some(into_export) => {
898
0
                    log::trace!("info/from shared export on `{name_str}`");
899
0
                    self.merge_world_item(from_export, into_export)
900
0
                        .with_context(|| format!("failed to merge world export {name_str}"))?;
901
                }
902
                None => {
903
9.42k
                    log::trace!("new export `{name_str}`");
904
                    // See comments in `ensure_can_add_world_export` for why
905
                    // this is slightly different than imports.
906
9.42k
                    self.ensure_can_add_world_export(
907
9.42k
                        into_world,
908
9.42k
                        name,
909
9.42k
                        from_export,
910
9.42k
                        &must_be_imported,
911
                    )
912
9.42k
                    .with_context(|| {
913
0
                        format!("failed to add export `{}`", self.name_world_key(name))
914
0
                    })?;
915
9.42k
                    new_exports.push((name.clone(), from_export.clone()));
916
                }
917
            }
918
        }
919
920
        // For all the new imports and exports they may need to be "cloned" to
921
        // be able to belong to the new world. For example:
922
        //
923
        // * Anonymous interfaces have a `package` field which points to the
924
        //   package of the containing world, but `from` and `into` may not be
925
        //   in the same package.
926
        //
927
        // * Type imports have an `owner` field that point to `from`, but they
928
        //   now need to point to `into` instead.
929
        //
930
        // Cloning is no trivial task, however, so cloning is delegated to a
931
        // submodule to perform a "deep" clone and copy items into new arena
932
        // entries as necessary.
933
6.46k
        let mut cloner = clone::Cloner::new(
934
6.46k
            self,
935
6.46k
            clone_maps,
936
6.46k
            TypeOwner::World(from),
937
6.46k
            TypeOwner::World(into),
938
        );
939
6.46k
        cloner.register_world_type_overlap(from, into);
940
14.8k
        for (name, item) in new_imports.iter_mut().chain(&mut new_exports) {
941
14.8k
            cloner.world_item(name, item);
942
14.8k
        }
943
944
        // Insert any new imports and new exports found first.
945
6.46k
        let into_world = &mut self.worlds[into];
946
6.46k
        for (name, import) in new_imports {
947
5.41k
            let prev = into_world.imports.insert(name, import);
948
5.41k
            assert!(prev.is_none());
949
        }
950
9.42k
        for (name, export) in new_exports {
951
9.42k
            let prev = into_world.exports.insert(name, export);
952
9.42k
            assert!(prev.is_none());
953
        }
954
955
        #[cfg(debug_assertions)]
956
        self.assert_valid();
957
6.46k
        Ok(())
958
6.46k
    }
959
960
0
    fn merge_world_item(&self, from: &WorldItem, into: &WorldItem) -> anyhow::Result<()> {
961
0
        let mut map = MergeMap::new(self, self);
962
0
        match (from, into) {
963
0
            (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
964
                // If these imports are the same that can happen, for
965
                // example, when both worlds to `import foo:bar/baz;`. That
966
                // foreign interface will point to the same interface within
967
                // `Resolve`.
968
0
                if from == into {
969
0
                    return Ok(());
970
0
                }
971
972
                // .. otherwise this MUST be a case of
973
                // `import foo: interface { ... }`. If `from != into` but
974
                // both `from` and `into` have the same name then the
975
                // `WorldKey::Interface` case is ruled out as otherwise
976
                // they'd have different names.
977
                //
978
                // In the case of an anonymous interface all we can do is
979
                // ensure that the interfaces both match, so use `MergeMap`
980
                // for that.
981
0
                map.build_interface(*from, *into)
982
0
                    .context("failed to merge interfaces")?;
983
            }
984
985
            // Like `WorldKey::Name` interfaces for functions and types the
986
            // structure is asserted to be the same.
987
0
            (WorldItem::Function(from), WorldItem::Function(into)) => {
988
0
                map.build_function(from, into)
989
0
                    .context("failed to merge functions")?;
990
            }
991
0
            (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
992
0
                map.build_type_id(*from, *into)
993
0
                    .context("failed to merge types")?;
994
            }
995
996
            // Kind-level mismatches are caught here.
997
            (WorldItem::Interface { .. }, _)
998
            | (WorldItem::Function { .. }, _)
999
            | (WorldItem::Type { .. }, _) => {
1000
0
                bail!("different kinds of items");
1001
            }
1002
        }
1003
0
        assert!(map.interfaces_to_add.is_empty());
1004
0
        assert!(map.worlds_to_add.is_empty());
1005
0
        Ok(())
1006
0
    }
1007
1008
    /// This method ensures that the world export of `name` and `item` can be
1009
    /// added to the world `into` without changing the meaning of `into`.
1010
    ///
1011
    /// All dependencies of world exports must either be:
1012
    ///
1013
    /// * An export themselves
1014
    /// * An import with all transitive dependencies of the import also imported
1015
    ///
1016
    /// It's not possible to depend on an import which then also depends on an
1017
    /// export at some point, for example. This method ensures that if `name`
1018
    /// and `item` are added that this property is upheld.
1019
9.42k
    fn ensure_can_add_world_export(
1020
9.42k
        &self,
1021
9.42k
        into: &World,
1022
9.42k
        name: &WorldKey,
1023
9.42k
        item: &WorldItem,
1024
9.42k
        must_be_imported: &HashMap<InterfaceId, WorldKey>,
1025
9.42k
    ) -> anyhow::Result<()> {
1026
9.42k
        assert!(!into.exports.contains_key(name));
1027
9.42k
        let name = self.name_world_key(name);
1028
1029
        // First make sure that all of this item's dependencies are either
1030
        // exported or the entire chain of imports rooted at that dependency are
1031
        // all imported.
1032
9.42k
        for dep in self.world_item_direct_deps(item) {
1033
1.19k
            if into.exports.contains_key(&WorldKey::Interface(dep)) {
1034
0
                continue;
1035
1.19k
            }
1036
1.19k
            self.ensure_not_exported(into, dep)
1037
1.19k
                .with_context(|| format!("failed validating export of `{name}`"))?;
1038
        }
1039
1040
        // Second make sure that this item, if it's an interface, will not alter
1041
        // the meaning of the preexisting world by ensuring that it's not in the
1042
        // set of "must be imported" items.
1043
9.42k
        if let WorldItem::Interface { id, .. } = item {
1044
8.96k
            if let Some(export) = must_be_imported.get(id) {
1045
0
                let export_name = self.name_world_key(export);
1046
0
                bail!(
1047
                    "export `{export_name}` depends on `{name}` \
1048
                     previously as an import which will change meaning \
1049
                     if `{name}` is added as an export"
1050
                );
1051
8.96k
            }
1052
460
        }
1053
1054
9.42k
        Ok(())
1055
9.42k
    }
1056
1057
1.56k
    fn ensure_not_exported(&self, world: &World, id: InterfaceId) -> anyhow::Result<()> {
1058
1.56k
        let key = WorldKey::Interface(id);
1059
1.56k
        let name = self.name_world_key(&key);
1060
1.56k
        if world.exports.contains_key(&key) {
1061
0
            bail!(
1062
                "world exports `{name}` but it's also transitively used by an \
1063
                     import \
1064
                   which means that this is not valid"
1065
            )
1066
1.56k
        }
1067
1.56k
        for dep in self.interface_direct_deps(id) {
1068
370
            self.ensure_not_exported(world, dep)
1069
370
                .with_context(|| format!("failed validating transitive import dep `{name}`"))?;
1070
        }
1071
1.56k
        Ok(())
1072
1.56k
    }
1073
1074
    /// Returns an iterator of all the direct interface dependencies of this
1075
    /// `item`.
1076
    ///
1077
    /// Note that this doesn't include transitive dependencies, that must be
1078
    /// followed manually.
1079
9.42k
    fn world_item_direct_deps(&self, item: &WorldItem) -> impl Iterator<Item = InterfaceId> + '_ {
1080
9.42k
        let mut interface = None;
1081
9.42k
        let mut ty = None;
1082
9.42k
        match item {
1083
460
            WorldItem::Function(_) => {}
1084
0
            WorldItem::Type { id, .. } => ty = Some(*id),
1085
8.96k
            WorldItem::Interface { id, .. } => interface = Some(*id),
1086
        }
1087
1088
9.42k
        interface
1089
9.42k
            .into_iter()
1090
9.42k
            .flat_map(move |id| self.interface_direct_deps(id))
1091
9.42k
            .chain(ty.and_then(|t| self.type_interface_dep(t)))
1092
9.42k
    }
1093
1094
    /// Invokes `f` with `id` and all transitive interface dependencies of `id`.
1095
    ///
1096
    /// Note that `f` may be called with the same id multiple times.
1097
1.17k
    fn foreach_interface_dep(&self, id: InterfaceId, f: &mut dyn FnMut(InterfaceId)) {
1098
1.17k
        self._foreach_interface_dep(id, f, &mut HashSet::new())
1099
1.17k
    }
1100
1101
    // Internal detail of `foreach_interface_dep` which uses a hash map to prune
1102
    // the visit tree to ensure that this doesn't visit an exponential number of
1103
    // interfaces.
1104
1.51k
    fn _foreach_interface_dep(
1105
1.51k
        &self,
1106
1.51k
        id: InterfaceId,
1107
1.51k
        f: &mut dyn FnMut(InterfaceId),
1108
1.51k
        visited: &mut HashSet<InterfaceId>,
1109
1.51k
    ) {
1110
1.51k
        if !visited.insert(id) {
1111
256
            return;
1112
1.26k
        }
1113
1.26k
        f(id);
1114
1.26k
        for dep in self.interface_direct_deps(id) {
1115
344
            self._foreach_interface_dep(dep, f, visited);
1116
344
        }
1117
1.51k
    }
1118
1119
    /// Returns the ID of the specified `interface`.
1120
    ///
1121
    /// Returns `None` for unnamed interfaces.
1122
69.3k
    pub fn id_of(&self, interface: InterfaceId) -> Option<String> {
1123
69.3k
        let interface = &self.interfaces[interface];
1124
69.3k
        Some(self.id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1125
69.3k
    }
1126
1127
    /// Returns the "canonicalized interface name" of `interface`.
1128
    ///
1129
    /// Returns `None` for unnamed interfaces. See `BuildTargets.md` in the
1130
    /// upstream component model repository for more information about this.
1131
50.5k
    pub fn canonicalized_id_of(&self, interface: InterfaceId) -> Option<String> {
1132
50.5k
        let interface = &self.interfaces[interface];
1133
50.5k
        Some(self.canonicalized_id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
1134
50.5k
    }
1135
1136
    /// Helper to rename a world and update the package's world map.
1137
    ///
1138
    /// Used by both [`Resolve::importize`] and [`Resolve::exportize`] to
1139
    /// rename the world to avoid confusion with the original world name.
1140
3.23k
    fn rename_world(
1141
3.23k
        &mut self,
1142
3.23k
        world_id: WorldId,
1143
3.23k
        out_world_name: Option<String>,
1144
3.23k
        default_suffix: &str,
1145
3.23k
    ) {
1146
3.23k
        let world = &mut self.worlds[world_id];
1147
3.23k
        let pkg = &mut self.packages[world.package.unwrap()];
1148
3.23k
        pkg.worlds.shift_remove(&world.name);
1149
3.23k
        if let Some(name) = out_world_name {
1150
0
            world.name = name.clone();
1151
0
            pkg.worlds.insert(name, world_id);
1152
3.23k
        } else {
1153
3.23k
            world.name.push_str(default_suffix);
1154
3.23k
            pkg.worlds.insert(world.name.clone(), world_id);
1155
3.23k
        }
1156
3.23k
    }
1157
1158
    /// Convert a world to an "importized" version where the world is updated
1159
    /// in-place to reflect what it would look like to be imported.
1160
    ///
1161
    /// This is a transformation which is used as part of the process of
1162
    /// importing a component today. For example when a component depends on
1163
    /// another component this is useful for generating WIT which can be use to
1164
    /// represent the component being imported. The general idea is that this
1165
    /// function will update the `world_id` specified such it imports the
1166
    /// functionality that it previously exported. The world will be left with
1167
    /// no exports.
1168
    ///
1169
    /// This world is then suitable for merging into other worlds or generating
1170
    /// bindings in a context that is importing the original world. This
1171
    /// is intended to be used as part of language tooling when depending on
1172
    /// other components.
1173
3.23k
    pub fn importize(
1174
3.23k
        &mut self,
1175
3.23k
        world_id: WorldId,
1176
3.23k
        out_world_name: Option<String>,
1177
3.23k
    ) -> anyhow::Result<()> {
1178
3.23k
        self.rename_world(world_id, out_world_name, "-importized");
1179
1180
        // Trim all non-type definitions from imports. Types can be used by
1181
        // exported functions, for example, so they're preserved.
1182
3.23k
        let world = &mut self.worlds[world_id];
1183
3.23k
        world.imports.retain(|_, item| match item {
1184
1.18k
            WorldItem::Type { .. } => true,
1185
1.52k
            _ => false,
1186
2.70k
        });
1187
1188
4.54k
        for (name, export) in mem::take(&mut world.exports) {
1189
4.54k
            match (name.clone(), world.imports.insert(name, export)) {
1190
                // no previous item? this insertion was ok
1191
4.42k
                (_, None) => {}
1192
1193
                // cannot overwrite an import with an export
1194
121
                (WorldKey::Name(name), Some(_)) => {
1195
121
                    bail!("world export `{name}` conflicts with import of same name");
1196
                }
1197
1198
                // Exports already don't overlap each other and the only imports
1199
                // preserved above were types so this shouldn't be reachable.
1200
0
                (WorldKey::Interface(_), _) => unreachable!(),
1201
            }
1202
        }
1203
1204
        // Fill out any missing transitive interface imports by elaborating this
1205
        // world which does that for us.
1206
3.11k
        let world_span = world.span;
1207
3.11k
        self.elaborate_world(world_id, world_span)?;
1208
1209
        #[cfg(debug_assertions)]
1210
        self.assert_valid();
1211
3.11k
        Ok(())
1212
3.23k
    }
1213
1214
    /// Convert a world to an "exportized" version where the world is updated
1215
    /// in-place to reflect what it would look like to be exported.
1216
    ///
1217
    /// This is the inverse of [`Resolve::importize`]. The general idea is that
1218
    /// this function will update the `world_id` specified such that it exports
1219
    /// the functionality that it previously imported. The world will be left
1220
    /// with no imports (except for transitive interface dependencies which may
1221
    /// be needed by exported interfaces).
1222
    ///
1223
    /// An optional `filter` can be provided to control which imports are moved.
1224
    /// When `Some`, only imports for which the filter returns `true` are moved
1225
    /// to exports; remaining imports are left as-is. When `None`, all imports
1226
    /// are moved.
1227
    ///
1228
    /// This world is then suitable for merging into other worlds or generating
1229
    /// bindings in a context that is exporting the original world. This is
1230
    /// intended to be used as part of language tooling when implementing
1231
    /// components.
1232
0
    pub fn exportize(
1233
0
        &mut self,
1234
0
        world_id: WorldId,
1235
0
        out_world_name: Option<String>,
1236
0
        filter: Option<&dyn Fn(&WorldKey, &WorldItem) -> bool>,
1237
0
    ) -> anyhow::Result<()> {
1238
0
        self.rename_world(world_id, out_world_name, "-exportized");
1239
1240
0
        let world = &mut self.worlds[world_id];
1241
0
        world.exports.clear();
1242
1243
0
        let old_imports = mem::take(&mut world.imports);
1244
0
        for (name, import) in old_imports {
1245
0
            let should_move = match &filter {
1246
0
                Some(f) => f(&name, &import),
1247
0
                None => true,
1248
            };
1249
0
            if should_move {
1250
0
                world.exports.insert(name, import);
1251
0
            } else {
1252
0
                world.imports.insert(name, import);
1253
0
            }
1254
        }
1255
1256
        // Fill out any missing transitive interface imports by elaborating this
1257
        // world which does that for us.
1258
0
        let world_span = world.span;
1259
0
        self.elaborate_world(world_id, world_span)?;
1260
1261
        #[cfg(debug_assertions)]
1262
        self.assert_valid();
1263
0
        Ok(())
1264
0
    }
1265
1266
    /// Returns the ID of the specified `name` within the `pkg`.
1267
72.5k
    pub fn id_of_name(&self, pkg: PackageId, name: &str) -> String {
1268
72.5k
        let package = &self.packages[pkg];
1269
72.5k
        let mut base = String::new();
1270
72.5k
        base.push_str(&package.name.namespace);
1271
72.5k
        base.push_str(":");
1272
72.5k
        base.push_str(&package.name.name);
1273
72.5k
        base.push_str("/");
1274
72.5k
        base.push_str(name);
1275
72.5k
        if let Some(version) = &package.name.version {
1276
59.5k
            base.push_str(&format!("@{version}"));
1277
59.5k
        }
1278
72.5k
        base
1279
72.5k
    }
1280
1281
    /// Returns the "canonicalized interface name" of the specified `name`
1282
    /// within the `pkg`.
1283
    ///
1284
    /// See `BuildTargets.md` in the upstream component model repository for
1285
    /// more information about this.
1286
50.5k
    pub fn canonicalized_id_of_name(&self, pkg: PackageId, name: &str) -> String {
1287
50.5k
        let package = &self.packages[pkg];
1288
50.5k
        let mut base = String::new();
1289
50.5k
        base.push_str(&package.name.namespace);
1290
50.5k
        base.push_str(":");
1291
50.5k
        base.push_str(&package.name.name);
1292
50.5k
        base.push_str("/");
1293
50.5k
        base.push_str(name);
1294
50.5k
        if let Some(version) = &package.name.version {
1295
44.8k
            base.push_str("@");
1296
44.8k
            let (string, _) = PackageName::version_compat_track_string(version);
1297
44.8k
            base.push_str(&string);
1298
44.8k
        }
1299
50.5k
        base
1300
50.5k
    }
1301
1302
    /// Selects a world from among the packages in a `Resolve`.
1303
    ///
1304
    /// A `Resolve` may have many packages, each with many worlds. Many WIT
1305
    /// tools need a specific world to operate on. This function chooses a
1306
    /// world, failing if the choice is ambiguous.
1307
    ///
1308
    /// `main_packages` provides the package IDs returned by
1309
    /// [`push_path`](Resolve::push_path), [`push_dir`](Resolve::push_dir),
1310
    /// [`push_file`](Resolve::push_file), [`push_group`](Resolve::push_group),
1311
    /// and [`push_str`](Resolve::push_str), which are the "main packages",
1312
    /// as distinguished from any packages nested inside them.
1313
    ///
1314
    /// `world` is a world name such as from a `--world` command-line option or
1315
    /// a `world:` macro parameter. `world` can be:
1316
    ///
1317
    /// * A kebab-name of a world, for example `"the-world"`. It is resolved
1318
    ///   within the "main package", if there is exactly one.
1319
    ///
1320
    /// * An ID-based form of a world, for example `"wasi:http/proxy"`. Note
1321
    ///   that a version does not need to be specified in this string if
1322
    ///   there's only one package of the same name and it has a version. In
1323
    ///   this situation the version can be omitted.
1324
    ///
1325
    /// * `None`. If there's exactly one "main package" and it contains exactly
1326
    ///   one world, that world is chosen.
1327
    ///
1328
    /// If successful, the chosen `WorldId` is returned.
1329
    ///
1330
    /// # Examples
1331
    ///
1332
    /// ```
1333
    /// use anyhow::Result;
1334
    /// use wit_parser::Resolve;
1335
    ///
1336
    /// fn main() -> Result<()> {
1337
    ///     let mut resolve = Resolve::default();
1338
    ///
1339
    ///     // If there's a single package and only one world, that world is
1340
    ///     // the obvious choice.
1341
    ///     let wit1 = resolve.push_str(
1342
    ///         "./my-test.wit",
1343
    ///         r#"
1344
    ///             package example:wit1;
1345
    ///
1346
    ///             world foo {
1347
    ///                 // ...
1348
    ///             }
1349
    ///         "#,
1350
    ///     )?;
1351
    ///     assert!(resolve.select_world(&[wit1], None).is_ok());
1352
    ///
1353
    ///     // If there are multiple packages, we need to be told which package
1354
    ///     // to use, either by a "main package" or by a fully-qualified name.
1355
    ///     let wit2 = resolve.push_str(
1356
    ///         "./my-test.wit",
1357
    ///         r#"
1358
    ///             package example:wit2;
1359
    ///
1360
    ///             world foo { /* ... */ }
1361
    ///         "#,
1362
    ///     )?;
1363
    ///     assert!(resolve.select_world(&[wit1, wit2], None).is_err());
1364
    ///     assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
1365
    ///     // Fix: use fully-qualified names.
1366
    ///     assert!(resolve.select_world(&[wit1, wit2], Some("example:wit1/foo")).is_ok());
1367
    ///     assert!(resolve.select_world(&[wit1, wit2], Some("example:wit2/foo")).is_ok());
1368
    ///
1369
    ///     // If a package has multiple worlds, then we can't guess the world
1370
    ///     // even if we know the package.
1371
    ///     let wit3 = resolve.push_str(
1372
    ///         "./my-test.wit",
1373
    ///         r#"
1374
    ///             package example:wit3;
1375
    ///
1376
    ///             world foo { /* ... */ }
1377
    ///
1378
    ///             world bar { /* ... */ }
1379
    ///         "#,
1380
    ///     )?;
1381
    ///     assert!(resolve.select_world(&[wit3], None).is_err());
1382
    ///     // Fix: pick between "foo" and "bar" here.
1383
    ///     assert!(resolve.select_world(&[wit3], Some("foo")).is_ok());
1384
    ///
1385
    ///     // When selecting with a version it's ok to drop the version when
1386
    ///     // there's only a single copy of that package in `Resolve`.
1387
    ///     let wit5_1 = resolve.push_str(
1388
    ///         "./my-test.wit",
1389
    ///         r#"
1390
    ///             package example:wit5@1.0.0;
1391
    ///
1392
    ///             world foo { /* ... */ }
1393
    ///         "#,
1394
    ///     )?;
1395
    ///     assert!(resolve.select_world(&[wit5_1], Some("foo")).is_ok());
1396
    ///     assert!(resolve.select_world(&[wit5_1], Some("example:wit5/foo")).is_ok());
1397
    ///
1398
    ///     // However when a single package has multiple versions in a resolve
1399
    ///     // it's required to specify the version to select which one.
1400
    ///     let wit5_2 = resolve.push_str(
1401
    ///         "./my-test.wit",
1402
    ///         r#"
1403
    ///             package example:wit5@2.0.0;
1404
    ///
1405
    ///             world foo { /* ... */ }
1406
    ///         "#,
1407
    ///     )?;
1408
    ///     assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo")).is_err());
1409
    ///     // Fix: Pass explicit versions.
1410
    ///     assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo@1.0.0")).is_ok());
1411
    ///     assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo@2.0.0")).is_ok());
1412
    ///
1413
    ///     Ok(())
1414
    /// }
1415
    /// ```
1416
0
    pub fn select_world(
1417
0
        &self,
1418
0
        main_packages: &[PackageId],
1419
0
        world: Option<&str>,
1420
0
    ) -> anyhow::Result<WorldId> {
1421
        // Determine if `world` is a kebab-name or an ID.
1422
0
        let world_path = match world {
1423
0
            Some(world) => Some(
1424
0
                parse_use_path(world)
1425
0
                    .with_context(|| format!("failed to parse world specifier `{world}`"))?,
1426
            ),
1427
0
            None => None,
1428
        };
1429
1430
0
        match world_path {
1431
            // We have a world path. If needed, pick a package to resolve it in.
1432
0
            Some(world_path) => {
1433
0
                let (pkg, world_name) = match (main_packages, world_path) {
1434
                    // We have no main packages; fail.
1435
0
                    ([], _) => bail!("No main packages defined"),
1436
1437
                    // We have exactly one main package.
1438
0
                    ([main_package], ParsedUsePath::Name(name)) => (*main_package, name),
1439
1440
                    // We have more than one main package; fail.
1441
0
                    (_, ParsedUsePath::Name(_name)) => {
1442
0
                        bail!(
1443
                            "There are multiple main packages; a world must be explicitly chosen:{}",
1444
0
                            self.worlds
1445
0
                                .iter()
1446
0
                                .map(|world| format!(
1447
                                    "\n  {}",
1448
0
                                    self.id_of_name(world.1.package.unwrap(), &world.1.name)
1449
                                ))
1450
0
                                .collect::<String>()
1451
                        )
1452
                    }
1453
1454
                    // The world name is fully-qualified.
1455
0
                    (_, ParsedUsePath::Package(pkg, world_name)) => {
1456
0
                        let pkg = match self.package_names.get(&pkg) {
1457
0
                            Some(pkg) => *pkg,
1458
                            None => {
1459
0
                                let mut candidates =
1460
0
                                    self.package_names.iter().filter(|(name, _)| {
1461
0
                                        pkg.version.is_none()
1462
0
                                            && pkg.name == name.name
1463
0
                                            && pkg.namespace == name.namespace
1464
0
                                            && name.version.is_some()
1465
0
                                    });
1466
0
                                let candidate = candidates.next();
1467
0
                                if let Some((c2, _)) = candidates.next() {
1468
0
                                    let (c1, _) = candidate.unwrap();
1469
0
                                    bail!(
1470
                                        "package name `{pkg}` is available at both \
1471
                                    versions {} and {} but which is not specified",
1472
0
                                        c1.version.as_ref().unwrap(),
1473
0
                                        c2.version.as_ref().unwrap(),
1474
                                    );
1475
0
                                }
1476
0
                                match candidate {
1477
0
                                    Some((_, id)) => *id,
1478
0
                                    None => bail!("unknown package `{pkg}`"),
1479
                                }
1480
                            }
1481
                        };
1482
0
                        (pkg, world_name.to_string())
1483
                    }
1484
                };
1485
1486
                // Now that we've picked the package, resolve the world name.
1487
0
                let pkg = &self.packages[pkg];
1488
0
                pkg.worlds.get(&world_name).copied().ok_or_else(|| {
1489
0
                    anyhow!("World `{world_name}` not found in package `{}`", pkg.name)
1490
0
                })
1491
            }
1492
1493
            // With no specified `world`, try to find a single obvious world.
1494
0
            None => match main_packages {
1495
0
                [] => bail!("No main packages defined"),
1496
1497
                // Check for exactly one main package with exactly one world.
1498
0
                [main_package] => {
1499
0
                    let pkg = &self.packages[*main_package];
1500
0
                    match pkg.worlds.len() {
1501
0
                        0 => bail!("The main package `{}` contains no worlds", pkg.name),
1502
0
                        1 => Ok(pkg.worlds[0]),
1503
0
                        _ => bail!(
1504
                            "There are multiple worlds in `{}`; one must be explicitly chosen:{}",
1505
                            pkg.name,
1506
0
                            pkg.worlds
1507
0
                                .values()
1508
0
                                .map(|world| format!(
1509
                                    "\n  {}",
1510
0
                                    self.id_of_name(*main_package, &self.worlds[*world].name)
1511
                                ))
1512
0
                                .collect::<String>()
1513
                        ),
1514
                    }
1515
                }
1516
1517
                // Multiple main packages and no world name; fail.
1518
                _ => {
1519
0
                    bail!(
1520
                        "There are multiple main packages; a world must be explicitly chosen:{}",
1521
0
                        self.worlds
1522
0
                            .iter()
1523
0
                            .map(|world| format!(
1524
                                "\n  {}",
1525
0
                                self.id_of_name(world.1.package.unwrap(), &world.1.name)
1526
                            ))
1527
0
                            .collect::<String>()
1528
                    )
1529
                }
1530
            },
1531
        }
1532
0
    }
1533
1534
    /// Assigns a human readable name to the `WorldKey` specified.
1535
186k
    pub fn name_world_key(&self, key: &WorldKey) -> String {
1536
186k
        match key {
1537
175k
            WorldKey::Name(s) => s.to_string(),
1538
10.5k
            WorldKey::Interface(i) => self.id_of(*i).expect("unexpected anonymous interface"),
1539
        }
1540
186k
    }
1541
1542
    /// Same as [`Resolve::name_world_key`] except that `WorldKey::Interfaces`
1543
    /// uses [`Resolve::canonicalized_id_of`].
1544
596
    pub fn name_canonicalized_world_key(&self, key: &WorldKey) -> String {
1545
596
        match key {
1546
556
            WorldKey::Name(s) => s.to_string(),
1547
40
            WorldKey::Interface(i) => self
1548
40
                .canonicalized_id_of(*i)
1549
40
                .expect("unexpected anonymous interface"),
1550
        }
1551
596
    }
1552
1553
    /// Returns the component model `implements` interface for the world import of
1554
    /// `key` and `item`.
1555
    ///
1556
    /// See the component model explainer and 🏷️ for more information on this feature.
1557
40.0k
    pub fn implements_interface(&self, key: &WorldKey, item: &WorldItem) -> Option<InterfaceId> {
1558
40.0k
        if let WorldKey::Name(_) = key {
1559
37.1k
            if let WorldItem::Interface { id, .. } = item {
1560
30.3k
                if self.interfaces[*id].name.is_some() {
1561
27.6k
                    return Some(*id);
1562
2.62k
                }
1563
6.85k
            }
1564
2.89k
        }
1565
12.3k
        None
1566
40.0k
    }
1567
1568
    /// Returns the component model `version-suffix` value for the interface `id`.
1569
    ///
1570
    /// See the component model explainer and 🔗 for more information on this feature.
1571
50.0k
    pub fn version_suffix_of(&self, id: InterfaceId) -> Option<String> {
1572
50.0k
        let pkg = self.interfaces[id].package?;
1573
50.0k
        let version = self.packages[pkg].name.version.as_ref()?;
1574
44.4k
        let (_, suffix) = PackageName::version_compat_track(version);
1575
44.4k
        suffix
1576
50.0k
    }
1577
1578
    /// Returns the component model `external-id` value for the world import of
1579
    /// `key` and `item`.
1580
    ///
1581
    /// See the component model explainer and 🏷️ for more information on this feature.
1582
50.4k
    pub fn external_id_value(&self, key: &WorldKey, item: &WorldItem) -> Option<String> {
1583
50.4k
        let _ = key;
1584
50.4k
        match item {
1585
43.9k
            WorldItem::Interface { external_id, .. } => external_id.clone(),
1586
6.53k
            WorldItem::Function(f) => f.external_id.clone(),
1587
0
            WorldItem::Type { id, .. } => self.types[*id].external_id.clone(),
1588
        }
1589
50.4k
    }
1590
1591
    /// Returns the interface that `id` uses a type from, if it uses a type from
1592
    /// a different interface than `id` is defined within.
1593
    ///
1594
    /// If `id` is not a use-of-a-type or it's using a type in the same
1595
    /// interface then `None` is returned.
1596
527k
    pub fn type_interface_dep(&self, id: TypeId) -> Option<InterfaceId> {
1597
527k
        let ty = &self.types[id];
1598
54.3k
        let dep = match ty.kind {
1599
45.0k
            TypeDefKind::Type(Type::Id(id)) => id,
1600
482k
            _ => return None,
1601
        };
1602
45.0k
        let other = &self.types[dep];
1603
45.0k
        if ty.owner == other.owner {
1604
133
            None
1605
        } else {
1606
44.9k
            match other.owner {
1607
44.9k
                TypeOwner::Interface(id) => Some(id),
1608
0
                _ => unreachable!(),
1609
            }
1610
        }
1611
527k
    }
1612
1613
    /// Returns an iterator of all interfaces that the interface `id` depends
1614
    /// on.
1615
    ///
1616
    /// Interfaces may depend on others for type information to resolve type
1617
    /// imports.
1618
    ///
1619
    /// Note that the returned iterator may yield the same interface as a
1620
    /// dependency multiple times. Additionally only direct dependencies of `id`
1621
    /// are yielded, not transitive dependencies.
1622
183k
    pub fn interface_direct_deps(&self, id: InterfaceId) -> impl Iterator<Item = InterfaceId> + '_ {
1623
183k
        self.interfaces[id]
1624
183k
            .types
1625
183k
            .iter()
1626
482k
            .filter_map(move |(_name, ty)| self.type_interface_dep(*ty))
1627
183k
    }
1628
1629
    /// Returns an iterator of all packages that the package `id` depends
1630
    /// on.
1631
    ///
1632
    /// Packages may depend on others for type information to resolve type
1633
    /// imports or interfaces to resolve worlds.
1634
    ///
1635
    /// Note that the returned iterator may yield the same package as a
1636
    /// dependency multiple times. Additionally only direct dependencies of `id`
1637
    /// are yielded, not transitive dependencies.
1638
15.9k
    pub fn package_direct_deps(&self, id: PackageId) -> impl Iterator<Item = PackageId> + '_ {
1639
15.9k
        let pkg = &self.packages[id];
1640
1641
15.9k
        pkg.interfaces
1642
15.9k
            .iter()
1643
20.8k
            .flat_map(move |(_name, id)| self.interface_direct_deps(*id))
1644
16.2k
            .chain(pkg.worlds.iter().flat_map(move |(_name, id)| {
1645
16.2k
                let world = &self.worlds[*id];
1646
16.2k
                world
1647
16.2k
                    .imports
1648
16.2k
                    .iter()
1649
16.2k
                    .chain(world.exports.iter())
1650
37.3k
                    .filter_map(move |(_name, item)| match item {
1651
26.9k
                        WorldItem::Interface { id, .. } => Some(*id),
1652
4.44k
                        WorldItem::Function(_) => None,
1653
5.95k
                        WorldItem::Type { id, .. } => self.type_interface_dep(*id),
1654
37.3k
                    })
1655
16.2k
            }))
1656
31.7k
            .filter_map(move |iface_id| {
1657
31.7k
                let pkg = self.interfaces[iface_id].package?;
1658
31.7k
                if pkg == id { None } else { Some(pkg) }
1659
31.7k
            })
1660
15.9k
    }
1661
1662
    /// Returns a topological ordering of packages contained in this `Resolve`.
1663
    ///
1664
    /// This returns a list of `PackageId` such that when visited in order it's
1665
    /// guaranteed that all dependencies will have been defined by prior items
1666
    /// in the list.
1667
10.6k
    pub fn topological_packages(&self) -> Vec<PackageId> {
1668
10.6k
        let mut pushed = vec![false; self.packages.len()];
1669
10.6k
        let mut order = Vec::new();
1670
15.9k
        for (id, _) in self.packages.iter() {
1671
15.9k
            self.build_topological_package_ordering(id, &mut pushed, &mut order);
1672
15.9k
        }
1673
10.6k
        order
1674
10.6k
    }
1675
1676
35.8k
    fn build_topological_package_ordering(
1677
35.8k
        &self,
1678
35.8k
        id: PackageId,
1679
35.8k
        pushed: &mut Vec<bool>,
1680
35.8k
        order: &mut Vec<PackageId>,
1681
35.8k
    ) {
1682
35.8k
        if pushed[id.index()] {
1683
19.8k
            return;
1684
15.9k
        }
1685
19.8k
        for dep in self.package_direct_deps(id) {
1686
19.8k
            self.build_topological_package_ordering(dep, pushed, order);
1687
19.8k
        }
1688
15.9k
        order.push(id);
1689
15.9k
        pushed[id.index()] = true;
1690
35.8k
    }
1691
1692
    #[doc(hidden)]
1693
4.13k
    pub fn assert_valid(&self) {
1694
4.13k
        let mut package_interfaces = Vec::new();
1695
4.13k
        let mut package_worlds = Vec::new();
1696
4.89k
        for (id, pkg) in self.packages.iter() {
1697
4.89k
            let mut interfaces = HashSet::new();
1698
18.2k
            for (name, iface) in pkg.interfaces.iter() {
1699
18.2k
                assert!(interfaces.insert(*iface));
1700
18.2k
                let iface = &self.interfaces[*iface];
1701
18.2k
                assert_eq!(name, iface.name.as_ref().unwrap());
1702
18.2k
                assert_eq!(iface.package.unwrap(), id);
1703
            }
1704
4.89k
            package_interfaces.push(pkg.interfaces.values().copied().collect::<HashSet<_>>());
1705
4.89k
            let mut worlds = HashSet::new();
1706
6.46k
            for (name, world) in pkg.worlds.iter() {
1707
6.46k
                assert!(worlds.insert(*world));
1708
6.46k
                assert_eq!(
1709
6.46k
                    pkg.worlds.get_key_value(name),
1710
6.46k
                    Some((name, world)),
1711
                    "`MutableKeys` impl may have been used to change a key's hash or equality"
1712
                );
1713
6.46k
                let world = &self.worlds[*world];
1714
6.46k
                assert_eq!(*name, world.name);
1715
6.46k
                assert_eq!(world.package.unwrap(), id);
1716
            }
1717
4.89k
            package_worlds.push(pkg.worlds.values().copied().collect::<HashSet<_>>());
1718
        }
1719
1720
4.13k
        let mut interface_types = Vec::new();
1721
19.0k
        for (id, iface) in self.interfaces.iter() {
1722
19.0k
            assert!(self.packages.get(iface.package.unwrap()).is_some());
1723
19.0k
            if iface.name.is_some() {
1724
18.2k
                match iface.clone_of {
1725
0
                    Some(other) => {
1726
0
                        assert_eq!(iface.name, self.interfaces[other].name);
1727
                    }
1728
                    None => {
1729
18.2k
                        assert!(package_interfaces[iface.package.unwrap().index()].contains(&id));
1730
                    }
1731
                }
1732
784
            }
1733
1734
19.0k
            for (name, ty) in iface.types.iter() {
1735
12.6k
                let ty = &self.types[*ty];
1736
12.6k
                assert_eq!(ty.name.as_ref(), Some(name));
1737
12.6k
                assert_eq!(ty.owner, TypeOwner::Interface(id));
1738
            }
1739
19.0k
            interface_types.push(iface.types.values().copied().collect::<HashSet<_>>());
1740
19.0k
            for (name, f) in iface.functions.iter() {
1741
6.08k
                assert_eq!(*name, f.name);
1742
            }
1743
        }
1744
1745
4.13k
        let mut world_types = Vec::new();
1746
6.46k
        for (id, world) in self.worlds.iter() {
1747
6.46k
            log::debug!("validating world {}", &world.name);
1748
6.46k
            if let Some(package) = world.package {
1749
6.46k
                assert!(self.packages.get(package).is_some());
1750
6.46k
                assert!(package_worlds[package.index()].contains(&id));
1751
0
            }
1752
6.46k
            assert!(world.includes.is_empty());
1753
1754
6.46k
            let mut types = HashSet::new();
1755
14.8k
            for (name, item) in world.imports.iter().chain(world.exports.iter()) {
1756
14.8k
                log::debug!("validating world item: {}", self.name_world_key(name));
1757
14.8k
                match item {
1758
10.7k
                    WorldItem::Interface { id, .. } => {
1759
                        // Anonymous interfaces must belong to the same package,
1760
                        // but interfaces through `implements` can be in any
1761
                        // package.
1762
10.7k
                        if matches!(name, WorldKey::Name(_)) {
1763
9.84k
                            let iface = &self.interfaces[*id];
1764
9.84k
                            if iface.name.is_none() {
1765
784
                                assert_eq!(iface.package, world.package);
1766
9.06k
                            }
1767
862
                        }
1768
                    }
1769
1.76k
                    WorldItem::Function(f) => {
1770
1.76k
                        assert!(!matches!(name, WorldKey::Interface(_)));
1771
1.76k
                        assert_eq!(f.name, name.clone().unwrap_name());
1772
                    }
1773
2.36k
                    WorldItem::Type { id: ty, .. } => {
1774
2.36k
                        assert!(!matches!(name, WorldKey::Interface(_)));
1775
2.36k
                        assert!(types.insert(*ty));
1776
2.36k
                        let ty = &self.types[*ty];
1777
2.36k
                        assert_eq!(ty.name, Some(name.clone().unwrap_name()));
1778
2.36k
                        assert_eq!(ty.owner, TypeOwner::World(id));
1779
                    }
1780
                }
1781
            }
1782
6.46k
            self.assert_world_elaborated(world);
1783
6.46k
            world_types.push(types);
1784
        }
1785
1786
55.7k
        for (ty_id, ty) in self.types.iter() {
1787
55.7k
            match ty.owner {
1788
12.6k
                TypeOwner::Interface(id) => {
1789
12.6k
                    assert!(self.interfaces.get(id).is_some());
1790
12.6k
                    assert!(interface_types[id.index()].contains(&ty_id));
1791
                }
1792
2.36k
                TypeOwner::World(id) => {
1793
2.36k
                    assert!(self.worlds.get(id).is_some());
1794
2.36k
                    assert!(world_types[id.index()].contains(&ty_id));
1795
                }
1796
40.7k
                TypeOwner::None => {}
1797
            }
1798
        }
1799
1800
4.13k
        self.assert_topologically_sorted();
1801
4.13k
    }
1802
1803
4.13k
    fn assert_topologically_sorted(&self) {
1804
4.13k
        let mut positions = IndexMap::default();
1805
4.89k
        for id in self.topological_packages() {
1806
4.89k
            let pkg = &self.packages[id];
1807
4.89k
            log::debug!("pkg {}", pkg.name);
1808
4.89k
            let prev = positions.insert(Some(id), IndexSet::default());
1809
4.89k
            assert!(prev.is_none());
1810
        }
1811
4.13k
        positions.insert(None, IndexSet::default());
1812
1813
19.0k
        for (id, iface) in self.interfaces.iter() {
1814
19.0k
            log::debug!("iface {:?}", iface.name);
1815
19.0k
            let ok = positions.get_mut(&iface.package).unwrap().insert(id);
1816
19.0k
            assert!(ok);
1817
        }
1818
1819
6.46k
        for (_, world) in self.worlds.iter() {
1820
6.46k
            log::debug!("world {:?}", world.name);
1821
1822
6.46k
            let my_package = world.package;
1823
6.46k
            let my_package_pos = positions.get_index_of(&my_package).unwrap();
1824
1825
14.8k
            for (_, item) in world.imports.iter().chain(&world.exports) {
1826
14.8k
                let id = match item {
1827
10.7k
                    WorldItem::Interface { id, .. } => *id,
1828
4.13k
                    _ => continue,
1829
                };
1830
10.7k
                let other_package = self.interfaces[id].package;
1831
10.7k
                let other_package_pos = positions.get_index_of(&other_package).unwrap();
1832
1833
10.7k
                assert!(other_package_pos <= my_package_pos);
1834
            }
1835
        }
1836
1837
55.7k
        for (_id, ty) in self.types.iter() {
1838
55.7k
            log::debug!("type {:?} {:?}", ty.name, ty.owner);
1839
4.47k
            let other_id = match ty.kind {
1840
3.85k
                TypeDefKind::Type(Type::Id(ty)) => ty,
1841
51.9k
                _ => continue,
1842
            };
1843
3.85k
            let other = &self.types[other_id];
1844
3.85k
            if ty.kind == other.kind {
1845
0
                continue;
1846
3.85k
            }
1847
3.85k
            let my_interface = match ty.owner {
1848
3.46k
                TypeOwner::Interface(id) => id,
1849
392
                _ => continue,
1850
            };
1851
3.46k
            let other_interface = match other.owner {
1852
3.46k
                TypeOwner::Interface(id) => id,
1853
0
                _ => continue,
1854
            };
1855
1856
3.46k
            let my_package = self.interfaces[my_interface].package;
1857
3.46k
            let other_package = self.interfaces[other_interface].package;
1858
3.46k
            let my_package_pos = positions.get_index_of(&my_package).unwrap();
1859
3.46k
            let other_package_pos = positions.get_index_of(&other_package).unwrap();
1860
1861
3.46k
            assert!(other_package_pos <= my_package_pos);
1862
        }
1863
4.13k
    }
1864
1865
6.46k
    fn assert_world_elaborated(&self, world: &World) {
1866
6.46k
        for (key, item) in world.imports.iter() {
1867
5.41k
            log::debug!(
1868
                "asserting elaborated world import {}",
1869
0
                self.name_world_key(key)
1870
            );
1871
5.41k
            match item {
1872
2.36k
                WorldItem::Type { id, .. } => self.assert_world_imports_type_deps(world, key, *id),
1873
1874
                // All types referred to must be imported.
1875
1.30k
                WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1876
1877
                // All direct dependencies of this interface must be imported.
1878
1.74k
                WorldItem::Interface { id, .. } => {
1879
1.74k
                    for dep in self.interface_direct_deps(*id) {
1880
530
                        assert!(
1881
530
                            world.imports.contains_key(&WorldKey::Interface(dep)),
1882
                            "world import of {} is missing transitive dep of {}",
1883
0
                            self.name_world_key(key),
1884
0
                            self.id_of(dep).unwrap(),
1885
                        );
1886
                    }
1887
                }
1888
            }
1889
        }
1890
9.42k
        for (key, item) in world.exports.iter() {
1891
9.42k
            log::debug!(
1892
                "asserting elaborated world export {}",
1893
0
                self.name_world_key(key)
1894
            );
1895
9.42k
            match item {
1896
                // Types referred to by this function must be imported.
1897
460
                WorldItem::Function(f) => self.assert_world_function_imports_types(world, key, f),
1898
1899
                // Dependencies of exported interfaces must also be exported, or
1900
                // if imported then that entire chain of imports must be
1901
                // imported and not exported.
1902
8.96k
                WorldItem::Interface { id, .. } => {
1903
8.96k
                    for dep in self.interface_direct_deps(*id) {
1904
1.19k
                        let dep_key = WorldKey::Interface(dep);
1905
1.19k
                        if world.exports.contains_key(&dep_key) {
1906
18
                            continue;
1907
1.17k
                        }
1908
1.26k
                        self.foreach_interface_dep(dep, &mut |dep| {
1909
1.26k
                            let dep_key = WorldKey::Interface(dep);
1910
1.26k
                            assert!(
1911
1.26k
                                world.imports.contains_key(&dep_key),
1912
                                "world should import {} (required by {})",
1913
0
                                self.name_world_key(&dep_key),
1914
0
                                self.name_world_key(key),
1915
                            );
1916
1.26k
                            assert!(
1917
1.26k
                                !world.exports.contains_key(&dep_key),
1918
                                "world should not export {} (required by {})",
1919
0
                                self.name_world_key(&dep_key),
1920
0
                                self.name_world_key(key),
1921
                            );
1922
1.26k
                        });
1923
                    }
1924
                }
1925
1926
                // exported types not allowed at this time
1927
0
                WorldItem::Type { .. } => unreachable!(),
1928
            }
1929
        }
1930
6.46k
    }
1931
1932
3.70k
    fn assert_world_imports_type_deps(&self, world: &World, key: &WorldKey, ty: TypeId) {
1933
        // If this is a `use` statement then the referred-to interface must be
1934
        // imported into this world.
1935
3.70k
        let ty = &self.types[ty];
1936
594
        if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
1937
392
            if let TypeOwner::Interface(id) = self.types[other].owner {
1938
380
                let key = WorldKey::Interface(id);
1939
380
                assert!(world.imports.contains_key(&key));
1940
380
                return;
1941
12
            }
1942
3.31k
        }
1943
1944
        // ... otherwise any named type that this type refers to, one level
1945
        // deep, must be imported into this world under that name.
1946
1947
3.32k
        let mut visitor = MyVisit(self, Vec::new());
1948
3.32k
        visitor.visit_type_def(self, ty);
1949
13.4k
        for ty in visitor.1 {
1950
13.4k
            let ty = &self.types[ty];
1951
13.4k
            let Some(name) = ty.name.clone() else {
1952
13.0k
                continue;
1953
            };
1954
428
            let dep_key = WorldKey::Name(name);
1955
428
            assert!(
1956
428
                world.imports.contains_key(&dep_key),
1957
                "world import `{}` should also force an import of `{}`",
1958
0
                self.name_world_key(key),
1959
0
                self.name_world_key(&dep_key),
1960
            );
1961
        }
1962
1963
        struct MyVisit<'a>(&'a Resolve, Vec<TypeId>);
1964
1965
        impl TypeIdVisitor for MyVisit<'_> {
1966
13.4k
            fn before_visit_type_id(&mut self, id: TypeId) -> bool {
1967
13.4k
                self.1.push(id);
1968
                // recurse into unnamed types to look at all named types
1969
13.4k
                self.0.types[id].name.is_none()
1970
13.4k
            }
1971
        }
1972
3.70k
    }
1973
1974
    /// This asserts that all types referred to by `func` are imported into
1975
    /// `world` under `WorldKey::Name`. Note that this is only applicable to
1976
    /// named type
1977
1.76k
    fn assert_world_function_imports_types(&self, world: &World, key: &WorldKey, func: &Function) {
1978
6.17k
        for ty in func
1979
1.76k
            .parameter_and_result_types()
1980
1.76k
            .chain(func.kind.resource().map(Type::Id))
1981
        {
1982
6.17k
            let Type::Id(id) = ty else {
1983
4.83k
                continue;
1984
            };
1985
1.34k
            self.assert_world_imports_type_deps(world, key, id);
1986
        }
1987
1.76k
    }
1988
1989
    /// Returns whether the `stability` annotation contained within `pkg_id`
1990
    /// should be included or not.
1991
    ///
1992
    /// The `span` provided here is an optional span pointing to the item that
1993
    /// is annotated with `stability`.
1994
    ///
1995
    /// Returns `Ok(true)` if the item is included, or `Ok(false)` if the item
1996
    /// is not.
1997
    ///
1998
    /// # Errors
1999
    ///
2000
    /// Returns an error if the `pkg_id` isn't annotated with sufficient version
2001
    /// information to have a `stability` annotation. For example if `pkg_id`
2002
    /// has no version listed then an error will be returned if `stability`
2003
    /// mentions a version.
2004
267k
    fn include_stability(
2005
267k
        &self,
2006
267k
        stability: &Stability,
2007
267k
        pkg_id: &PackageId,
2008
267k
        span: Span,
2009
267k
    ) -> ResolveResult<bool> {
2010
267k
        Ok(match stability {
2011
261k
            Stability::Unknown => true,
2012
            // NOTE: deprecations are intentionally omitted -- an existing
2013
            // `@since` takes precedence over `@deprecated`
2014
4.59k
            Stability::Stable { since, .. } => {
2015
4.59k
                let Some(p) = self.packages.get(*pkg_id) else {
2016
                    // We can't check much without a package (possibly dealing
2017
                    // with an item in an `UnresolvedPackage`), @since version &
2018
                    // deprecations can't be checked because there's no package
2019
                    // version to compare to.
2020
                    //
2021
                    // Feature requirements on stabilized features are ignored
2022
                    // in resolved packages, so we do the same here.
2023
0
                    return Ok(true);
2024
                };
2025
2026
                // Use of feature gating with version specifiers inside a
2027
                // package that is not versioned is not allowed
2028
4.59k
                let package_version = p.name.version.as_ref().ok_or_else(|| {
2029
0
                    ResolveError::new_semantic(
2030
0
                        span,
2031
0
                        format!(
2032
                            "package [{}] contains a feature gate with a version \
2033
                         specifier, so it must have a version",
2034
                            p.name
2035
                        ),
2036
                    )
2037
0
                })?;
2038
2039
                // If the version on the feature gate is:
2040
                // - released, then we can include it
2041
                // - unreleased, then we must check the feature (if present)
2042
4.59k
                if since > package_version {
2043
0
                    return Err(ResolveError::new_semantic(
2044
0
                        span,
2045
0
                        format!(
2046
0
                            "feature gate cannot reference unreleased version \
2047
0
                        {since} of package [{}] (current version {package_version})",
2048
0
                            p.name
2049
0
                        ),
2050
0
                    ));
2051
4.59k
                }
2052
2053
4.59k
                true
2054
            }
2055
1.62k
            Stability::Unstable { feature, .. } => {
2056
1.62k
                self.features.contains(feature) || self.all_features
2057
            }
2058
        })
2059
267k
    }
2060
2061
    /// Performs the "elaboration process" necessary for the `world_id`
2062
    /// specified to ensure that all of its transitive imports are listed.
2063
    ///
2064
    /// This function will take the unordered lists of the specified world's
2065
    /// imports and exports and "elaborate" them to ensure that they're
2066
    /// topographically sorted where all transitively required interfaces by
2067
    /// imports, or exports, are listed. This will additionally validate that
2068
    /// the exports are all valid and present, specifically with the restriction
2069
    /// noted on `elaborate_world_exports`.
2070
    ///
2071
    /// The world is mutated in-place in this `Resolve`.
2072
45.9k
    fn elaborate_world(&mut self, world_id: WorldId, span: Span) -> ResolveResult<()> {
2073
        // First process all imports. This is easier than exports since the only
2074
        // requirement here is that all interfaces need to be added with a
2075
        // topological order between them.
2076
45.9k
        let mut new_imports = IndexMap::default();
2077
45.9k
        let world = &self.worlds[world_id];
2078
2079
        // Sort the imports by "class" to ensure that this matches the order
2080
        // that items are printed and that items are in topological order.
2081
        //
2082
        // When printing worlds in WIT:
2083
        //
2084
        // * interfaces come first
2085
        // * types are next
2086
        //   * type imports are first
2087
        //   * type definitions are next
2088
        //   * resource definitions have methods printed inline
2089
        // * freestanding functions are last
2090
        //
2091
        // This reflects the topological order between items where types
2092
        // can refer to imports and functions can refer to these types. Ordering
2093
        // within a single class (e.g. imports depending on each other, types
2094
        // referring to each other) is already preserved by other passes in this
2095
        // file and general AST resolution. That means that a stable sort here
2096
        // can be used to ensure that each class is in the right location
2097
        // relative to the others.
2098
        //
2099
        // Overall this ensures that round-trips of WIT through wasm should
2100
        // always produce the same result.
2101
72.2k
        let sort_key = |resolve: &Resolve, item: &WorldItem| match item {
2102
27.8k
            WorldItem::Interface { .. } => 0,
2103
31.9k
            WorldItem::Type { id, .. } => {
2104
31.9k
                let ty = &resolve.types[*id];
2105
5.93k
                match ty.kind {
2106
5.93k
                    TypeDefKind::Type(Type::Id(t)) if resolve.types[t].owner != ty.owner => 1,
2107
26.1k
                    _ => 2,
2108
                }
2109
            }
2110
12.4k
            WorldItem::Function(f) => {
2111
12.4k
                if f.kind.resource().is_none() {
2112
8.26k
                    3
2113
                } else {
2114
4.19k
                    4
2115
                }
2116
            }
2117
72.2k
        };
2118
2119
        // Sort world items when we start to elaborate the world to start with a
2120
        // topological view of items.
2121
45.9k
        let mut world_imports = world.imports.iter().collect::<Vec<_>>();
2122
45.9k
        world_imports.sort_by_key(|(_name, import)| sort_key(self, import));
2123
45.9k
        for (name, item) in world_imports {
2124
34.9k
            match item {
2125
                // Interfaces get their dependencies added first followed by the
2126
                // interface itself.
2127
                WorldItem::Interface {
2128
13.0k
                    id,
2129
13.0k
                    stability,
2130
13.0k
                    docs,
2131
13.0k
                    external_id,
2132
                    ..
2133
13.0k
                } => {
2134
13.0k
                    self.elaborate_world_import(
2135
13.0k
                        &mut new_imports,
2136
13.0k
                        name.clone(),
2137
13.0k
                        *id,
2138
13.0k
                        &stability,
2139
13.0k
                        docs,
2140
13.0k
                        external_id.as_deref(),
2141
13.0k
                    );
2142
13.0k
                }
2143
2144
                // Functions are added as-is since their dependence on types in
2145
                // the world should already be satisfied.
2146
                WorldItem::Function(_) => {
2147
7.56k
                    let prev = new_imports.insert(name.clone(), item.clone());
2148
7.56k
                    assert!(prev.is_none());
2149
                }
2150
2151
                // Types may depend on an interface, in which case a (possibly)
2152
                // recursive addition of that interface happens here. Afterwards
2153
                // the type itself can be added safely.
2154
14.3k
                WorldItem::Type { id, .. } => {
2155
14.3k
                    if let Some(dep) = self.type_interface_dep(*id) {
2156
2.16k
                        self.elaborate_world_import(
2157
2.16k
                            &mut new_imports,
2158
2.16k
                            WorldKey::Interface(dep),
2159
2.16k
                            dep,
2160
2.16k
                            &self.types[*id].stability,
2161
2.16k
                            &Docs::default(),
2162
2.16k
                            None,
2163
2.16k
                        );
2164
12.1k
                    }
2165
14.3k
                    let prev = new_imports.insert(name.clone(), item.clone());
2166
14.3k
                    assert!(prev.is_none());
2167
                }
2168
            }
2169
        }
2170
2171
        // Exports are trickier than imports, notably to uphold the invariant
2172
        // required by `elaborate_world_exports`. To do this the exports are
2173
        // partitioned into interfaces/functions. All functions are added to
2174
        // the new exports list during this loop but interfaces are all deferred
2175
        // to be handled in the `elaborate_world_exports` function.
2176
45.9k
        let mut new_exports = IndexMap::default();
2177
45.9k
        let mut export_interfaces = IndexMap::default();
2178
59.5k
        for (name, item) in world.exports.iter() {
2179
59.5k
            match item {
2180
                WorldItem::Interface { .. } => {
2181
56.7k
                    let prev = export_interfaces.insert(name.clone(), item.clone());
2182
56.7k
                    assert!(prev.is_none());
2183
                }
2184
                WorldItem::Function(_) => {
2185
2.85k
                    let prev = new_exports.insert(name.clone(), item.clone());
2186
2.85k
                    assert!(prev.is_none());
2187
                }
2188
0
                WorldItem::Type { .. } => unreachable!(),
2189
            }
2190
        }
2191
2192
45.9k
        self.elaborate_world_exports(&export_interfaces, &mut new_imports, &mut new_exports, span)?;
2193
2194
        // In addition to sorting at the start of elaboration also sort here at
2195
        // the end of elaboration to handle types being interspersed with
2196
        // interfaces as they're found.
2197
45.9k
        new_imports.sort_by_cached_key(|_name, import| sort_key(self, import));
2198
2199
        // And with all that done the world is updated in-place with
2200
        // imports/exports.
2201
45.9k
        log::trace!("imports = {new_imports:?}");
2202
45.9k
        log::trace!("exports = {new_exports:?}");
2203
45.9k
        let world = &mut self.worlds[world_id];
2204
45.9k
        world.imports = new_imports;
2205
45.9k
        world.exports = new_exports;
2206
2207
45.9k
        Ok(())
2208
45.9k
    }
2209
2210
18.9k
    fn elaborate_world_import(
2211
18.9k
        &self,
2212
18.9k
        imports: &mut IndexMap<WorldKey, WorldItem>,
2213
18.9k
        key: WorldKey,
2214
18.9k
        id: InterfaceId,
2215
18.9k
        stability: &Stability,
2216
18.9k
        docs: &Docs,
2217
18.9k
        external_id: Option<&str>,
2218
18.9k
    ) {
2219
18.9k
        if imports.contains_key(&key) {
2220
5.01k
            return;
2221
13.8k
        }
2222
        // Synthesized dependency imports carry no statement-level docs of their
2223
        // own.
2224
13.8k
        for dep in self.interface_direct_deps(id) {
2225
3.72k
            self.elaborate_world_import(
2226
3.72k
                imports,
2227
3.72k
                WorldKey::Interface(dep),
2228
3.72k
                dep,
2229
3.72k
                stability,
2230
3.72k
                &Docs::default(),
2231
3.72k
                None,
2232
3.72k
            );
2233
3.72k
        }
2234
13.8k
        let prev = imports.insert(
2235
13.8k
            key,
2236
            WorldItem::Interface {
2237
13.8k
                id,
2238
13.8k
                stability: stability.clone(),
2239
13.8k
                docs: docs.clone(),
2240
13.8k
                span: Default::default(),
2241
13.8k
                external_id: external_id.map(|s| s.to_string()),
2242
            },
2243
        );
2244
13.8k
        assert!(prev.is_none());
2245
18.9k
    }
2246
2247
    /// This function adds all of the interfaces in `export_interfaces` to the
2248
    /// list of exports of the `world` specified.
2249
    ///
2250
    /// This method is more involved than adding imports because it is fallible.
2251
    /// Chiefly what can happen is that the dependencies of all exports must be
2252
    /// satisfied by other exports or imports, but not both. For example given a
2253
    /// situation such as:
2254
    ///
2255
    /// ```wit
2256
    /// interface a {
2257
    ///     type t = u32
2258
    /// }
2259
    /// interface b {
2260
    ///     use a.{t}
2261
    /// }
2262
    /// interface c {
2263
    ///     use a.{t}
2264
    ///     use b.{t as t2}
2265
    /// }
2266
    /// ```
2267
    ///
2268
    /// where `c` depends on `b` and `a` where `b` depends on `a`, then the
2269
    /// purpose of this method is to reject this world:
2270
    ///
2271
    /// ```wit
2272
    /// world foo {
2273
    ///     export a
2274
    ///     export c
2275
    /// }
2276
    /// ```
2277
    ///
2278
    /// The reasoning here is unfortunately subtle and is additionally the
2279
    /// subject of WebAssembly/component-model#208. Effectively the `c`
2280
    /// interface depends on `b`, but it's not listed explicitly as an import,
2281
    /// so it's then implicitly added as an import. This then transitively
2282
    /// depends on `a` so it's also added as an import. At this point though `c`
2283
    /// also depends on `a`, and it's also exported, so naively it should depend
2284
    /// on the export and not implicitly add an import. This means though that
2285
    /// `c` has access to two copies of `a`, one imported and one exported. This
2286
    /// is not valid, especially in the face of resource types.
2287
    ///
2288
    /// Overall this method is tasked with rejecting the above world by walking
2289
    /// over all the exports and adding their dependencies. Each dependency is
2290
    /// recorded with whether it's required to be imported, and then if an
2291
    /// export is added for something that's required to be an error then the
2292
    /// operation fails.
2293
45.9k
    fn elaborate_world_exports(
2294
45.9k
        &self,
2295
45.9k
        export_interfaces: &IndexMap<WorldKey, WorldItem>,
2296
45.9k
        imports: &mut IndexMap<WorldKey, WorldItem>,
2297
45.9k
        exports: &mut IndexMap<WorldKey, WorldItem>,
2298
45.9k
        span: Span,
2299
45.9k
    ) -> ResolveResult<()> {
2300
45.9k
        let mut required_imports = HashSet::new();
2301
56.6k
        for (key, item) in export_interfaces.iter() {
2302
56.6k
            let name = self.name_world_key(&key);
2303
56.6k
            let ok = add_world_export(
2304
56.6k
                self,
2305
56.6k
                imports,
2306
56.6k
                exports,
2307
56.6k
                &export_interfaces,
2308
56.6k
                &mut required_imports,
2309
56.6k
                key.clone(),
2310
56.6k
                item.clone(),
2311
                true,
2312
            );
2313
56.6k
            if !ok {
2314
                // FIXME: this is not a great error message and basically no
2315
                // one will know what to do when it gets printed. Improving
2316
                // this error message, however, is a chunk of work that may
2317
                // not be best spent doing this at this time, so I'm writing
2318
                // this comment instead.
2319
                //
2320
                // More-or-less what should happen here is that a "path"
2321
                // from this interface to the conflicting interface should
2322
                // be printed. It should be explained why an import is being
2323
                // injected, why that's conflicting with an export, and
2324
                // ideally with a suggestion of "add this interface to the
2325
                // export list to fix this error".
2326
                //
2327
                // That's a lot of info that's not easy to get at without
2328
                // more refactoring, so it's left to a future date in the
2329
                // hopes that most folks won't actually run into this for
2330
                // the time being.
2331
18
                return Err(ResolveError::from(
2332
18
                    ResolveErrorKind::InvalidTransitiveDependency { name, span },
2333
18
                ));
2334
56.6k
            }
2335
        }
2336
45.9k
        return Ok(());
2337
2338
64.1k
        fn add_world_export(
2339
64.1k
            resolve: &Resolve,
2340
64.1k
            imports: &mut IndexMap<WorldKey, WorldItem>,
2341
64.1k
            exports: &mut IndexMap<WorldKey, WorldItem>,
2342
64.1k
            export_interfaces: &IndexMap<WorldKey, WorldItem>,
2343
64.1k
            required_imports: &mut HashSet<InterfaceId>,
2344
64.1k
            key: WorldKey,
2345
64.1k
            item: WorldItem,
2346
64.1k
            add_export: bool,
2347
64.1k
        ) -> bool {
2348
64.1k
            if exports.contains_key(&key) {
2349
91
                if add_export {
2350
91
                    return true;
2351
                } else {
2352
0
                    return false;
2353
                }
2354
64.0k
            }
2355
64.0k
            let (id, stability, external_id) = match &item {
2356
                WorldItem::Interface {
2357
64.0k
                    id,
2358
64.0k
                    stability,
2359
64.0k
                    external_id,
2360
                    ..
2361
64.0k
                } => (*id, stability, external_id),
2362
0
                _ => unreachable!(),
2363
            };
2364
            // If this is an import and it's already in the `imports` set then
2365
            // we can skip it as we've already visited this interface.
2366
64.0k
            if !add_export && required_imports.contains(&id) {
2367
6.06k
                return true;
2368
58.0k
            }
2369
58.0k
            let ok = resolve.interface_direct_deps(id).all(|dep| {
2370
7.48k
                let item = WorldItem::Interface {
2371
7.48k
                    id: dep,
2372
7.48k
                    stability: stability.clone(),
2373
7.48k
                    docs: Default::default(),
2374
7.48k
                    span: Default::default(),
2375
7.48k
                    external_id: external_id.clone(),
2376
7.48k
                };
2377
7.48k
                let key = WorldKey::Interface(dep);
2378
7.48k
                let add_export = add_export && export_interfaces.contains_key(&key);
2379
7.48k
                add_world_export(
2380
7.48k
                    resolve,
2381
7.48k
                    imports,
2382
7.48k
                    exports,
2383
7.48k
                    export_interfaces,
2384
7.48k
                    required_imports,
2385
7.48k
                    key,
2386
7.48k
                    item,
2387
7.48k
                    add_export,
2388
                )
2389
7.48k
            });
2390
58.0k
            if !ok {
2391
0
                return false;
2392
58.0k
            }
2393
58.0k
            if add_export {
2394
56.6k
                if required_imports.contains(&id) {
2395
18
                    return false;
2396
56.6k
                }
2397
56.6k
                let prev = exports.insert(key.clone(), item);
2398
56.6k
                assert!(prev.is_none());
2399
            } else {
2400
1.33k
                required_imports.insert(id);
2401
1.33k
                if !imports.contains_key(&key) {
2402
318
                    imports.insert(key.clone(), item);
2403
1.01k
                }
2404
            }
2405
57.9k
            true
2406
64.1k
        }
2407
45.9k
    }
2408
2409
    /// Remove duplicate imports from a world if they import from the same
2410
    /// interface with semver-compatible versions.
2411
    ///
2412
    /// This will merge duplicate interfaces present at multiple versions in
2413
    /// both a world by selecting the larger version of the two interfaces. This
2414
    /// requires that the interfaces are indeed semver-compatible and it means
2415
    /// that some imports might be removed and replaced. Note that this is only
2416
    /// done within a single semver track, for example the world imports 0.2.0
2417
    /// and 0.2.1 then the result afterwards will be that it imports
2418
    /// 0.2.1. If, however, 0.3.0 where imported then the final result would
2419
    /// import both 0.2.0 and 0.3.0.
2420
3.73k
    pub fn merge_world_imports_based_on_semver(&mut self, world_id: WorldId) -> anyhow::Result<()> {
2421
3.73k
        let world = &self.worlds[world_id];
2422
2423
        // The first pass here is to build a map of "semver tracks" where they
2424
        // key is per-interface and the value is the maximal version found in
2425
        // that semver-compatible-track plus the interface which is the maximal
2426
        // version.
2427
        //
2428
        // At the same time a `to_remove` set is maintained to remember what
2429
        // interfaces are being removed from `from` and `into`. All of
2430
        // `to_remove` are placed with a known other version.
2431
3.73k
        let mut semver_tracks = HashMap::new();
2432
3.73k
        let mut to_remove = HashSet::new();
2433
3.73k
        for (key, _) in world.imports.iter() {
2434
3.14k
            let iface_id = match key {
2435
447
                WorldKey::Interface(id) => *id,
2436
2.70k
                WorldKey::Name(_) => continue,
2437
            };
2438
447
            let (track, version) = match self.semver_track(iface_id) {
2439
413
                Some(track) => track,
2440
34
                None => continue,
2441
            };
2442
413
            log::debug!(
2443
                "{} is on track {}/{}",
2444
0
                self.id_of(iface_id).unwrap(),
2445
                track.0,
2446
                track.1,
2447
            );
2448
413
            match semver_tracks.entry(track) {
2449
413
                Entry::Vacant(e) => {
2450
413
                    e.insert((version, iface_id));
2451
413
                }
2452
0
                Entry::Occupied(mut e) => match version.cmp(&e.get().0) {
2453
0
                    Ordering::Greater => {
2454
0
                        to_remove.insert(e.get().1);
2455
0
                        e.insert((version, iface_id));
2456
0
                    }
2457
0
                    Ordering::Equal => {}
2458
0
                    Ordering::Less => {
2459
0
                        to_remove.insert(iface_id);
2460
0
                    }
2461
                },
2462
            }
2463
        }
2464
2465
        // Build a map of "this interface is replaced with this interface" using
2466
        // the results of the loop above.
2467
3.73k
        let mut replacements = HashMap::new();
2468
3.73k
        for id in to_remove {
2469
0
            let (track, _) = self.semver_track(id).unwrap();
2470
0
            let (_, latest) = semver_tracks[&track];
2471
0
            let prev = replacements.insert(id, latest);
2472
0
            assert!(prev.is_none());
2473
        }
2474
        // Explicit drop needed for hashbrown compatibility - hashbrown's HashMap
2475
        // destructor may access stored references, extending the borrow.
2476
3.73k
        drop(semver_tracks);
2477
2478
        // Validate that `merge_world_item` succeeds for merging all removed
2479
        // interfaces with their replacement. This is a double-check that the
2480
        // semver version is actually correct and all items present in the old
2481
        // interface are in the new.
2482
3.73k
        for (to_replace, replace_with) in replacements.iter() {
2483
0
            self.merge_world_item(
2484
0
                &WorldItem::Interface {
2485
0
                    id: *to_replace,
2486
0
                    stability: Default::default(),
2487
0
                    docs: Default::default(),
2488
0
                    span: Default::default(),
2489
0
                    external_id: Default::default(),
2490
0
                },
2491
0
                &WorldItem::Interface {
2492
0
                    id: *replace_with,
2493
0
                    stability: Default::default(),
2494
0
                    docs: Default::default(),
2495
0
                    span: Default::default(),
2496
0
                    external_id: Default::default(),
2497
0
                },
2498
            )
2499
0
            .with_context(|| {
2500
0
                let old_name = self.id_of(*to_replace).unwrap();
2501
0
                let new_name = self.id_of(*replace_with).unwrap();
2502
0
                format!(
2503
                    "failed to upgrade `{old_name}` to `{new_name}`, was \
2504
                     this semver-compatible update not semver compatible?"
2505
                )
2506
0
            })?;
2507
        }
2508
2509
3.73k
        for (to_replace, replace_with) in replacements.iter() {
2510
0
            log::debug!(
2511
                "REPLACE {} => {}",
2512
0
                self.id_of(*to_replace).unwrap(),
2513
0
                self.id_of(*replace_with).unwrap(),
2514
            );
2515
        }
2516
2517
        // Finally perform the actual transformation of the imports/exports.
2518
        // Here all imports are removed if they're replaced and otherwise all
2519
        // imports have their dependencies updated, possibly transitively, to
2520
        // point to the new interfaces in `replacements`.
2521
        //
2522
        // Afterwards exports are additionally updated, but only their
2523
        // dependencies on imports which were remapped. Exports themselves are
2524
        // not deduplicated and/or removed.
2525
3.73k
        for (key, item) in mem::take(&mut self.worlds[world_id].imports) {
2526
3.14k
            if let WorldItem::Interface { id, .. } = item {
2527
990
                if replacements.contains_key(&id) {
2528
0
                    if let WorldKey::Interface(_) = key {
2529
0
                        continue;
2530
0
                    }
2531
                    // Keep labeled imports with `implements` version unchanged
2532
990
                }
2533
2.15k
            }
2534
2535
3.14k
            self.update_interface_deps_of_world_item(&item, &replacements);
2536
2537
3.14k
            let prev = self.worlds[world_id].imports.insert(key, item);
2538
3.14k
            assert!(prev.is_none());
2539
        }
2540
5.58k
        for (key, item) in mem::take(&mut self.worlds[world_id].exports) {
2541
5.58k
            self.update_interface_deps_of_world_item(&item, &replacements);
2542
5.58k
            let prev = self.worlds[world_id].exports.insert(key, item);
2543
5.58k
            assert!(prev.is_none());
2544
        }
2545
2546
        // Run through `elaborate_world` to reorder imports as appropriate and
2547
        // fill anything back in if it's actually required by exports. For now
2548
        // this doesn't tamper with exports at all. Also note that this is
2549
        // applied to all worlds in this `Resolve` because interfaces were
2550
        // modified directly.
2551
3.73k
        let ids = self.worlds.iter().map(|(id, _)| id).collect::<Vec<_>>();
2552
10.1k
        for world_id in ids {
2553
10.1k
            let world_span = self.worlds[world_id].span;
2554
10.1k
            self.elaborate_world(world_id, world_span)?;
2555
        }
2556
2557
        #[cfg(debug_assertions)]
2558
        self.assert_valid();
2559
2560
3.73k
        Ok(())
2561
3.73k
    }
2562
2563
8.73k
    fn update_interface_deps_of_world_item(
2564
8.73k
        &mut self,
2565
8.73k
        item: &WorldItem,
2566
8.73k
        replacements: &HashMap<InterfaceId, InterfaceId>,
2567
8.73k
    ) {
2568
8.73k
        match *item {
2569
1.42k
            WorldItem::Type { id, .. } => self.update_interface_dep_of_type(id, &replacements),
2570
6.31k
            WorldItem::Interface { id, .. } => {
2571
6.31k
                let types = self.interfaces[id]
2572
6.31k
                    .types
2573
6.31k
                    .values()
2574
6.31k
                    .copied()
2575
6.31k
                    .collect::<Vec<_>>();
2576
23.4k
                for ty in types {
2577
23.4k
                    self.update_interface_dep_of_type(ty, &replacements);
2578
23.4k
                }
2579
            }
2580
994
            WorldItem::Function(_) => {}
2581
        }
2582
8.73k
    }
2583
2584
    /// Returns the "semver track" of an interface plus the interface's version.
2585
    ///
2586
    /// This function returns `None` if the interface `id` has a package without
2587
    /// a version. If the version is present, however, the first element of the
2588
    /// tuple returned is a "semver track" for the specific interface. The
2589
    /// version listed in `PackageName` will be modified so all
2590
    /// semver-compatible versions are listed the same way.
2591
    ///
2592
    /// The second element in the returned tuple is this interface's package's
2593
    /// version.
2594
447
    fn semver_track(&self, id: InterfaceId) -> Option<((PackageName, String), &Version)> {
2595
447
        let iface = &self.interfaces[id];
2596
447
        let pkg = &self.packages[iface.package?];
2597
447
        let version = pkg.name.version.as_ref()?;
2598
413
        let mut name = pkg.name.clone();
2599
413
        name.version = Some(PackageName::version_compat_track(version).0);
2600
413
        Some(((name, iface.name.clone()?), version))
2601
447
    }
2602
2603
    /// If `ty` is a definition where it's a `use` from another interface, then
2604
    /// change what interface it's using from according to the pairs in the
2605
    /// `replacements` map.
2606
24.8k
    fn update_interface_dep_of_type(
2607
24.8k
        &mut self,
2608
24.8k
        ty: TypeId,
2609
24.8k
        replacements: &HashMap<InterfaceId, InterfaceId>,
2610
24.8k
    ) {
2611
24.8k
        let to_replace = match self.type_interface_dep(ty) {
2612
1.25k
            Some(id) => id,
2613
23.5k
            None => return,
2614
        };
2615
1.25k
        let replace_with = match replacements.get(&to_replace) {
2616
0
            Some(id) => id,
2617
1.25k
            None => return,
2618
        };
2619
0
        let dep = match self.types[ty].kind {
2620
0
            TypeDefKind::Type(Type::Id(id)) => id,
2621
0
            _ => return,
2622
        };
2623
0
        let name = self.types[dep].name.as_ref().unwrap();
2624
        // Note the infallible name indexing happening here. This should be
2625
        // previously validated with `merge_world_item` to succeed.
2626
0
        let replacement_id = self.interfaces[*replace_with].types[name];
2627
0
        self.types[ty].kind = TypeDefKind::Type(Type::Id(replacement_id));
2628
24.8k
    }
2629
2630
    /// Returns the core wasm module/field names for the specified `import`.
2631
    ///
2632
    /// This function will return the core wasm module/field that can be used to
2633
    /// use `import` with the name `mangling` scheme specified as well. This can
2634
    /// be useful for bindings generators, for example, and these names are
2635
    /// recognized by `wit-component` and `wasm-tools component new`.
2636
5.02k
    pub fn wasm_import_name(
2637
5.02k
        &self,
2638
5.02k
        mangling: ManglingAndAbi,
2639
5.02k
        import: WasmImport<'_>,
2640
5.02k
    ) -> (String, String) {
2641
5.02k
        match mangling {
2642
158
            ManglingAndAbi::Standard32 => match import {
2643
91
                WasmImport::Func { interface, func } => {
2644
91
                    let module = match interface {
2645
34
                        Some(key) => format!("cm32p2|{}", self.name_canonicalized_world_key(key)),
2646
57
                        None => format!("cm32p2"),
2647
                    };
2648
91
                    (module, func.name.clone())
2649
                }
2650
                WasmImport::ResourceIntrinsic {
2651
67
                    interface,
2652
67
                    resource,
2653
67
                    intrinsic,
2654
                } => {
2655
67
                    let name = self.types[resource].name.as_ref().unwrap();
2656
67
                    let (prefix, name) = match intrinsic {
2657
10
                        ResourceIntrinsic::ImportedDrop => ("", format!("{name}_drop")),
2658
19
                        ResourceIntrinsic::ExportedDrop => ("_ex_", format!("{name}_drop")),
2659
19
                        ResourceIntrinsic::ExportedNew => ("_ex_", format!("{name}_new")),
2660
19
                        ResourceIntrinsic::ExportedRep => ("_ex_", format!("{name}_rep")),
2661
                    };
2662
67
                    let module = match interface {
2663
63
                        Some(key) => {
2664
63
                            format!("cm32p2|{prefix}{}", self.name_canonicalized_world_key(key))
2665
                        }
2666
                        None => {
2667
4
                            assert_eq!(prefix, "");
2668
4
                            format!("cm32p2")
2669
                        }
2670
                    };
2671
67
                    (module, name)
2672
                }
2673
                WasmImport::FutureIntrinsic { .. } | WasmImport::StreamIntrinsic { .. } => {
2674
0
                    panic!(
2675
                        "at the time of writing, standard32 name mangling only supports the \
2676
                         synchronous ABI and does not define future/stream intrinsic imports; \
2677
                         use legacy mangling for these imports"
2678
                    )
2679
                }
2680
            },
2681
4.86k
            ManglingAndAbi::Legacy(abi) => match import {
2682
1.33k
                WasmImport::Func { interface, func } => {
2683
1.33k
                    let module = match interface {
2684
735
                        Some(key) => self.name_world_key(key),
2685
596
                        None => format!("$root"),
2686
                    };
2687
1.33k
                    (module, format!("{}{}", abi.import_prefix(), func.name))
2688
                }
2689
                WasmImport::ResourceIntrinsic {
2690
772
                    interface,
2691
772
                    resource,
2692
772
                    intrinsic,
2693
                } => {
2694
772
                    let name = self.types[resource].name.as_ref().unwrap();
2695
772
                    let (prefix, name) = match intrinsic {
2696
154
                        ResourceIntrinsic::ImportedDrop => ("", format!("[resource-drop]{name}")),
2697
                        ResourceIntrinsic::ExportedDrop => {
2698
206
                            ("[export]", format!("[resource-drop]{name}"))
2699
                        }
2700
                        ResourceIntrinsic::ExportedNew => {
2701
206
                            ("[export]", format!("[resource-new]{name}"))
2702
                        }
2703
                        ResourceIntrinsic::ExportedRep => {
2704
206
                            ("[export]", format!("[resource-rep]{name}"))
2705
                        }
2706
                    };
2707
772
                    let module = match interface {
2708
707
                        Some(key) => format!("{prefix}{}", self.name_world_key(key)),
2709
                        None => {
2710
65
                            assert_eq!(prefix, "");
2711
65
                            format!("$root")
2712
                        }
2713
                    };
2714
772
                    (module, format!("{}{name}", abi.import_prefix()))
2715
                }
2716
                WasmImport::FutureIntrinsic {
2717
1.74k
                    interface,
2718
1.74k
                    func,
2719
1.74k
                    ty,
2720
1.74k
                    intrinsic,
2721
1.74k
                    exported,
2722
1.74k
                    async_,
2723
                } => {
2724
1.74k
                    let module_prefix = if exported { "[export]" } else { "" };
2725
1.74k
                    let module = match interface {
2726
1.44k
                        Some(key) => format!("{module_prefix}{}", self.name_world_key(key)),
2727
300
                        None => format!("{module_prefix}$root"),
2728
                    };
2729
1.74k
                    let type_index = match ty {
2730
1.74k
                        Some(ty) => func
2731
1.74k
                            .find_futures_and_streams(self)
2732
1.74k
                            .into_iter()
2733
9.79k
                            .position(|candidate| candidate == ty)
2734
1.74k
                            .unwrap_or_else(|| {
2735
0
                                panic!(
2736
                                    "future type {ty:?} not found in `find_futures_and_streams` for `{}`",
2737
                                    func.name
2738
                                )
2739
                            })
2740
1.74k
                            .to_string(),
2741
0
                        None => "unit".to_string(),
2742
                    };
2743
1.74k
                    let (async_prefix, name) = match intrinsic {
2744
                        FutureIntrinsic::New => {
2745
145
                            assert!(!async_, "future.new cannot be async-lowered");
2746
145
                            ("", "new")
2747
                        }
2748
                        FutureIntrinsic::Read => {
2749
290
                            (if async_ { "[async-lower]" } else { "" }, "read")
2750
                        }
2751
                        FutureIntrinsic::Write => {
2752
290
                            (if async_ { "[async-lower]" } else { "" }, "write")
2753
                        }
2754
                        FutureIntrinsic::Forward => {
2755
145
                            assert!(!async_, "future.forward cannot be async-lowered");
2756
145
                            ("", "forward")
2757
                        }
2758
                        FutureIntrinsic::CancelRead => {
2759
290
                            (if async_ { "[async-lower]" } else { "" }, "cancel-read")
2760
                        }
2761
                        FutureIntrinsic::CancelWrite => {
2762
290
                            (if async_ { "[async-lower]" } else { "" }, "cancel-write")
2763
                        }
2764
                        FutureIntrinsic::DropReadable => {
2765
145
                            assert!(!async_, "future.drop-readable cannot be async-lowered");
2766
145
                            ("", "drop-readable")
2767
                        }
2768
                        FutureIntrinsic::DropWritable => {
2769
145
                            assert!(!async_, "future.drop-writable cannot be async-lowered");
2770
145
                            ("", "drop-writable")
2771
                        }
2772
                    };
2773
1.74k
                    (
2774
1.74k
                        module,
2775
1.74k
                        format!("{async_prefix}[future-{name}-{type_index}]{}", func.name),
2776
1.74k
                    )
2777
                }
2778
                WasmImport::StreamIntrinsic {
2779
1.02k
                    interface,
2780
1.02k
                    func,
2781
1.02k
                    ty,
2782
1.02k
                    intrinsic,
2783
1.02k
                    exported,
2784
1.02k
                    async_,
2785
                } => {
2786
1.02k
                    let module_prefix = if exported { "[export]" } else { "" };
2787
1.02k
                    let module = match interface {
2788
408
                        Some(key) => format!("{module_prefix}{}", self.name_world_key(key)),
2789
612
                        None => format!("{module_prefix}$root"),
2790
                    };
2791
1.02k
                    let type_index = match ty {
2792
1.02k
                        Some(ty) => func
2793
1.02k
                            .find_futures_and_streams(self)
2794
1.02k
                            .into_iter()
2795
5.07k
                            .position(|candidate| candidate == ty)
2796
1.02k
                            .unwrap_or_else(|| {
2797
0
                                panic!(
2798
                                    "stream type {ty:?} not found in `find_futures_and_streams` for `{}`",
2799
                                    func.name
2800
                                )
2801
                            })
2802
1.02k
                            .to_string(),
2803
0
                        None => "unit".to_string(),
2804
                    };
2805
1.02k
                    let (async_prefix, name) = match intrinsic {
2806
                        StreamIntrinsic::New => {
2807
85
                            assert!(!async_, "stream.new cannot be async-lowered");
2808
85
                            ("", "new")
2809
                        }
2810
                        StreamIntrinsic::Read => {
2811
170
                            (if async_ { "[async-lower]" } else { "" }, "read")
2812
                        }
2813
                        StreamIntrinsic::Write => {
2814
170
                            (if async_ { "[async-lower]" } else { "" }, "write")
2815
                        }
2816
                        StreamIntrinsic::Forward => {
2817
85
                            assert!(!async_, "stream.forward cannot be async-lowered");
2818
85
                            ("", "forward")
2819
                        }
2820
                        StreamIntrinsic::CancelRead => {
2821
170
                            (if async_ { "[async-lower]" } else { "" }, "cancel-read")
2822
                        }
2823
                        StreamIntrinsic::CancelWrite => {
2824
170
                            (if async_ { "[async-lower]" } else { "" }, "cancel-write")
2825
                        }
2826
                        StreamIntrinsic::DropReadable => {
2827
85
                            assert!(!async_, "stream.drop-readable cannot be async-lowered");
2828
85
                            ("", "drop-readable")
2829
                        }
2830
                        StreamIntrinsic::DropWritable => {
2831
85
                            assert!(!async_, "stream.drop-writable cannot be async-lowered");
2832
85
                            ("", "drop-writable")
2833
                        }
2834
                    };
2835
1.02k
                    (
2836
1.02k
                        module,
2837
1.02k
                        format!("{async_prefix}[stream-{name}-{type_index}]{}", func.name),
2838
1.02k
                    )
2839
                }
2840
            },
2841
        }
2842
5.02k
    }
2843
2844
    /// Returns the core wasm export name for the specified `export`.
2845
    ///
2846
    /// This is the same as [`Resolve::wasm_import_name`], except for exports.
2847
14.6k
    pub fn wasm_export_name(&self, mangling: ManglingAndAbi, export: WasmExport<'_>) -> String {
2848
14.6k
        match mangling {
2849
1.05k
            ManglingAndAbi::Standard32 => match export {
2850
                WasmExport::Func {
2851
528
                    interface,
2852
528
                    func,
2853
528
                    kind,
2854
                } => {
2855
528
                    let mut name = String::from("cm32p2|");
2856
528
                    if let Some(interface) = interface {
2857
480
                        let s = self.name_canonicalized_world_key(interface);
2858
480
                        name.push_str(&s);
2859
480
                    }
2860
528
                    name.push_str("|");
2861
528
                    name.push_str(&func.name);
2862
528
                    match kind {
2863
264
                        WasmExportKind::Normal => {}
2864
264
                        WasmExportKind::PostReturn => name.push_str("_post"),
2865
0
                        WasmExportKind::Callback => todo!(
2866
                            "not yet supported: \
2867
                             async callback functions using standard name mangling"
2868
                        ),
2869
                    }
2870
528
                    name
2871
                }
2872
                WasmExport::ResourceDtor {
2873
19
                    interface,
2874
19
                    resource,
2875
                } => {
2876
19
                    let name = self.types[resource].name.as_ref().unwrap();
2877
19
                    let interface = self.name_canonicalized_world_key(interface);
2878
19
                    format!("cm32p2|{interface}|{name}_dtor")
2879
                }
2880
168
                WasmExport::Memory => "cm32p2_memory".to_string(),
2881
168
                WasmExport::Initialize => "cm32p2_initialize".to_string(),
2882
168
                WasmExport::Realloc => "cm32p2_realloc".to_string(),
2883
            },
2884
13.6k
            ManglingAndAbi::Legacy(abi) => match export {
2885
                WasmExport::Func {
2886
4.23k
                    interface,
2887
4.23k
                    func,
2888
4.23k
                    kind,
2889
                } => {
2890
4.23k
                    let mut name = abi.export_prefix().to_string();
2891
4.23k
                    match kind {
2892
2.13k
                        WasmExportKind::Normal => {}
2893
1.90k
                        WasmExportKind::PostReturn => name.push_str("cabi_post_"),
2894
                        WasmExportKind::Callback => {
2895
188
                            assert!(matches!(abi, LiftLowerAbi::AsyncCallback));
2896
188
                            name = format!("[callback]{name}")
2897
                        }
2898
                    }
2899
4.23k
                    if let Some(interface) = interface {
2900
3.83k
                        let s = self.name_world_key(interface);
2901
3.83k
                        name.push_str(&s);
2902
3.83k
                        name.push_str("#");
2903
3.83k
                    }
2904
4.23k
                    name.push_str(&func.name);
2905
4.23k
                    name
2906
                }
2907
                WasmExport::ResourceDtor {
2908
206
                    interface,
2909
206
                    resource,
2910
                } => {
2911
206
                    let name = self.types[resource].name.as_ref().unwrap();
2912
206
                    let interface = self.name_world_key(interface);
2913
206
                    format!("{}{interface}#[dtor]{name}", abi.export_prefix())
2914
                }
2915
3.06k
                WasmExport::Memory => "memory".to_string(),
2916
3.06k
                WasmExport::Initialize => "_initialize".to_string(),
2917
3.06k
                WasmExport::Realloc => "cabi_realloc".to_string(),
2918
            },
2919
        }
2920
14.6k
    }
2921
2922
    /// This method will rewrite the `world` provided to ensure that, where
2923
    /// necessary, all types in interfaces referred to by the `world` have
2924
    /// nominal type ids for bindings generation.
2925
    ///
2926
    /// The need for this method primarily arises from bindings generators
2927
    /// generating types in a programming language. Bindings generators try to
2928
    /// generate a type-per-WIT-type but this becomes problematic in situations
2929
    /// such as when an `interface` is both imported and exported. For example:
2930
    ///
2931
    /// ```wit
2932
    /// interface x {
2933
    ///    resource r;
2934
    /// }
2935
    ///
2936
    /// world foo {
2937
    ///     import x;
2938
    ///     export x;
2939
    /// }
2940
    /// ```
2941
    ///
2942
    /// Here the `r` resource, before this method, exists once within this
2943
    /// [`Resolve`]. This is a problem for bindings generators because guest
2944
    /// languages typically want to represent this world with two types: one
2945
    /// for the import and one for the export. This matches component model
2946
    /// semantics where `r` is a different type between the import and the
2947
    /// export.
2948
    ///
2949
    /// The purpose of this method is to ensure that languages with nominal
2950
    /// types, where type identity is unique based on definition not structure,
2951
    /// will have an easier time generating bindings. This method will
2952
    /// duplicate the interface `x`, for example, and everything it contains.
2953
    /// This means that the `world foo` above will have a different
2954
    /// `InterfaceId` for the import and the export of `x`, despite them using
2955
    /// the same interface in WIT. This is intended to make bindings generators'
2956
    /// jobs much easier because now Id-uniqueness matches the semantic meaning
2957
    /// of the world as well.
2958
    ///
2959
    /// This function will rewrite imported/exported interfaces, as appropriate,
2960
    /// to all have unique ids if they would otherwise overlap with the imports.
2961
6.46k
    pub fn generate_nominal_type_ids(&mut self, world_id: WorldId) {
2962
6.46k
        let mut seen = HashSet::new();
2963
6.46k
        let mut interface_keys_rewritten = HashSet::new();
2964
6.46k
        let mut maps = CloneMaps::default();
2965
2966
        // Pull out the imports/exports from `self` to have simultaneous
2967
        // borrows.
2968
6.46k
        let world = &mut self.worlds[world_id];
2969
6.46k
        let mut imports = mem::take(&mut world.imports);
2970
6.46k
        let mut exports = mem::take(&mut world.exports);
2971
2972
        // Notably visit `imports` first as they always get priority in the
2973
        // order of having things imported from them. After `imports` are
2974
        // visited then process all `exports`.
2975
6.46k
        log::trace!("nominalizing world imports");
2976
6.46k
        self.nominalize_world_items(
2977
6.46k
            &mut maps,
2978
6.46k
            world_id,
2979
6.46k
            &mut imports,
2980
6.46k
            &mut seen,
2981
6.46k
            &mut interface_keys_rewritten,
2982
        );
2983
6.46k
        log::trace!("nominalizing world exports");
2984
6.46k
        self.nominalize_world_items(
2985
6.46k
            &mut maps,
2986
6.46k
            world_id,
2987
6.46k
            &mut exports,
2988
6.46k
            &mut seen,
2989
6.46k
            &mut interface_keys_rewritten,
2990
        );
2991
2992
        // Put that thing back where it came from, or so help me!
2993
6.46k
        let world = &mut self.worlds[world_id];
2994
6.46k
        assert!(world.imports.is_empty());
2995
6.46k
        assert!(world.exports.is_empty());
2996
6.46k
        world.imports = imports;
2997
6.46k
        world.exports = exports;
2998
2999
        #[cfg(debug_assertions)]
3000
        self.assert_valid();
3001
6.46k
    }
3002
3003
    /// Implementation of `generate_nominal_type_ids` which processes either a
3004
    /// world's imports or exports as specified in `items`.
3005
    ///
3006
    /// The parameters here are:
3007
    ///
3008
    /// * `maps` - the set of types that have previously been cloned by the
3009
    ///   previous stage, if any. This is used to update any dependencies of an
3010
    ///   interface that is cloned.
3011
    ///
3012
    /// * `world` - the world that's being nominalized.
3013
    ///
3014
    /// * `items` - either `imports` or `exports` for the `world`. This is
3015
    ///   mutated in-place to have keys/items rewritten as-needed.
3016
    ///
3017
    /// * `seen` - the set of interfaces that have been seen previously when
3018
    ///   iterating over this world. All interfaces processed are added to this
3019
    ///   set.
3020
    ///
3021
    /// * `interface_keys_rewritten` - a distinct set from `seen` which only
3022
    ///   tracks rewritten interfaces which have `WorldKey::Interface`. This is
3023
    ///   the set of interfaces which dependencies can pull types from, which
3024
    ///   needs to be tracked separately to know when to rewrite.
3025
12.9k
    fn nominalize_world_items(
3026
12.9k
        &mut self,
3027
12.9k
        maps: &mut CloneMaps,
3028
12.9k
        world: WorldId,
3029
12.9k
        items: &mut IndexMap<WorldKey, WorldItem>,
3030
12.9k
        seen: &mut HashSet<InterfaceId>,
3031
12.9k
        interface_keys_rewritten: &mut HashSet<InterfaceId>,
3032
12.9k
    ) {
3033
        // Overall the problem that this function is trying to solve is not an
3034
        // easy one. The input is an AST-like structure and the goal of this
3035
        // function is to effectively perform a name resolution pass. The end
3036
        // result is that if a thing points to another thing (e.g. type-use or
3037
        // interface id) then that represents the actual name resolution of what
3038
        // it points to.
3039
        //
3040
        // Currently, though, this isn't really a full-blown name resolution
3041
        // pass. This is a pretty simple "do things in the right order" and name
3042
        // resolution pops out. The conventions of WIT and how it translates to
3043
        // components is what falls out of this loop below.
3044
        //
3045
        // The first rule of WIT is that interfaces can only use types from
3046
        // other interface imports/exports. This notably excludes named imports.
3047
        // For example:
3048
        //
3049
        //      interface a {
3050
        //          type t = u32;
3051
        //      }
3052
        //
3053
        //      interface b {
3054
        //          use a.{t};
3055
        //      }
3056
        //
3057
        //      world w {
3058
        //          import a;
3059
        //          import b; // uses `import a`
3060
        //          import c: b; // also uses `import a`
3061
        //          import d: interface {
3062
        //              use a.{t}; // uses `import a`
3063
        //          }
3064
        //      }
3065
        //
3066
        // The next rule is that exported interfaces will use types from
3067
        // imports, unless the interface is also exported. For example:
3068
        //
3069
        //      interface a {
3070
        //          type t = u32;
3071
        //      }
3072
        //
3073
        //      interface b {
3074
        //          use a.{t};
3075
        //      }
3076
        //
3077
        //      world w1 {
3078
        //          import a;
3079
        //
3080
        //          export b; // uses `import a`
3081
        //          export c: b; // uses `import a`
3082
        //          export d: interface {
3083
        //              use a.{t}; // uses `import a`
3084
        //          }
3085
        //      }
3086
        //
3087
        //      world w2 {
3088
        //          export a;
3089
        //          export b; // uses `export a`
3090
        //          export c: b; // uses `export a`
3091
        //          export d: interface {
3092
        //              use a.{t}; // uses `export a`
3093
        //          }
3094
        //      }
3095
        //
3096
        // Finally, named imports, such as `import a: b` and `import a:
3097
        // interface { ... }` cannot be used by anything. They can only
3098
        // reference types in other interface imports/exports.
3099
        //
3100
        // Overall this is a pretty simplistic system. It's "good enough" for
3101
        // now but will almost certainly be expanded over time. The hope is that
3102
        // expanding this involves making this function more complicated but
3103
        // ideally nowhere else.
3104
3105
        // Given all that intro, the first thing we need to prioritize is that
3106
        // `WorldKey::Name`'d interfaces are visited after `WorldKey::Interface`
3107
        // interfaces. This is a bit of a weird result of how this function is
3108
        // implemented right now. This visit order is a bit of a hack and
3109
        // probably won't live beyond making WIT more powerful.
3110
        //
3111
        // Anyway, the reason for this has to do with the `CloneMaps` down
3112
        // below. Basically what we're doing here is cloning interfaces, but
3113
        // when doing so we need to be able to rewrite references to
3114
        // previously-cloned interfaces if need be. `CloneMaps` represents the
3115
        // aggregate results of all previous clones. Due to named interfaces
3116
        // never being importable-from it means that mutations to `CloneMaps`
3117
        // are discarded when named interfaces are cloned. The trick here
3118
        // happens where this unconditionally preserves all modifications to
3119
        // `CloneMaps` for `WorldKey::Interface` clones. Behavior then "falls
3120
        // out" where references to cloned interfaces are naturally rewritten.
3121
        //
3122
        // This all falls down, however, if an import is cloned and recorded.
3123
        // Interfaces can be both exported and imported, which would mean that
3124
        // the import and export are both cloned, and both need to be preserved
3125
        // in `CloneMaps`. Right now `CloneMaps` requires uniqueness when
3126
        // cloning (e.g. can't clone the same thing twice).
3127
        //
3128
        // Long story short: it's a hack that sort order here is the way it is.
3129
        // Sorry. Be prepared to delete this should WIT get more powerful.
3130
12.9k
        let mut order = items.iter().enumerate().collect::<Vec<_>>();
3131
21.6k
        order.sort_by_key(|(_, (key, item))| match (key, item) {
3132
15.6k
            (WorldKey::Name(_), WorldItem::Interface { .. }) => 1,
3133
6.00k
            _ => 0,
3134
21.6k
        });
3135
12.9k
        let mut to_rewrite = IndexMap::default();
3136
14.8k
        for (i, (key, item)) in order {
3137
14.8k
            let id = match item {
3138
10.7k
                WorldItem::Interface { id, .. } => *id,
3139
3140
                // Functions/types aren't rewritten, they're all nominal at the
3141
                // world-level anyway.
3142
4.13k
                WorldItem::Function(_) | WorldItem::Type { .. } => continue,
3143
            };
3144
3145
            // If this interface itself is being visited for the second time
3146
            // (e.g. imported & exported, imported twice, exported twice, etc),
3147
            // or if any dependency of this interface is rewritten, then the
3148
            // interface itself needs to be rewritten. Otherwise continue
3149
            // onwards.
3150
10.7k
            let duplicated = !seen.insert(id);
3151
10.7k
            let any_dep_rewritten = self
3152
10.7k
                .interface_direct_deps(id)
3153
10.7k
                .any(|dep| interface_keys_rewritten.contains(&dep));
3154
10.7k
            if !(duplicated || any_dep_rewritten) {
3155
3.27k
                log::trace!("{} already nominal", self.name_world_key(key));
3156
3.27k
                continue;
3157
7.43k
            }
3158
7.43k
            log::trace!("{} getting rewritten nominal", self.name_world_key(key));
3159
3160
            // If this is `WorldKey::Interface` then register this in the
3161
            // `interface_keys_rewritten` map, and also plumb this through to
3162
            // the rewriting stage to know whether `maps` needs to be reset or
3163
            // not.
3164
7.43k
            let is_name = matches!(key, WorldKey::Name(_));
3165
7.43k
            if !is_name {
3166
62
                assert!(interface_keys_rewritten.insert(id));
3167
7.37k
            }
3168
3169
7.43k
            to_rewrite
3170
7.43k
                .entry(id)
3171
7.43k
                .or_insert(Vec::new())
3172
7.43k
                .push((i, is_name));
3173
        }
3174
3175
        // Now that we know what to rewrite, rewrite everything.
3176
        //
3177
        // The trickiest part here is deciding what to do with `maps`. As
3178
        // interfaces are cloned they'll record all remappings of
3179
        // types/interfaces/etc within `maps`. We don't want to persist
3180
        // everything because if an interface is cloned twice then everything
3181
        // will get overwritten/corrupted within the map. In theory what we want
3182
        // is for `maps` to track, for any one interface, just the transitive
3183
        // set of dependencies for that interface and how they've been cloned.
3184
        // What's implemented here is an approximation of this that should work
3185
        // for now.
3186
        //
3187
        // Notably `to_rewrite` is an ordered list keyed by `InterfaceId`. This
3188
        // means that if we walk `to_rewrite` in order we're walking this in
3189
        // topological order. Second we then additionally sort the `list` for
3190
        // each `to_rewrite` entry to ensure that all `WorldKey::Name` items are
3191
        // visited first. In doing so we also discard all mutations to `maps`
3192
        // after visiting is done. In effect what this does is it discards all
3193
        // modifications due to `WorldKey::Name`, because nothing can depend on
3194
        // those interfaces, and then it preserves modifications for
3195
        // `WorldKey::Interface`, which other interfaces can indeed depend on.
3196
        // In the end this basically does a very careful walk over a very
3197
        // careful organization of `to_rewrite`.
3198
        //
3199
        // This'll need massive refactoring if WIT gets the ability to express
3200
        // arbitrary edges between interfaces. It's WIT-level restriction right
3201
        // now of sorts. There's no current way to model a `import a: i;` where
3202
        // `i`'s dependencies are pulled from `import b: dep`, for example.
3203
        // Right now if `i` depends on `dep` then that just always results in
3204
        // `import dep`.
3205
12.9k
        for (id, mut list) in to_rewrite {
3206
11.8k
            list.sort_by_key(|(_, is_name)| if *is_name { 0 } else { 1 });
3207
7.43k
            for (i, is_name) in list {
3208
7.43k
                let prev_maps = if is_name { Some(maps.clone()) } else { None };
3209
3210
7.43k
                let mut cloner = clone::Cloner::new(
3211
7.43k
                    self,
3212
7.43k
                    maps,
3213
7.43k
                    TypeOwner::World(world),
3214
7.43k
                    TypeOwner::World(world),
3215
                );
3216
3217
7.43k
                let mut new_id = id;
3218
7.43k
                cloner.new_package = cloner.resolve.interfaces[id].package;
3219
7.43k
                cloner.interface(&mut new_id);
3220
7.43k
                let (key, prev) = items.get_index_mut(i).unwrap();
3221
7.43k
                match prev {
3222
7.43k
                    WorldItem::Interface { id, .. } => *id = new_id,
3223
0
                    _ => unreachable!(),
3224
                }
3225
3226
7.43k
                match key {
3227
                    // If the key for this is an `Interface` then that means we
3228
                    // need to update the key as well. Here that's replaced by-index
3229
                    // in the `IndexMap` to preserve the same ordering as before,
3230
                    // and this operation should always succeed since `new_id` is
3231
                    // fresh, hence the `unwrap()`.
3232
62
                    WorldKey::Interface(_) => {
3233
62
                        items.replace_index(i, WorldKey::Interface(new_id)).unwrap();
3234
62
                    }
3235
3236
                    // Name-based keys don't need updating as they only contain a
3237
                    // string, no ids.
3238
7.37k
                    WorldKey::Name(_) => {}
3239
                }
3240
3241
7.43k
                if let Some(prev) = prev_maps {
3242
7.37k
                    *maps = prev;
3243
7.37k
                }
3244
            }
3245
        }
3246
12.9k
    }
3247
}
3248
3249
/// Possible imports that can be passed to [`Resolve::wasm_import_name`].
3250
#[derive(Debug)]
3251
pub enum WasmImport<'a> {
3252
    /// A WIT function is being imported. Optionally from an interface.
3253
    Func {
3254
        /// The name of the interface that the function is being imported from.
3255
        ///
3256
        /// If the function is imported directly from the world then this is
3257
        /// `None`.
3258
        interface: Option<&'a WorldKey>,
3259
3260
        /// The function being imported.
3261
        func: &'a Function,
3262
    },
3263
3264
    /// A resource-related intrinsic is being imported.
3265
    ResourceIntrinsic {
3266
        /// The optional interface to import from, same as `WasmImport::Func`.
3267
        interface: Option<&'a WorldKey>,
3268
3269
        /// The resource that's being operated on.
3270
        resource: TypeId,
3271
3272
        /// The intrinsic that's being imported.
3273
        intrinsic: ResourceIntrinsic,
3274
    },
3275
3276
    /// A future-related intrinsic is being imported.
3277
    FutureIntrinsic {
3278
        /// The optional interface to import from, same as `WasmImport::Func`.
3279
        interface: Option<&'a WorldKey>,
3280
3281
        /// The function whose signature this future type appears in.
3282
        func: &'a Function,
3283
3284
        /// The future type appearing in `func.find_futures_and_streams(resolve)`.
3285
        ///
3286
        /// Use `None` for the special `unit` payload case.
3287
        ty: Option<TypeId>,
3288
3289
        /// The intrinsic that's being imported.
3290
        intrinsic: FutureIntrinsic,
3291
3292
        /// Whether this import is for an exported WIT function.
3293
        ///
3294
        /// This controls whether the module name is prefixed with `[export]`.
3295
        exported: bool,
3296
3297
        /// Whether this intrinsic import is async-lowered.
3298
        ///
3299
        /// This is only valid for read/write/cancel intrinsics.
3300
        async_: bool,
3301
    },
3302
3303
    /// A stream-related intrinsic is being imported.
3304
    StreamIntrinsic {
3305
        /// The optional interface to import from, same as `WasmImport::Func`.
3306
        interface: Option<&'a WorldKey>,
3307
3308
        /// The function whose signature this stream type appears in.
3309
        func: &'a Function,
3310
3311
        /// The stream type appearing in `func.find_futures_and_streams(resolve)`.
3312
        ///
3313
        /// Use `None` for the special `unit` payload case.
3314
        ty: Option<TypeId>,
3315
3316
        /// The intrinsic that's being imported.
3317
        intrinsic: StreamIntrinsic,
3318
3319
        /// Whether this import is for an exported WIT function.
3320
        ///
3321
        /// This controls whether the module name is prefixed with `[export]`.
3322
        exported: bool,
3323
3324
        /// Whether this intrinsic import is async-lowered.
3325
        ///
3326
        /// This is only valid for read/write/cancel intrinsics.
3327
        async_: bool,
3328
    },
3329
}
3330
3331
/// Intrinsic definitions to go with [`WasmImport::ResourceIntrinsic`] which
3332
/// also goes with [`Resolve::wasm_import_name`].
3333
#[derive(Debug)]
3334
pub enum ResourceIntrinsic {
3335
    ImportedDrop,
3336
    ExportedDrop,
3337
    ExportedNew,
3338
    ExportedRep,
3339
}
3340
3341
/// Intrinsic definitions to go with [`WasmImport::FutureIntrinsic`] which
3342
/// also goes with [`Resolve::wasm_import_name`].
3343
#[derive(Debug)]
3344
pub enum FutureIntrinsic {
3345
    New,
3346
    Read,
3347
    Write,
3348
    Forward,
3349
    CancelRead,
3350
    CancelWrite,
3351
    DropReadable,
3352
    DropWritable,
3353
}
3354
3355
/// Intrinsic definitions to go with [`WasmImport::StreamIntrinsic`] which
3356
/// also goes with [`Resolve::wasm_import_name`].
3357
#[derive(Debug)]
3358
pub enum StreamIntrinsic {
3359
    New,
3360
    Read,
3361
    Write,
3362
    Forward,
3363
    CancelRead,
3364
    CancelWrite,
3365
    DropReadable,
3366
    DropWritable,
3367
}
3368
3369
/// Indicates whether a function export is a normal export, a post-return
3370
/// function, or a callback function.
3371
#[derive(Debug)]
3372
pub enum WasmExportKind {
3373
    /// Normal function export.
3374
    Normal,
3375
3376
    /// Post-return function.
3377
    PostReturn,
3378
3379
    /// Async callback function.
3380
    Callback,
3381
}
3382
3383
/// Different kinds of exports that can be passed to
3384
/// [`Resolve::wasm_export_name`] to export from core wasm modules.
3385
#[derive(Debug)]
3386
pub enum WasmExport<'a> {
3387
    /// A WIT function is being exported, optionally from an interface.
3388
    Func {
3389
        /// An optional interface which owns `func`. Use `None` for top-level
3390
        /// world function.
3391
        interface: Option<&'a WorldKey>,
3392
3393
        /// The function being exported.
3394
        func: &'a Function,
3395
3396
        /// Kind of function (normal, post-return, or callback) being exported.
3397
        kind: WasmExportKind,
3398
    },
3399
3400
    /// A destructor for a resource exported from this module.
3401
    ResourceDtor {
3402
        /// The interface that owns the resource.
3403
        interface: &'a WorldKey,
3404
        /// The resource itself that the destructor is for.
3405
        resource: TypeId,
3406
    },
3407
3408
    /// Linear memory, the one that the canonical ABI uses.
3409
    Memory,
3410
3411
    /// An initialization function (not the core wasm `start`).
3412
    Initialize,
3413
3414
    /// The general-purpose realloc hook.
3415
    Realloc,
3416
}
3417
3418
/// Structure returned by [`Resolve::merge`] which contains mappings from
3419
/// old-ids to new-ids after the merge.
3420
#[derive(Default)]
3421
pub struct Remap {
3422
    pub types: Vec<Option<TypeId>>,
3423
    pub interfaces: Vec<Option<InterfaceId>>,
3424
    pub worlds: Vec<Option<WorldId>>,
3425
    pub packages: Vec<PackageId>,
3426
3427
    /// A cache of anonymous `own<T>` handles for resource types.
3428
    ///
3429
    /// The appending operation of `Remap` is the one responsible for
3430
    /// translating references to `T` where `T` is a resource into `own<T>`
3431
    /// instead. This map is used to deduplicate the `own<T>` types generated
3432
    /// to generate as few as possible.
3433
    ///
3434
    /// The key of this map is the resource id `T` in the new resolve, and
3435
    /// the value is the `own<T>` type pointing to `T`.
3436
    own_handles: HashMap<TypeId, TypeId>,
3437
3438
    type_has_borrow: Vec<Option<bool>>,
3439
}
3440
3441
389k
fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Span) -> ResolveResult<Id<T>> {
3442
389k
    match map.get(id.index()) {
3443
389k
        Some(Some(id)) => Ok(*id),
3444
        Some(None) => {
3445
0
            let msg = format!(
3446
                "found a reference to a {desc} which is excluded \
3447
                 due to its feature not being activated"
3448
            );
3449
0
            Err(ResolveError::new_semantic(span, msg))
3450
        }
3451
0
        None => panic!("request to remap a {desc} that has not yet been registered"),
3452
    }
3453
389k
}
wit_parser::resolve::apply_map::<wit_parser::World>
Line
Count
Source
3441
35.6k
fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Span) -> ResolveResult<Id<T>> {
3442
35.6k
    match map.get(id.index()) {
3443
35.6k
        Some(Some(id)) => Ok(*id),
3444
        Some(None) => {
3445
0
            let msg = format!(
3446
                "found a reference to a {desc} which is excluded \
3447
                 due to its feature not being activated"
3448
            );
3449
0
            Err(ResolveError::new_semantic(span, msg))
3450
        }
3451
0
        None => panic!("request to remap a {desc} that has not yet been registered"),
3452
    }
3453
35.6k
}
wit_parser::resolve::apply_map::<wit_parser::TypeDef>
Line
Count
Source
3441
245k
fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Span) -> ResolveResult<Id<T>> {
3442
245k
    match map.get(id.index()) {
3443
245k
        Some(Some(id)) => Ok(*id),
3444
        Some(None) => {
3445
0
            let msg = format!(
3446
                "found a reference to a {desc} which is excluded \
3447
                 due to its feature not being activated"
3448
            );
3449
0
            Err(ResolveError::new_semantic(span, msg))
3450
        }
3451
0
        None => panic!("request to remap a {desc} that has not yet been registered"),
3452
    }
3453
245k
}
wit_parser::resolve::apply_map::<wit_parser::Interface>
Line
Count
Source
3441
108k
fn apply_map<T>(map: &[Option<Id<T>>], id: Id<T>, desc: &str, span: Span) -> ResolveResult<Id<T>> {
3442
108k
    match map.get(id.index()) {
3443
108k
        Some(Some(id)) => Ok(*id),
3444
        Some(None) => {
3445
0
            let msg = format!(
3446
                "found a reference to a {desc} which is excluded \
3447
                 due to its feature not being activated"
3448
            );
3449
0
            Err(ResolveError::new_semantic(span, msg))
3450
        }
3451
0
        None => panic!("request to remap a {desc} that has not yet been registered"),
3452
    }
3453
108k
}
3454
3455
0
fn rename(original_name: &str, include_name: &IncludeName) -> Option<String> {
3456
    // Strip all leading `[...]` annotations.
3457
0
    let mut prefix_len = 0;
3458
0
    while original_name[prefix_len..].starts_with('[') {
3459
0
        let close = original_name[prefix_len..].find(']')?;
3460
0
        prefix_len += close + 1;
3461
    }
3462
0
    let (prefix, rest) = original_name.split_at(prefix_len);
3463
3464
0
    match rest.split_once('.') {
3465
        // Rename just the resource portion.
3466
0
        Some((resource, func)) if resource == include_name.name => {
3467
0
            Some(format!("{prefix}{}.{func}", include_name.as_))
3468
        }
3469
        // Rename the whole label.
3470
0
        None if rest == include_name.name => Some(format!("{prefix}{}", include_name.as_)),
3471
0
        _ => None,
3472
    }
3473
0
}
3474
3475
impl Remap {
3476
245k
    pub fn map_type(&self, id: TypeId, span: Span) -> ResolveResult<TypeId> {
3477
245k
        apply_map(&self.types, id, "type", span)
3478
245k
    }
3479
3480
108k
    pub fn map_interface(&self, id: InterfaceId, span: Span) -> ResolveResult<InterfaceId> {
3481
108k
        apply_map(&self.interfaces, id, "interface", span)
3482
108k
    }
3483
3484
35.6k
    pub fn map_world(&self, id: WorldId, span: Span) -> ResolveResult<WorldId> {
3485
35.6k
        apply_map(&self.worlds, id, "world", span)
3486
35.6k
    }
3487
3488
5.97k
    pub fn map_world_for_type(&self, id: WorldId, span: Span) -> ResolveResult<WorldId> {
3489
5.97k
        self.map_world(id, span).map_err(|e| {
3490
0
            ResolveError::new_semantic(
3491
0
                span,
3492
0
                format!("{e}; this type is not gated by a feature but its world is"),
3493
            )
3494
0
        })
3495
5.97k
    }
3496
3497
37.8k
    pub fn map_interface_for_type(
3498
37.8k
        &self,
3499
37.8k
        id: InterfaceId,
3500
37.8k
        span: Span,
3501
37.8k
    ) -> ResolveResult<InterfaceId> {
3502
37.8k
        self.map_interface(id, span).map_err(|e| {
3503
0
            ResolveError::new_semantic(
3504
0
                span,
3505
0
                format!("{e}; this type is not gated by a feature but its interface is"),
3506
            )
3507
0
        })
3508
37.8k
    }
3509
3510
11.8k
    fn append(
3511
11.8k
        &mut self,
3512
11.8k
        resolve: &mut Resolve,
3513
11.8k
        unresolved: UnresolvedPackage,
3514
11.8k
    ) -> ResolveResult<PackageId> {
3515
11.8k
        let pkgid = resolve.packages.alloc(Package {
3516
11.8k
            name: unresolved.name.clone(),
3517
11.8k
            docs: unresolved.docs.clone(),
3518
11.8k
            interfaces: Default::default(),
3519
11.8k
            worlds: Default::default(),
3520
11.8k
        });
3521
11.8k
        assert!(
3522
11.8k
            !resolve.package_names.contains_key(&unresolved.name),
3523
            "attempting to re-add package `{}` when it's already present in this `Resolve`",
3524
            unresolved.name,
3525
        );
3526
11.8k
        resolve.package_names.insert(unresolved.name.clone(), pkgid);
3527
11.8k
        self.process_foreign_deps(resolve, pkgid, &unresolved)?;
3528
3529
11.8k
        let foreign_types = self.types.len();
3530
11.8k
        let foreign_interfaces = self.interfaces.len();
3531
11.8k
        let foreign_worlds = self.worlds.len();
3532
3533
        // Copy over all types first, updating any intra-type references. Note
3534
        // that types are sorted topologically which means this iteration
3535
        // order should be sufficient. Also note though that the interface
3536
        // owner of a type isn't updated here due to interfaces not being known
3537
        // yet.
3538
120k
        for (id, mut ty) in unresolved.types.into_iter().skip(foreign_types) {
3539
120k
            let span = ty.span;
3540
120k
            if !resolve.include_stability(&ty.stability, &pkgid, span)? {
3541
0
                self.types.push(None);
3542
0
                continue;
3543
120k
            }
3544
3545
120k
            self.update_typedef(resolve, &mut ty, span)?;
3546
120k
            let new_id = resolve.types.alloc(ty);
3547
120k
            assert_eq!(self.types.len(), id.index());
3548
3549
120k
            let new_id = match resolve.types[new_id] {
3550
                // If this is an `own<T>` handle then either replace it with a
3551
                // preexisting `own<T>` handle which may have been generated in
3552
                // `update_ty`. If that doesn't exist though then insert it into
3553
                // the `own_handles` cache.
3554
                TypeDef {
3555
                    name: None,
3556
                    owner: TypeOwner::None,
3557
0
                    kind: TypeDefKind::Handle(Handle::Own(id)),
3558
                    docs: _,
3559
                    stability: _,
3560
                    span: _,
3561
                    external_id: _,
3562
0
                } => *self.own_handles.entry(id).or_insert(new_id),
3563
3564
                // Everything not-related to `own<T>` doesn't get its ID
3565
                // modified.
3566
120k
                _ => new_id,
3567
            };
3568
120k
            self.types.push(Some(new_id));
3569
        }
3570
3571
        // Next transfer all interfaces into `Resolve`, updating type ids
3572
        // referenced along the way.
3573
44.1k
        for (id, mut iface) in unresolved.interfaces.into_iter().skip(foreign_interfaces) {
3574
44.1k
            let span = iface.span;
3575
44.1k
            if !resolve.include_stability(&iface.stability, &pkgid, span)? {
3576
0
                self.interfaces.push(None);
3577
0
                continue;
3578
44.1k
            }
3579
44.1k
            assert!(iface.package.is_none());
3580
44.1k
            iface.package = Some(pkgid);
3581
44.1k
            self.update_interface(resolve, &mut iface)?;
3582
44.1k
            let new_id = resolve.interfaces.alloc(iface);
3583
44.1k
            assert_eq!(self.interfaces.len(), id.index());
3584
44.1k
            self.interfaces.push(Some(new_id));
3585
        }
3586
3587
        // Now that interfaces are identified go back through the types and
3588
        // update their interface owners.
3589
120k
        for id in self.types.iter().skip(foreign_types) {
3590
120k
            let id = match id {
3591
120k
                Some(id) => *id,
3592
0
                None => continue,
3593
            };
3594
120k
            let span = resolve.types[id].span;
3595
120k
            match &mut resolve.types[id].owner {
3596
37.8k
                TypeOwner::Interface(iface_id) => {
3597
37.8k
                    *iface_id = self.map_interface_for_type(*iface_id, span)?;
3598
                }
3599
82.5k
                TypeOwner::World(_) | TypeOwner::None => {}
3600
            }
3601
        }
3602
3603
        // Expand worlds. Note that this does NOT process `include` statements,
3604
        // that's handled below. Instead this just handles world item updates
3605
        // and resolves references to types/items within `Resolve`.
3606
        //
3607
        // This is done after types/interfaces are fully settled so the
3608
        // transitive relation between interfaces, through types, is understood
3609
        // here.
3610
16.3k
        for (id, mut world) in unresolved.worlds.into_iter().skip(foreign_worlds) {
3611
16.3k
            let world_span = world.span;
3612
16.3k
            if !resolve.include_stability(&world.stability, &pkgid, world_span)? {
3613
0
                self.worlds.push(None);
3614
0
                continue;
3615
16.3k
            }
3616
16.3k
            self.update_world(&mut world, resolve, &pkgid)?;
3617
3618
16.3k
            let new_id = resolve.worlds.alloc(world);
3619
16.3k
            assert_eq!(self.worlds.len(), id.index());
3620
16.3k
            self.worlds.push(Some(new_id));
3621
        }
3622
3623
        // As with interfaces, now update the ids of world-owned types.
3624
120k
        for id in self.types.iter().skip(foreign_types) {
3625
120k
            let id = match id {
3626
120k
                Some(id) => *id,
3627
0
                None => continue,
3628
            };
3629
120k
            let span = resolve.types[id].span;
3630
120k
            match &mut resolve.types[id].owner {
3631
5.97k
                TypeOwner::World(world_id) => {
3632
5.97k
                    *world_id = self.map_world_for_type(*world_id, span)?;
3633
                }
3634
114k
                TypeOwner::Interface(_) | TypeOwner::None => {}
3635
            }
3636
        }
3637
3638
        // After the above, process `include` statements for worlds and
3639
        // additionally fully elaborate them. Processing of `include` is
3640
        // deferred until after the steps above so the fully resolved state of
3641
        // local types in this package are all available. This is required
3642
        // because `include` may copy types between worlds when the type is
3643
        // defined in the world itself.
3644
        //
3645
        // This step, after processing `include`, will also use
3646
        // `elaborate_world` to fully expand the world in terms of
3647
        // imports/exports and ensure that all necessary imports/exports are all
3648
        // listed.
3649
        //
3650
        // Note that `self.worlds` is already sorted in topological order so if
3651
        // one world refers to another via `include` then it's guaranteed that
3652
        // the one we're referring to is already expanded and ready to be
3653
        // included.
3654
16.2k
        for id in self.worlds.iter().skip(foreign_worlds) {
3655
16.2k
            let Some(id) = *id else {
3656
0
                continue;
3657
            };
3658
16.2k
            self.process_world_includes(id, resolve, &pkgid)?;
3659
3660
16.2k
            let world_span = resolve.worlds[id].span;
3661
16.2k
            resolve.elaborate_world(id, world_span)?;
3662
        }
3663
3664
        // Fixup "parent" ids now that everything has been identified
3665
44.0k
        for id in self.interfaces.iter().skip(foreign_interfaces) {
3666
44.0k
            let id = match id {
3667
44.0k
                Some(id) => *id,
3668
0
                None => continue,
3669
            };
3670
44.0k
            let iface = &mut resolve.interfaces[id];
3671
44.0k
            iface.package = Some(pkgid);
3672
44.0k
            if let Some(name) = &iface.name {
3673
42.2k
                let prev = resolve.packages[pkgid].interfaces.insert(name.clone(), id);
3674
42.2k
                assert!(prev.is_none());
3675
1.78k
            }
3676
        }
3677
16.2k
        for id in self.worlds.iter().skip(foreign_worlds) {
3678
16.2k
            let id = match id {
3679
16.2k
                Some(id) => *id,
3680
0
                None => continue,
3681
            };
3682
16.2k
            let world = &mut resolve.worlds[id];
3683
16.2k
            world.package = Some(pkgid);
3684
16.2k
            let prev = resolve.packages[pkgid]
3685
16.2k
                .worlds
3686
16.2k
                .insert(world.name.clone(), id);
3687
16.2k
            assert!(prev.is_none());
3688
        }
3689
11.8k
        Ok(pkgid)
3690
11.8k
    }
3691
3692
11.8k
    fn process_foreign_deps(
3693
11.8k
        &mut self,
3694
11.8k
        resolve: &mut Resolve,
3695
11.8k
        pkgid: PackageId,
3696
11.8k
        unresolved: &UnresolvedPackage,
3697
11.8k
    ) -> ResolveResult<()> {
3698
        // Invert the `foreign_deps` map to be keyed by world id to get
3699
        // used in the loops below.
3700
11.8k
        let mut world_to_package = HashMap::new();
3701
11.8k
        let mut interface_to_package = HashMap::new();
3702
11.8k
        for (i, (pkg_name, worlds_or_ifaces)) in unresolved.foreign_deps.iter().enumerate() {
3703
3.53k
            for (name, (item, stabilities)) in worlds_or_ifaces {
3704
3.53k
                match item {
3705
3.53k
                    AstItem::Interface(unresolved_interface_id) => {
3706
3.53k
                        let prev = interface_to_package.insert(
3707
3.53k
                            *unresolved_interface_id,
3708
3.53k
                            (pkg_name, name, unresolved.foreign_dep_spans[i], stabilities),
3709
                        );
3710
3.53k
                        assert!(prev.is_none());
3711
                    }
3712
0
                    AstItem::World(unresolved_world_id) => {
3713
0
                        let prev = world_to_package.insert(
3714
0
                            *unresolved_world_id,
3715
0
                            (pkg_name, name, unresolved.foreign_dep_spans[i], stabilities),
3716
                        );
3717
0
                        assert!(prev.is_none());
3718
                    }
3719
                }
3720
            }
3721
        }
3722
3723
        // Connect all interfaces referred to in `interface_to_package`, which
3724
        // are at the front of `unresolved.interfaces`, to interfaces already
3725
        // contained within `resolve`.
3726
11.8k
        self.process_foreign_interfaces(unresolved, &interface_to_package, resolve, &pkgid)?;
3727
3728
        // Connect all worlds referred to in `world_to_package`, which
3729
        // are at the front of `unresolved.worlds`, to worlds already
3730
        // contained within `resolve`.
3731
11.8k
        self.process_foreign_worlds(unresolved, &world_to_package, resolve, &pkgid)?;
3732
3733
        // Finally, iterate over all foreign-defined types and determine
3734
        // what they map to.
3735
11.8k
        self.process_foreign_types(unresolved, pkgid, resolve)?;
3736
3737
11.8k
        for (id, span) in unresolved.required_resource_types.iter() {
3738
            // Note that errors are ignored here because an error represents a
3739
            // type that has been configured away. If a type is configured away
3740
            // then any future use of it will generate an error so there's no
3741
            // need to validate that it's a resource here.
3742
17
            let Ok(mut id) = self.map_type(*id, *span) else {
3743
0
                continue;
3744
            };
3745
            loop {
3746
19
                match resolve.types[id].kind {
3747
2
                    TypeDefKind::Type(Type::Id(i)) => id = i,
3748
17
                    TypeDefKind::Resource => break,
3749
                    _ => {
3750
0
                        return Err(ResolveError::new_semantic(
3751
0
                            *span,
3752
0
                            "type used in a handle must be a resource",
3753
0
                        ));
3754
                    }
3755
                }
3756
            }
3757
        }
3758
3759
        #[cfg(debug_assertions)]
3760
        resolve.assert_valid();
3761
3762
11.8k
        Ok(())
3763
11.8k
    }
3764
3765
11.8k
    fn process_foreign_interfaces(
3766
11.8k
        &mut self,
3767
11.8k
        unresolved: &UnresolvedPackage,
3768
11.8k
        interface_to_package: &HashMap<InterfaceId, (&PackageName, &String, Span, &Vec<Stability>)>,
3769
11.8k
        resolve: &mut Resolve,
3770
11.8k
        parent_pkg_id: &PackageId,
3771
11.8k
    ) -> ResolveResult<()> {
3772
14.2k
        for (unresolved_iface_id, unresolved_iface) in unresolved.interfaces.iter() {
3773
3.53k
            let (pkg_name, interface, span, stabilities) =
3774
14.2k
                match interface_to_package.get(&unresolved_iface_id) {
3775
3.53k
                    Some(items) => *items,
3776
                    // All foreign interfaces are defined first, so the first one
3777
                    // which is defined in a non-foreign document means that all
3778
                    // further interfaces will be non-foreign as well.
3779
10.6k
                    None => break,
3780
                };
3781
3782
3.53k
            let pkgid = resolve
3783
3.53k
                .package_names
3784
3.53k
                .get(pkg_name)
3785
3.53k
                .copied()
3786
3.53k
                .ok_or_else(|| {
3787
0
                    ResolveError::from(ResolveErrorKind::PackageNotFound {
3788
0
                        span,
3789
0
                        requested: pkg_name.clone(),
3790
0
                        known: resolve.package_names.keys().cloned().collect(),
3791
0
                    })
3792
0
                })?;
3793
3794
            // Functions can't be imported so this should be empty.
3795
3.53k
            assert!(unresolved_iface.functions.is_empty());
3796
3797
3.53k
            let pkg = &resolve.packages[pkgid];
3798
3.53k
            let iface_span = unresolved_iface.span;
3799
3800
3.53k
            let mut enabled = false;
3801
3.53k
            for stability in stabilities {
3802
3.53k
                if resolve.include_stability(stability, parent_pkg_id, iface_span)? {
3803
3.53k
                    enabled = true;
3804
3.53k
                    break;
3805
0
                }
3806
            }
3807
3808
3.53k
            if !enabled {
3809
0
                self.interfaces.push(None);
3810
0
                continue;
3811
3.53k
            }
3812
3813
3.53k
            let iface_id = pkg.interfaces.get(interface).copied().ok_or_else(|| {
3814
0
                ResolveError::from(ResolveErrorKind::InterfaceNotFound {
3815
0
                    span: iface_span,
3816
0
                    requested: interface.to_string(),
3817
0
                    package: pkg.name.clone(),
3818
0
                })
3819
0
            })?;
3820
3.53k
            assert_eq!(self.interfaces.len(), unresolved_iface_id.index());
3821
3.53k
            self.interfaces.push(Some(iface_id));
3822
        }
3823
44.1k
        for (id, _) in unresolved.interfaces.iter().skip(self.interfaces.len()) {
3824
44.1k
            assert!(
3825
44.1k
                interface_to_package.get(&id).is_none(),
3826
                "found foreign interface after local interface"
3827
            );
3828
        }
3829
11.8k
        Ok(())
3830
11.8k
    }
3831
3832
11.8k
    fn process_foreign_worlds(
3833
11.8k
        &mut self,
3834
11.8k
        unresolved: &UnresolvedPackage,
3835
11.8k
        world_to_package: &HashMap<WorldId, (&PackageName, &String, Span, &Vec<Stability>)>,
3836
11.8k
        resolve: &mut Resolve,
3837
11.8k
        parent_pkg_id: &PackageId,
3838
11.8k
    ) -> ResolveResult<()> {
3839
11.8k
        for (unresolved_world_id, unresolved_world) in unresolved.worlds.iter() {
3840
0
            let (pkg_name, world, span, stabilities) =
3841
8.19k
                match world_to_package.get(&unresolved_world_id) {
3842
0
                    Some(items) => *items,
3843
                    // Same as above, all worlds are foreign until we find a
3844
                    // non-foreign one.
3845
8.19k
                    None => break,
3846
                };
3847
3848
0
            let pkgid = resolve
3849
0
                .package_names
3850
0
                .get(pkg_name)
3851
0
                .copied()
3852
0
                .ok_or_else(|| {
3853
0
                    ResolveError::from(ResolveErrorKind::PackageNotFound {
3854
0
                        span,
3855
0
                        requested: pkg_name.clone(),
3856
0
                        known: resolve.package_names.keys().cloned().collect(),
3857
0
                    })
3858
0
                })?;
3859
0
            let pkg = &resolve.packages[pkgid];
3860
0
            let world_span = unresolved_world.span;
3861
3862
0
            let mut enabled = false;
3863
0
            for stability in stabilities {
3864
0
                if resolve.include_stability(stability, parent_pkg_id, world_span)? {
3865
0
                    enabled = true;
3866
0
                    break;
3867
0
                }
3868
            }
3869
3870
0
            if !enabled {
3871
0
                self.worlds.push(None);
3872
0
                continue;
3873
0
            }
3874
3875
0
            let world_id = pkg.worlds.get(world).copied().ok_or_else(|| {
3876
0
                ResolveError::from(ResolveErrorKind::WorldNotFound {
3877
0
                    span: world_span,
3878
0
                    requested: world.to_string(),
3879
0
                    package: pkg.name.clone(),
3880
0
                })
3881
0
            })?;
3882
0
            assert_eq!(self.worlds.len(), unresolved_world_id.index());
3883
0
            self.worlds.push(Some(world_id));
3884
        }
3885
16.3k
        for (id, _) in unresolved.worlds.iter().skip(self.worlds.len()) {
3886
16.3k
            assert!(
3887
16.3k
                world_to_package.get(&id).is_none(),
3888
                "found foreign world after local world"
3889
            );
3890
        }
3891
11.8k
        Ok(())
3892
11.8k
    }
3893
3894
11.8k
    fn process_foreign_types(
3895
11.8k
        &mut self,
3896
11.8k
        unresolved: &UnresolvedPackage,
3897
11.8k
        pkgid: PackageId,
3898
11.8k
        resolve: &mut Resolve,
3899
11.8k
    ) -> ResolveResult<()> {
3900
11.8k
        for (unresolved_type_id, unresolved_ty) in unresolved.types.iter() {
3901
            // All "Unknown" types should appear first so once we're no longer
3902
            // in unknown territory it's package-defined types so break out of
3903
            // this loop.
3904
10.8k
            match unresolved_ty.kind {
3905
2.49k
                TypeDefKind::Unknown => {}
3906
8.34k
                _ => break,
3907
            }
3908
3909
2.49k
            let span = unresolved_ty.span;
3910
2.49k
            if !resolve.include_stability(&unresolved_ty.stability, &pkgid, span)? {
3911
0
                self.types.push(None);
3912
0
                continue;
3913
2.49k
            }
3914
3915
2.49k
            let unresolved_iface_id = match unresolved_ty.owner {
3916
2.49k
                TypeOwner::Interface(id) => id,
3917
0
                _ => unreachable!(),
3918
            };
3919
2.49k
            let iface_id = self.map_interface(unresolved_iface_id, Default::default())?;
3920
2.49k
            let name = unresolved_ty.name.as_ref().unwrap();
3921
2.49k
            let span = unresolved.unknown_type_spans[unresolved_type_id.index()];
3922
2.49k
            let type_id = *resolve.interfaces[iface_id]
3923
2.49k
                .types
3924
2.49k
                .get(name)
3925
2.49k
                .ok_or_else(|| {
3926
0
                    ResolveError::new_semantic(
3927
0
                        span,
3928
0
                        format!("type `{name}` not defined in interface"),
3929
                    )
3930
0
                })?;
3931
2.49k
            assert_eq!(self.types.len(), unresolved_type_id.index());
3932
2.49k
            self.types.push(Some(type_id));
3933
        }
3934
120k
        for (_, ty) in unresolved.types.iter().skip(self.types.len()) {
3935
120k
            if let TypeDefKind::Unknown = ty.kind {
3936
0
                panic!("unknown type after defined type");
3937
120k
            }
3938
        }
3939
11.8k
        Ok(())
3940
11.8k
    }
3941
3942
159k
    fn update_typedef(
3943
159k
        &mut self,
3944
159k
        resolve: &mut Resolve,
3945
159k
        ty: &mut TypeDef,
3946
159k
        span: Span,
3947
159k
    ) -> ResolveResult<()> {
3948
        // NB: note that `ty.owner` is not updated here since interfaces
3949
        // haven't been mapped yet and that's done in a separate step.
3950
        use crate::TypeDefKind::*;
3951
5.33k
        match &mut ty.kind {
3952
1.39k
            Handle(handle) => match handle {
3953
1.22k
                crate::Handle::Own(ty) | crate::Handle::Borrow(ty) => {
3954
1.39k
                    self.update_type_id(ty, span)?
3955
                }
3956
            },
3957
2.74k
            Resource => {}
3958
3.87k
            Record(r) => {
3959
12.2k
                for field in r.fields.iter_mut() {
3960
12.2k
                    self.update_ty(resolve, &mut field.ty, field.span)?
3961
                }
3962
            }
3963
40.0k
            Tuple(t) => {
3964
134k
                for ty in t.types.iter_mut() {
3965
134k
                    self.update_ty(resolve, ty, span)?;
3966
                }
3967
            }
3968
5.41k
            Variant(v) => {
3969
19.4k
                for case in v.cases.iter_mut() {
3970
19.4k
                    if let Some(t) = &mut case.ty {
3971
15.9k
                        self.update_ty(resolve, t, span)?;
3972
3.44k
                    }
3973
                }
3974
            }
3975
20.3k
            Option(t)
3976
8.85k
            | List(t, ..)
3977
3.85k
            | FixedLengthList(t, ..)
3978
4.76k
            | Future(Some(t))
3979
44.2k
            | Stream(Some(t)) => self.update_ty(resolve, t, span)?,
3980
0
            Map(k, v) => {
3981
0
                self.update_ty(resolve, k, span)?;
3982
0
                self.update_ty(resolve, v, span)?;
3983
            }
3984
16.8k
            Result(r) => {
3985
16.8k
                if let Some(ty) = &mut r.ok {
3986
13.6k
                    self.update_ty(resolve, ty, span)?;
3987
3.21k
                }
3988
16.8k
                if let Some(ty) = &mut r.err {
3989
13.5k
                    self.update_ty(resolve, ty, span)?;
3990
3.28k
                }
3991
            }
3992
3993
            // Note that `update_ty` is specifically not used here as typedefs
3994
            // because for the `type a = b` form that doesn't force `a` to be a
3995
            // handle type if `b` is a resource type, instead `a` is
3996
            // simultaneously usable as a resource and a handle type
3997
17.6k
            Type(crate::Type::Id(id)) => self.update_type_id(id, span)?,
3998
1.93k
            Type(_) => {}
3999
4000
            // nothing to do for these as they're just names or empty
4001
25.5k
            Flags(_) | Enum(_) | Future(None) | Stream(None) => {}
4002
4003
0
            Unknown => unreachable!(),
4004
        }
4005
4006
159k
        Ok(())
4007
159k
    }
4008
4009
326k
    fn update_ty(&mut self, resolve: &mut Resolve, ty: &mut Type, span: Span) -> ResolveResult<()> {
4010
326k
        let id = match ty {
4011
123k
            Type::Id(id) => id,
4012
202k
            _ => return Ok(()),
4013
        };
4014
123k
        self.update_type_id(id, span)?;
4015
4016
        // If `id` points to a `Resource` type then this means that what was
4017
        // just discovered was a reference to what will implicitly become an
4018
        // `own<T>` handle. This `own` handle is implicitly allocated here
4019
        // and handled during the merging process.
4020
123k
        let mut cur = *id;
4021
123k
        let points_to_resource = loop {
4022
124k
            match resolve.types[cur].kind {
4023
655
                TypeDefKind::Type(Type::Id(id)) => cur = id,
4024
1.26k
                TypeDefKind::Resource => break true,
4025
122k
                _ => break false,
4026
            }
4027
        };
4028
4029
123k
        if points_to_resource {
4030
1.26k
            *id = *self.own_handles.entry(*id).or_insert_with(|| {
4031
658
                resolve.types.alloc(TypeDef {
4032
658
                    name: None,
4033
658
                    owner: TypeOwner::None,
4034
658
                    kind: TypeDefKind::Handle(Handle::Own(*id)),
4035
658
                    docs: Default::default(),
4036
658
                    stability: Default::default(),
4037
658
                    span: Default::default(),
4038
658
                    external_id: None,
4039
658
                })
4040
658
            });
4041
122k
        }
4042
123k
        Ok(())
4043
326k
    }
4044
4045
196k
    fn update_type_id(&self, id: &mut TypeId, span: Span) -> ResolveResult<()> {
4046
196k
        *id = self.map_type(*id, span)?;
4047
196k
        Ok(())
4048
196k
    }
4049
4050
47.8k
    fn update_interface(
4051
47.8k
        &mut self,
4052
47.8k
        resolve: &mut Resolve,
4053
47.8k
        iface: &mut Interface,
4054
47.8k
    ) -> ResolveResult<()> {
4055
48.6k
        iface.types.retain(|_, ty| self.types[ty.index()].is_some());
4056
47.8k
        let iface_pkg_id = iface.package.as_ref().unwrap_or_else(|| {
4057
0
            panic!(
4058
                "unexpectedly missing package on interface [{}]",
4059
0
                iface
4060
0
                    .name
4061
0
                    .as_ref()
4062
0
                    .map(String::as_str)
4063
0
                    .unwrap_or("<unknown>"),
4064
            )
4065
        });
4066
4067
        // NB: note that `iface.doc` is not updated here since interfaces
4068
        // haven't been mapped yet and that's done in a separate step.
4069
48.6k
        for (_name, ty) in iface.types.iter_mut() {
4070
48.6k
            self.update_type_id(ty, iface.span)?;
4071
        }
4072
47.8k
        for (_, func) in iface.functions.iter_mut() {
4073
18.5k
            let span = func.span;
4074
18.5k
            if !resolve.include_stability(&func.stability, iface_pkg_id, span)? {
4075
0
                continue;
4076
18.5k
            }
4077
18.5k
            self.update_function(resolve, func, span)?
4078
        }
4079
4080
        // Filter out all of the existing functions in interface which fail the
4081
        // `include_stability()` check, as they shouldn't be available.
4082
47.8k
        for (name, func) in mem::take(&mut iface.functions) {
4083
18.5k
            if resolve.include_stability(&func.stability, iface_pkg_id, func.span)? {
4084
18.5k
                iface.functions.insert(name, func);
4085
18.5k
            }
4086
        }
4087
4088
47.8k
        Ok(())
4089
47.8k
    }
4090
4091
26.0k
    fn update_function(
4092
26.0k
        &mut self,
4093
26.0k
        resolve: &mut Resolve,
4094
26.0k
        func: &mut Function,
4095
26.0k
        span: Span,
4096
26.0k
    ) -> ResolveResult<()> {
4097
26.0k
        if let Some(id) = func.kind.resource_mut() {
4098
4.89k
            self.update_type_id(id, span)?;
4099
21.1k
        }
4100
72.5k
        for param in func.params.iter_mut() {
4101
72.5k
            self.update_ty(resolve, &mut param.ty, span)?;
4102
        }
4103
26.0k
        if let Some(ty) = &mut func.result {
4104
19.3k
            self.update_ty(resolve, ty, span)?;
4105
6.71k
        }
4106
4107
26.0k
        if let Some(ty) = &func.result {
4108
19.3k
            if self.type_has_borrow(resolve, ty) {
4109
0
                return Err(ResolveError::new_semantic(
4110
0
                    span,
4111
0
                    format!(
4112
0
                        "function `{}` returns a type which contains a `borrow<T>` which is not supported",
4113
0
                        func.name,
4114
0
                    ),
4115
0
                ));
4116
19.3k
            }
4117
6.71k
        }
4118
4119
26.0k
        Ok(())
4120
26.0k
    }
4121
4122
16.3k
    fn update_world(
4123
16.3k
        &mut self,
4124
16.3k
        world: &mut World,
4125
16.3k
        resolve: &mut Resolve,
4126
16.3k
        pkg_id: &PackageId,
4127
16.3k
    ) -> ResolveResult<()> {
4128
        // Rewrite imports/exports with their updated versions. Note that this
4129
        // may involve updating the key of the imports/exports maps so this
4130
        // starts by emptying them out and then everything is re-inserted.
4131
16.3k
        let imports = mem::take(&mut world.imports).into_iter().map(|p| (p, true));
4132
16.3k
        let exports = mem::take(&mut world.exports)
4133
16.3k
            .into_iter()
4134
30.3k
            .map(|p| (p, false));
4135
43.1k
        for ((mut name, mut item), import) in imports.chain(exports) {
4136
43.1k
            let span = item.span();
4137
            // Update the `id` eagerly here so `item.stability(..)` below
4138
            // works.
4139
43.1k
            if let WorldItem::Type { id, .. } = &mut item {
4140
5.97k
                *id = self.map_type(*id, span)?;
4141
37.2k
            }
4142
43.1k
            let stability = item.stability(resolve);
4143
43.1k
            if !resolve.include_stability(stability, pkg_id, span)? {
4144
0
                continue;
4145
43.1k
            }
4146
43.1k
            self.update_world_key(&mut name, span)?;
4147
43.1k
            match &mut item {
4148
32.4k
                WorldItem::Interface { id, .. } => {
4149
32.4k
                    *id = self.map_interface(*id, span)?;
4150
                }
4151
4.76k
                WorldItem::Function(f) => {
4152
4.76k
                    self.update_function(resolve, f, span)?;
4153
                }
4154
5.97k
                WorldItem::Type { .. } => {
4155
5.97k
                    // already mapped above
4156
5.97k
                }
4157
            }
4158
4159
43.1k
            let dst = if import {
4160
12.8k
                &mut world.imports
4161
            } else {
4162
30.3k
                &mut world.exports
4163
            };
4164
43.1k
            let prev = dst.insert(name, item);
4165
43.1k
            assert!(prev.is_none());
4166
        }
4167
4168
16.3k
        Ok(())
4169
16.3k
    }
4170
4171
16.2k
    fn process_world_includes(
4172
16.2k
        &self,
4173
16.2k
        id: WorldId,
4174
16.2k
        resolve: &mut Resolve,
4175
16.2k
        pkg_id: &PackageId,
4176
16.2k
    ) -> ResolveResult<()> {
4177
16.2k
        let world = &mut resolve.worlds[id];
4178
        // Resolve all `include` statements of the world which will add more
4179
        // entries to the imports/exports list for this world.
4180
16.2k
        let includes = mem::take(&mut world.includes);
4181
16.2k
        for include in includes {
4182
0
            if !resolve.include_stability(&include.stability, pkg_id, include.span)? {
4183
0
                continue;
4184
0
            }
4185
0
            self.resolve_include(
4186
0
                id,
4187
0
                include.id,
4188
0
                &include.names,
4189
0
                include.span,
4190
0
                pkg_id,
4191
0
                resolve,
4192
0
            )?;
4193
        }
4194
4195
        // Validate that all names in the imports/exports are still strongly unique.
4196
16.2k
        Self::validate_world_strongly_unique_names(resolve, id)?;
4197
4198
        // Every setter must have a corresponding getter. This is checked here
4199
        // rather than at parse time since it's possible for a getter to come
4200
        // from an included WIT world.
4201
16.2k
        let world = &mut resolve.worlds[id];
4202
16.2k
        place_setters_after_getters(&mut world.imports, world_item_func);
4203
16.2k
        place_setters_after_getters(&mut world.exports, world_item_func);
4204
32.5k
        for (items, item_type) in [(&world.imports, "import"), (&world.exports, "export")] {
4205
42.8k
            for item in items.values() {
4206
42.8k
                if let Some(f) = world_item_func(item)
4207
4.75k
                    && f.kind.accessor() == Some(AccessorKind::Setter)
4208
                {
4209
0
                    let getter = f.name.replacen("[set]", "[get]", 1);
4210
0
                    if !items.contains_key(&WorldKey::Name(getter.clone())) {
4211
0
                        return Err(ResolveError::new_semantic(
4212
0
                            item.span(),
4213
0
                            format!(
4214
0
                                "{item_type} `{}` in world `{}` has no corresponding getter `{getter}`",
4215
0
                                f.name, world.name,
4216
0
                            ),
4217
0
                        ));
4218
0
                    }
4219
42.8k
                }
4220
            }
4221
        }
4222
4223
16.2k
        Ok(())
4224
16.2k
    }
4225
4226
    /// Validates that a world's imports and exports are each strongly unique.
4227
16.2k
    fn validate_world_strongly_unique_names(
4228
16.2k
        resolve: &Resolve,
4229
16.2k
        world_id: WorldId,
4230
16.2k
    ) -> ResolveResult<()> {
4231
        use wasmparser::names::ComponentName;
4232
4233
16.2k
        let world = &resolve.worlds[world_id];
4234
4235
16.2k
        let validate_names =
4236
32.5k
            |items: &IndexMap<WorldKey, WorldItem>, item_type: &str| -> ResolveResult<()> {
4237
32.5k
                let mut seen: HashMap<ComponentName, &str> = HashMap::new();
4238
4239
42.8k
                for key in items.keys() {
4240
                    // Only `WorldKey::Name` variants can conflict with each
4241
                    // other here because interfaces are keyed by ID.
4242
42.8k
                    let WorldKey::Name(name) = key else {
4243
1.23k
                        continue;
4244
                    };
4245
41.6k
                    let Ok(component_name) = crate::parse_component_name(name) else {
4246
0
                        continue;
4247
                    };
4248
4249
41.6k
                    if let Some(existing_name) = seen.get(&component_name) {
4250
                        // TODO: `WorldKey::Name` does not carry a `Span`, so we
4251
                        // cannot point at the conflicting item. Add a span to
4252
                        // `WorldKey::Name` to improve this error.
4253
0
                        return Err(ResolveError::new_semantic(
4254
0
                            Span::default(),
4255
0
                            format!(
4256
0
                                "{item_type} `{name}` in world `{}` conflicts with \
4257
0
                                 {item_type} `{existing_name}` \
4258
0
                                 (names must be strongly unique)",
4259
0
                                world.name,
4260
0
                            ),
4261
0
                        ));
4262
41.6k
                    }
4263
4264
41.6k
                    seen.insert(component_name, name);
4265
                }
4266
4267
32.5k
                Ok(())
4268
32.5k
            };
4269
4270
16.2k
        validate_names(&world.imports, "import")?;
4271
16.2k
        validate_names(&world.exports, "export")?;
4272
4273
16.2k
        Ok(())
4274
16.2k
    }
4275
4276
65.6k
    fn update_world_key(&self, key: &mut WorldKey, span: Span) -> ResolveResult<()> {
4277
65.6k
        match key {
4278
63.1k
            WorldKey::Name(_) => {}
4279
2.54k
            WorldKey::Interface(id) => {
4280
2.54k
                *id = self.map_interface(*id, span)?;
4281
            }
4282
        }
4283
65.6k
        Ok(())
4284
65.6k
    }
4285
4286
0
    fn resolve_include(
4287
0
        &self,
4288
0
        id: WorldId,
4289
0
        include_world_id_orig: WorldId,
4290
0
        names: &[IncludeName],
4291
0
        span: Span,
4292
0
        pkg_id: &PackageId,
4293
0
        resolve: &mut Resolve,
4294
0
    ) -> ResolveResult<()> {
4295
0
        let world = &resolve.worlds[id];
4296
0
        let include_world_id = self.map_world(include_world_id_orig, span)?;
4297
0
        let include_world = resolve.worlds[include_world_id].clone();
4298
0
        let mut names_ = names.to_owned();
4299
0
        let is_external_include = world.package != include_world.package;
4300
4301
        // remove all imports and exports that match the names we're including
4302
0
        for import in include_world.imports.iter() {
4303
0
            self.remove_matching_name(import, &mut names_);
4304
0
        }
4305
0
        for export in include_world.exports.iter() {
4306
0
            self.remove_matching_name(export, &mut names_);
4307
0
        }
4308
0
        if !names_.is_empty() {
4309
0
            return Err(ResolveError::new_semantic(
4310
0
                span,
4311
0
                format!(
4312
0
                    "no import or export kebab-name `{}`. Note that an ID does not support renaming",
4313
0
                    names_[0].name
4314
0
                ),
4315
0
            ));
4316
0
        }
4317
4318
0
        let mut maps = Default::default();
4319
0
        let mut cloner = clone::Cloner::new(
4320
0
            resolve,
4321
0
            &mut maps,
4322
0
            TypeOwner::World(if is_external_include {
4323
0
                include_world_id
4324
            } else {
4325
0
                include_world_id
4326
                // include_world_id_orig
4327
            }),
4328
0
            TypeOwner::World(id),
4329
        );
4330
0
        cloner.new_package = Some(*pkg_id);
4331
4332
        // copy the imports and exports from the included world into the current world
4333
0
        for import in include_world.imports.iter() {
4334
0
            self.resolve_include_item(
4335
0
                &mut cloner,
4336
0
                names,
4337
0
                |resolve| &mut resolve.worlds[id].imports,
4338
0
                import,
4339
0
                span,
4340
0
                "import",
4341
0
                is_external_include,
4342
0
            )?;
4343
        }
4344
4345
0
        for export in include_world.exports.iter() {
4346
0
            self.resolve_include_item(
4347
0
                &mut cloner,
4348
0
                names,
4349
0
                |resolve| &mut resolve.worlds[id].exports,
4350
0
                export,
4351
0
                span,
4352
0
                "export",
4353
0
                is_external_include,
4354
0
            )?;
4355
        }
4356
0
        Ok(())
4357
0
    }
4358
4359
0
    fn resolve_include_item(
4360
0
        &self,
4361
0
        cloner: &mut clone::Cloner<'_>,
4362
0
        names: &[IncludeName],
4363
0
        get_items: impl Fn(&mut Resolve) -> &mut IndexMap<WorldKey, WorldItem>,
4364
0
        item: (&WorldKey, &WorldItem),
4365
0
        span: Span,
4366
0
        item_type: &str,
4367
0
        is_external_include: bool,
4368
0
    ) -> ResolveResult<()> {
4369
0
        match item.0 {
4370
0
            WorldKey::Name(n) => {
4371
0
                let n = names
4372
0
                    .into_iter()
4373
0
                    .find_map(|include_name| rename(n, include_name))
Unexecuted instantiation: <wit_parser::resolve::Remap>::resolve_include_item::<<wit_parser::resolve::Remap>::resolve_include::{closure#0}>::{closure#0}
Unexecuted instantiation: <wit_parser::resolve::Remap>::resolve_include_item::<<wit_parser::resolve::Remap>::resolve_include::{closure#1}>::{closure#0}
4374
0
                    .unwrap_or(n.clone());
4375
4376
                // When the `with` option to the `include` directive is
4377
                // specified and is used to rename a function that means that
4378
                // the function's own original name needs to be updated, so
4379
                // reflect the change not only in the world key but additionally
4380
                // in the function itself.
4381
0
                let mut new_item = item.1.clone();
4382
0
                let key = WorldKey::Name(n.clone());
4383
0
                cloner.world_item(&key, &mut new_item);
4384
0
                match &mut new_item {
4385
0
                    WorldItem::Function(f) => f.name = n.clone(),
4386
0
                    WorldItem::Type { id, .. } => cloner.resolve.types[*id].name = Some(n.clone()),
4387
0
                    WorldItem::Interface { .. } => {}
4388
                }
4389
4390
0
                let prev = get_items(cloner.resolve).insert(key, new_item);
4391
0
                if prev.is_some() {
4392
0
                    return Err(ResolveError::from(ResolveErrorKind::ItemShadowing {
4393
0
                        span,
4394
0
                        item_type: item_type.to_owned(),
4395
0
                        name: n,
4396
0
                    }));
4397
0
                }
4398
            }
4399
0
            key @ WorldKey::Interface(_) => {
4400
0
                let prev = get_items(cloner.resolve)
4401
0
                    .entry(key.clone())
4402
0
                    .or_insert(item.1.clone());
4403
0
                match (&item.1, prev) {
4404
                    (
4405
                        WorldItem::Interface {
4406
0
                            id: aid,
4407
0
                            stability: astability,
4408
0
                            span: aspan,
4409
                            ..
4410
                        },
4411
                        WorldItem::Interface {
4412
0
                            id: bid,
4413
0
                            stability: bstability,
4414
                            ..
4415
                        },
4416
                    ) => {
4417
0
                        assert_eq!(*aid, *bid);
4418
0
                        merge_include_stability(
4419
0
                            astability,
4420
0
                            bstability,
4421
0
                            is_external_include,
4422
0
                            *aspan,
4423
0
                        )?;
4424
                    }
4425
0
                    (WorldItem::Interface { .. }, _) => unreachable!(),
4426
0
                    (WorldItem::Function(_), _) => unreachable!(),
4427
0
                    (WorldItem::Type { .. }, _) => unreachable!(),
4428
                }
4429
            }
4430
        };
4431
4432
0
        Ok(())
4433
0
    }
Unexecuted instantiation: <wit_parser::resolve::Remap>::resolve_include_item::<<wit_parser::resolve::Remap>::resolve_include::{closure#0}>
Unexecuted instantiation: <wit_parser::resolve::Remap>::resolve_include_item::<<wit_parser::resolve::Remap>::resolve_include::{closure#1}>
4434
4435
0
    fn remove_matching_name(&self, item: (&WorldKey, &WorldItem), names: &mut Vec<IncludeName>) {
4436
0
        match item.0 {
4437
0
            WorldKey::Name(n) => {
4438
0
                names.retain(|name| rename(n, name).is_none());
4439
            }
4440
0
            _ => {}
4441
        }
4442
0
    }
4443
4444
56.1k
    fn type_has_borrow(&mut self, resolve: &Resolve, ty: &Type) -> bool {
4445
56.1k
        let id = match ty {
4446
23.3k
            Type::Id(id) => *id,
4447
32.8k
            _ => return false,
4448
        };
4449
4450
23.3k
        if let Some(Some(has_borrow)) = self.type_has_borrow.get(id.index()) {
4451
2.78k
            return *has_borrow;
4452
20.5k
        }
4453
4454
20.5k
        let result = self.typedef_has_borrow(resolve, &resolve.types[id]);
4455
20.5k
        if self.type_has_borrow.len() <= id.index() {
4456
19.1k
            self.type_has_borrow.resize(id.index() + 1, None);
4457
19.1k
        }
4458
20.5k
        self.type_has_borrow[id.index()] = Some(result);
4459
20.5k
        result
4460
56.1k
    }
4461
4462
20.5k
    fn typedef_has_borrow(&mut self, resolve: &Resolve, ty: &TypeDef) -> bool {
4463
686
        match &ty.kind {
4464
76
            TypeDefKind::Type(t) => self.type_has_borrow(resolve, t),
4465
17
            TypeDefKind::Variant(v) => v
4466
17
                .cases
4467
17
                .iter()
4468
81
                .filter_map(|case| case.ty.as_ref())
4469
73
                .any(|ty| self.type_has_borrow(resolve, ty)),
4470
0
            TypeDefKind::Handle(Handle::Borrow(_)) => true,
4471
686
            TypeDefKind::Handle(Handle::Own(_)) => false,
4472
0
            TypeDefKind::Resource => false,
4473
57
            TypeDefKind::Record(r) => r
4474
57
                .fields
4475
57
                .iter()
4476
214
                .any(|case| self.type_has_borrow(resolve, &case.ty)),
4477
17
            TypeDefKind::Flags(_) => false,
4478
21.0k
            TypeDefKind::Tuple(t) => t.types.iter().any(|t| self.type_has_borrow(resolve, t)),
4479
100
            TypeDefKind::Enum(_) => false,
4480
1.81k
            TypeDefKind::List(ty)
4481
1.00k
            | TypeDefKind::FixedLengthList(ty, ..)
4482
787
            | TypeDefKind::Future(Some(ty))
4483
1.74k
            | TypeDefKind::Stream(Some(ty))
4484
7.94k
            | TypeDefKind::Option(ty) => self.type_has_borrow(resolve, ty),
4485
0
            TypeDefKind::Map(k, v) => {
4486
0
                self.type_has_borrow(resolve, k) || self.type_has_borrow(resolve, v)
4487
            }
4488
4.52k
            TypeDefKind::Result(r) => [&r.ok, &r.err]
4489
4.52k
                .iter()
4490
9.04k
                .filter_map(|t| t.as_ref())
4491
7.40k
                .any(|t| self.type_has_borrow(resolve, t)),
4492
105
            TypeDefKind::Future(None) | TypeDefKind::Stream(None) => false,
4493
0
            TypeDefKind::Unknown => unreachable!(),
4494
        }
4495
20.5k
    }
4496
}
4497
4498
struct MergeMap<'a> {
4499
    /// A map of package ids in `from` to those in `into` for those that are
4500
    /// found to be equivalent.
4501
    package_map: HashMap<PackageId, PackageId>,
4502
4503
    /// A map of interface ids in `from` to those in `into` for those that are
4504
    /// found to be equivalent.
4505
    interface_map: HashMap<InterfaceId, InterfaceId>,
4506
4507
    /// A map of type ids in `from` to those in `into` for those that are
4508
    /// found to be equivalent.
4509
    type_map: HashMap<TypeId, TypeId>,
4510
4511
    /// A map of world ids in `from` to those in `into` for those that are
4512
    /// found to be equivalent.
4513
    world_map: HashMap<WorldId, WorldId>,
4514
4515
    /// A list of documents that need to be added to packages in `into`.
4516
    ///
4517
    /// The elements here are:
4518
    ///
4519
    /// * The name of the interface/world
4520
    /// * The ID within `into` of the package being added to
4521
    /// * The ID within `from` of the item being added.
4522
    interfaces_to_add: Vec<(String, PackageId, InterfaceId)>,
4523
    worlds_to_add: Vec<(String, PackageId, WorldId)>,
4524
4525
    /// Which `Resolve` is being merged from.
4526
    from: &'a Resolve,
4527
4528
    /// Which `Resolve` is being merged into.
4529
    into: &'a Resolve,
4530
}
4531
4532
impl<'a> MergeMap<'a> {
4533
6.55k
    fn new(from: &'a Resolve, into: &'a Resolve) -> MergeMap<'a> {
4534
6.55k
        MergeMap {
4535
6.55k
            package_map: Default::default(),
4536
6.55k
            interface_map: Default::default(),
4537
6.55k
            type_map: Default::default(),
4538
6.55k
            world_map: Default::default(),
4539
6.55k
            interfaces_to_add: Default::default(),
4540
6.55k
            worlds_to_add: Default::default(),
4541
6.55k
            from,
4542
6.55k
            into,
4543
6.55k
        }
4544
6.55k
    }
4545
4546
6.55k
    fn build(&mut self) -> anyhow::Result<()> {
4547
11.0k
        for from_id in self.from.topological_packages() {
4548
11.0k
            let from = &self.from.packages[from_id];
4549
11.0k
            let into_id = match self.into.package_names.get(&from.name) {
4550
35
                Some(id) => *id,
4551
4552
                // This package, according to its name and url, is not present
4553
                // in `self` so it needs to get added below.
4554
                None => {
4555
11.0k
                    log::trace!("adding unique package {}", from.name);
4556
11.0k
                    continue;
4557
                }
4558
            };
4559
35
            log::trace!("merging duplicate package {}", from.name);
4560
4561
35
            self.build_package(from_id, into_id).with_context(|| {
4562
0
                format!("failed to merge package `{}` into existing copy", from.name)
4563
0
            })?;
4564
        }
4565
4566
6.55k
        Ok(())
4567
6.55k
    }
4568
4569
35
    fn build_package(&mut self, from_id: PackageId, into_id: PackageId) -> anyhow::Result<()> {
4570
35
        let prev = self.package_map.insert(from_id, into_id);
4571
35
        assert!(prev.is_none());
4572
4573
35
        let from = &self.from.packages[from_id];
4574
35
        let into = &self.into.packages[into_id];
4575
4576
        // If an interface is present in `from_id` but not present in `into_id`
4577
        // then it can be copied over wholesale. That copy is scheduled to
4578
        // happen within the `self.interfaces_to_add` list.
4579
38
        for (name, from_interface_id) in from.interfaces.iter() {
4580
38
            let into_interface_id = match into.interfaces.get(name) {
4581
35
                Some(id) => *id,
4582
                None => {
4583
3
                    log::trace!("adding unique interface {name}");
4584
3
                    self.interfaces_to_add
4585
3
                        .push((name.clone(), into_id, *from_interface_id));
4586
3
                    continue;
4587
                }
4588
            };
4589
4590
35
            log::trace!("merging duplicate interfaces {name}");
4591
35
            self.build_interface(*from_interface_id, into_interface_id)
4592
35
                .with_context(|| format!("failed to merge interface `{name}`"))?;
4593
        }
4594
4595
35
        for (name, from_world_id) in from.worlds.iter() {
4596
0
            let into_world_id = match into.worlds.get(name) {
4597
0
                Some(id) => *id,
4598
                None => {
4599
0
                    log::trace!("adding unique world {name}");
4600
0
                    self.worlds_to_add
4601
0
                        .push((name.clone(), into_id, *from_world_id));
4602
0
                    continue;
4603
                }
4604
            };
4605
4606
0
            log::trace!("merging duplicate worlds {name}");
4607
0
            self.build_world(*from_world_id, into_world_id)
4608
0
                .with_context(|| format!("failed to merge world `{name}`"))?;
4609
        }
4610
4611
35
        Ok(())
4612
35
    }
4613
4614
35
    fn build_interface(
4615
35
        &mut self,
4616
35
        from_id: InterfaceId,
4617
35
        into_id: InterfaceId,
4618
35
    ) -> anyhow::Result<()> {
4619
35
        let prev = self.interface_map.insert(from_id, into_id);
4620
35
        assert!(prev.is_none());
4621
4622
35
        let from_interface = &self.from.interfaces[from_id];
4623
35
        let into_interface = &self.into.interfaces[into_id];
4624
4625
        // When merging interfaces, types and functions that exist in both
4626
        // `from` and `into` must match structurally. Either side is allowed
4627
        // to have extra types or functions not present in the other, which
4628
        // enables commutative merging of partial views of the same
4629
        // interface. The only requirement is that the intersection of the
4630
        // two interfaces is compatible.
4631
4632
119
        for (name, from_type_id) in from_interface.types.iter() {
4633
119
            let into_type_id = match into_interface.types.get(name) {
4634
119
                Some(id) => *id,
4635
                // Extra type in `from` not present in `into`; it will be
4636
                // moved as a new type and added to the interface later.
4637
0
                None => continue,
4638
            };
4639
119
            let prev = self.type_map.insert(*from_type_id, into_type_id);
4640
119
            assert!(prev.is_none());
4641
4642
119
            self.build_type_id(*from_type_id, into_type_id)
4643
119
                .with_context(|| format!("mismatch in type `{name}`"))?;
4644
        }
4645
4646
35
        for (name, from_func) in from_interface.functions.iter() {
4647
19
            let into_func = match into_interface.functions.get(name) {
4648
19
                Some(func) => func,
4649
                // Extra function in `from` not present in `into`; it will
4650
                // be added to the interface during the merge phase.
4651
0
                None => continue,
4652
            };
4653
19
            self.build_function(from_func, into_func)
4654
19
                .with_context(|| format!("mismatch in function `{name}`"))?;
4655
        }
4656
4657
35
        Ok(())
4658
35
    }
4659
4660
148
    fn build_type_id(&mut self, from_id: TypeId, into_id: TypeId) -> anyhow::Result<()> {
4661
        // FIXME: ideally the types should be "structurally
4662
        // equal" but that's not trivial to do in the face of
4663
        // resources.
4664
148
        let _ = from_id;
4665
148
        let _ = into_id;
4666
148
        Ok(())
4667
148
    }
4668
4669
80
    fn build_type(&mut self, from_ty: &Type, into_ty: &Type) -> anyhow::Result<()> {
4670
80
        match (from_ty, into_ty) {
4671
20
            (Type::Id(from), Type::Id(into)) => {
4672
20
                self.build_type_id(*from, *into)?;
4673
            }
4674
60
            (from, into) if from != into => bail!("different kinds of types"),
4675
60
            _ => {}
4676
        }
4677
80
        Ok(())
4678
80
    }
4679
4680
19
    fn build_function(&mut self, from_func: &Function, into_func: &Function) -> anyhow::Result<()> {
4681
19
        if from_func.name != into_func.name {
4682
0
            bail!(
4683
                "different function names `{}` and `{}`",
4684
                from_func.name,
4685
                into_func.name
4686
            );
4687
19
        }
4688
19
        match (&from_func.kind, &into_func.kind) {
4689
1
            (FunctionKind::Freestanding, FunctionKind::Freestanding) => {}
4690
9
            (FunctionKind::AsyncFreestanding, FunctionKind::AsyncFreestanding) => {}
4691
0
            (FunctionKind::Getter, FunctionKind::Getter) => {}
4692
0
            (FunctionKind::Setter, FunctionKind::Setter) => {}
4693
4694
0
            (FunctionKind::Method(from), FunctionKind::Method(into))
4695
0
            | (FunctionKind::Static(from), FunctionKind::Static(into))
4696
7
            | (FunctionKind::AsyncMethod(from), FunctionKind::AsyncMethod(into))
4697
2
            | (FunctionKind::AsyncStatic(from), FunctionKind::AsyncStatic(into))
4698
0
            | (FunctionKind::MethodGetter(from), FunctionKind::MethodGetter(into))
4699
0
            | (FunctionKind::MethodSetter(from), FunctionKind::MethodSetter(into))
4700
0
            | (FunctionKind::StaticGetter(from), FunctionKind::StaticGetter(into))
4701
0
            | (FunctionKind::StaticSetter(from), FunctionKind::StaticSetter(into))
4702
0
            | (FunctionKind::Constructor(from), FunctionKind::Constructor(into)) => {
4703
9
                self.build_type_id(*from, *into)
4704
9
                    .context("different function kind types")?;
4705
            }
4706
4707
            (FunctionKind::Method(_), _)
4708
            | (FunctionKind::Constructor(_), _)
4709
            | (FunctionKind::Static(_), _)
4710
            | (FunctionKind::Freestanding, _)
4711
            | (FunctionKind::AsyncFreestanding, _)
4712
            | (FunctionKind::AsyncMethod(_), _)
4713
            | (FunctionKind::AsyncStatic(_), _)
4714
            | (FunctionKind::Getter, _)
4715
            | (FunctionKind::Setter, _)
4716
            | (FunctionKind::MethodGetter(_), _)
4717
            | (FunctionKind::MethodSetter(_), _)
4718
            | (FunctionKind::StaticGetter(_), _)
4719
            | (FunctionKind::StaticSetter(_), _) => {
4720
0
                bail!("different function kind types")
4721
            }
4722
        }
4723
4724
19
        if from_func.params.len() != into_func.params.len() {
4725
0
            bail!("different number of function parameters");
4726
19
        }
4727
61
        for (from_param, into_param) in from_func.params.iter().zip(&into_func.params) {
4728
61
            if from_param.name != into_param.name {
4729
0
                bail!(
4730
                    "different function parameter names: {} != {}",
4731
                    from_param.name,
4732
                    into_param.name
4733
                );
4734
61
            }
4735
61
            self.build_type(&from_param.ty, &into_param.ty)
4736
61
                .with_context(|| {
4737
0
                    format!(
4738
                        "different function parameter types for `{}`",
4739
                        from_param.name
4740
                    )
4741
0
                })?;
4742
        }
4743
19
        match (&from_func.result, &into_func.result) {
4744
19
            (Some(from_ty), Some(into_ty)) => {
4745
19
                self.build_type(from_ty, into_ty)
4746
19
                    .context("different function result types")?;
4747
            }
4748
0
            (None, None) => {}
4749
0
            (Some(_), None) | (None, Some(_)) => bail!("different number of function results"),
4750
        }
4751
19
        Ok(())
4752
19
    }
4753
4754
0
    fn build_world(&mut self, from_id: WorldId, into_id: WorldId) -> anyhow::Result<()> {
4755
0
        let prev = self.world_map.insert(from_id, into_id);
4756
0
        assert!(prev.is_none());
4757
4758
0
        let from_world = &self.from.worlds[from_id];
4759
0
        let into_world = &self.into.worlds[into_id];
4760
4761
        // Same as interfaces worlds are expected to exactly match to avoid
4762
        // unexpectedly changing a particular component's view of imports and
4763
        // exports.
4764
        //
4765
        // FIXME: this should probably share functionality with
4766
        // `Resolve::merge_worlds` to support adding imports but not changing
4767
        // exports.
4768
4769
0
        if from_world.imports.len() != into_world.imports.len() {
4770
0
            bail!("world contains different number of imports than expected");
4771
0
        }
4772
0
        if from_world.exports.len() != into_world.exports.len() {
4773
0
            bail!("world contains different number of exports than expected");
4774
0
        }
4775
4776
0
        for (from_name, from) in from_world.imports.iter() {
4777
0
            let into_name = MergeMap::map_name(from_name, &self.interface_map);
4778
0
            let name_str = self.from.name_world_key(from_name);
4779
0
            let into = into_world
4780
0
                .imports
4781
0
                .get(&into_name)
4782
0
                .ok_or_else(|| anyhow!("import `{name_str}` not found in target world"))?;
4783
0
            self.match_world_item(from, into)
4784
0
                .with_context(|| format!("import `{name_str}` didn't match target world"))?;
4785
        }
4786
4787
0
        for (from_name, from) in from_world.exports.iter() {
4788
0
            let into_name = MergeMap::map_name(from_name, &self.interface_map);
4789
0
            let name_str = self.from.name_world_key(from_name);
4790
0
            let into = into_world
4791
0
                .exports
4792
0
                .get(&into_name)
4793
0
                .ok_or_else(|| anyhow!("export `{name_str}` not found in target world"))?;
4794
0
            self.match_world_item(from, into)
4795
0
                .with_context(|| format!("export `{name_str}` didn't match target world"))?;
4796
        }
4797
4798
0
        Ok(())
4799
0
    }
4800
4801
0
    fn map_name(
4802
0
        from_name: &WorldKey,
4803
0
        interface_map: &HashMap<InterfaceId, InterfaceId>,
4804
0
    ) -> WorldKey {
4805
0
        match from_name {
4806
0
            WorldKey::Name(s) => WorldKey::Name(s.clone()),
4807
0
            WorldKey::Interface(id) => {
4808
0
                WorldKey::Interface(interface_map.get(id).copied().unwrap_or(*id))
4809
            }
4810
        }
4811
0
    }
4812
4813
0
    fn match_world_item(&mut self, from: &WorldItem, into: &WorldItem) -> anyhow::Result<()> {
4814
0
        match (from, into) {
4815
0
            (WorldItem::Interface { id: from, .. }, WorldItem::Interface { id: into, .. }) => {
4816
                match (
4817
0
                    &self.from.interfaces[*from].name,
4818
0
                    &self.into.interfaces[*into].name,
4819
                ) {
4820
                    // If one interface is unnamed then they must both be
4821
                    // unnamed and they must both have the same structure for
4822
                    // now.
4823
0
                    (None, None) => self.build_interface(*from, *into)?,
4824
4825
                    // Otherwise both interfaces must be named and they must
4826
                    // have been previously found to be equivalent. Note that
4827
                    // if either is unnamed it won't be present in
4828
                    // `interface_map` so this'll return an error.
4829
                    _ => {
4830
0
                        if self.interface_map.get(from) != Some(into) {
4831
0
                            bail!("interfaces are not the same");
4832
0
                        }
4833
                    }
4834
                }
4835
            }
4836
0
            (WorldItem::Function(from), WorldItem::Function(into)) => {
4837
0
                let _ = (from, into);
4838
0
                // FIXME: should assert an check that `from` structurally
4839
0
                // matches `into`
4840
0
            }
4841
0
            (WorldItem::Type { id: from, .. }, WorldItem::Type { id: into, .. }) => {
4842
                // FIXME: should assert an check that `from` structurally
4843
                // matches `into`
4844
0
                let prev = self.type_map.insert(*from, *into);
4845
0
                assert!(prev.is_none());
4846
            }
4847
4848
            (WorldItem::Interface { .. }, _)
4849
            | (WorldItem::Function(_), _)
4850
            | (WorldItem::Type { .. }, _) => {
4851
0
                bail!("world items do not have the same type")
4852
            }
4853
        }
4854
0
        Ok(())
4855
0
    }
4856
}
4857
4858
/// Updates stability annotations when merging `from` into `into`.
4859
///
4860
/// This is done to keep up-to-date stability information if possible.
4861
/// Components for example don't carry stability information but WIT does so
4862
/// this tries to move from "unknown" to stable/unstable if possible.
4863
154
fn update_stability(from: &Stability, into: &mut Stability, span: Span) -> ResolveResult<()> {
4864
    // If `from` is unknown or the two stability annotations are equal then
4865
    // there's nothing to do here.
4866
154
    if from == into || from.is_unknown() {
4867
154
        return Ok(());
4868
0
    }
4869
    // Otherwise if `into` is unknown then inherit the stability listed in
4870
    // `from`.
4871
0
    if into.is_unknown() {
4872
0
        *into = from.clone();
4873
0
        return Ok(());
4874
0
    }
4875
4876
    // Failing all that this means that the two attributes are different so
4877
    // generate an error.
4878
0
    Err(ResolveError::from(ResolveErrorKind::StabilityMismatch {
4879
0
        span,
4880
0
        from: from.clone(),
4881
0
        into: into.clone(),
4882
0
    }))
4883
154
}
4884
4885
0
fn merge_include_stability(
4886
0
    from: &Stability,
4887
0
    into: &mut Stability,
4888
0
    is_external_include: bool,
4889
0
    span: Span,
4890
0
) -> ResolveResult<()> {
4891
0
    if is_external_include && from.is_stable() {
4892
0
        log::trace!("dropped stability from external package");
4893
0
        *into = Stability::Unknown;
4894
0
        return Ok(());
4895
0
    }
4896
4897
0
    update_stability(from, into, span)
4898
0
}
4899
4900
#[cfg(test)]
4901
mod tests {
4902
    use crate::alloc::format;
4903
    use crate::alloc::string::{String, ToString};
4904
    use crate::alloc::vec::Vec;
4905
    use crate::{Resolve, SourceMap, WorldItem, WorldKey};
4906
    use anyhow::Result;
4907
4908
    #[test]
4909
    fn select_world() -> Result<()> {
4910
        let mut resolve = Resolve::default();
4911
        resolve.push_str(
4912
            "test.wit",
4913
            r#"
4914
                package foo:bar@0.1.0;
4915
4916
                world foo {}
4917
            "#,
4918
        )?;
4919
        resolve.push_str(
4920
            "test.wit",
4921
            r#"
4922
                package foo:baz@0.1.0;
4923
4924
                world foo {}
4925
            "#,
4926
        )?;
4927
        resolve.push_str(
4928
            "test.wit",
4929
            r#"
4930
                package foo:baz@0.2.0;
4931
4932
                world foo {}
4933
            "#,
4934
        )?;
4935
4936
        let dummy = resolve.push_str(
4937
            "test.wit",
4938
            r#"
4939
                package foo:dummy;
4940
4941
                world foo {}
4942
            "#,
4943
        )?;
4944
4945
        assert!(resolve.select_world(&[dummy], None).is_ok());
4946
        assert!(resolve.select_world(&[dummy], Some("xx")).is_err());
4947
        assert!(resolve.select_world(&[dummy], Some("")).is_err());
4948
        assert!(resolve.select_world(&[dummy], Some("foo:bar/foo")).is_ok());
4949
        assert!(
4950
            resolve
4951
                .select_world(&[dummy], Some("foo:bar/foo@0.1.0"))
4952
                .is_ok()
4953
        );
4954
        assert!(resolve.select_world(&[dummy], Some("foo:baz/foo")).is_err());
4955
        assert!(
4956
            resolve
4957
                .select_world(&[dummy], Some("foo:baz/foo@0.1.0"))
4958
                .is_ok()
4959
        );
4960
        assert!(
4961
            resolve
4962
                .select_world(&[dummy], Some("foo:baz/foo@0.2.0"))
4963
                .is_ok()
4964
        );
4965
        Ok(())
4966
    }
4967
4968
    #[test]
4969
    fn wasm_import_name_future_and_stream_intrinsics() -> Result<()> {
4970
        use crate::{FutureIntrinsic, LiftLowerAbi, ManglingAndAbi, StreamIntrinsic, WasmImport};
4971
4972
        let mut resolve = Resolve::default();
4973
        let pkg = resolve.push_str(
4974
            "test.wit",
4975
            r#"
4976
                package foo:bar;
4977
4978
                interface iface {
4979
                    iface-func: func(x: future<u32>) -> stream<u32>;
4980
                }
4981
4982
                world w {
4983
                    import import-func: func(x: future<future<u32>>, y: u32) -> stream<string>;
4984
                    export export-func: func(x: future, y: stream);
4985
                    import iface;
4986
                    export iface;
4987
                }
4988
            "#,
4989
        )?;
4990
        let world = resolve.packages[pkg].worlds["w"];
4991
        let world = &resolve.worlds[world];
4992
        let mangling = ManglingAndAbi::Legacy(LiftLowerAbi::AsyncStackful);
4993
4994
        let WorldItem::Function(import_func) =
4995
            &world.imports[&WorldKey::Name("import-func".to_string())]
4996
        else {
4997
            panic!("expected `import-func` to be a top-level world import");
4998
        };
4999
        let WorldItem::Function(export_func) =
5000
            &world.exports[&WorldKey::Name("export-func".to_string())]
5001
        else {
5002
            panic!("expected `export-func` to be a top-level world export");
5003
        };
5004
        let import_types = import_func.find_futures_and_streams(&resolve);
5005
        assert_eq!(import_types.len(), 3);
5006
5007
        let (interface_key, interface_func) = world
5008
            .imports
5009
            .iter()
5010
            .find_map(|(key, item)| match item {
5011
                WorldItem::Interface { id, .. } => Some((
5012
                    key.clone(),
5013
                    &resolve.interfaces[*id].functions["iface-func"],
5014
                )),
5015
                _ => None,
5016
            })
5017
            .expect("expected interface import");
5018
        let interface_types = interface_func.find_futures_and_streams(&resolve);
5019
        assert_eq!(interface_types.len(), 2);
5020
5021
        let (module, name) = resolve.wasm_import_name(
5022
            mangling,
5023
            WasmImport::FutureIntrinsic {
5024
                interface: None,
5025
                func: import_func,
5026
                ty: Some(import_types[0]),
5027
                intrinsic: FutureIntrinsic::New,
5028
                exported: false,
5029
                async_: false,
5030
            },
5031
        );
5032
        assert_eq!(module, "$root");
5033
        assert_eq!(name, "[future-new-0]import-func");
5034
5035
        let (module, name) = resolve.wasm_import_name(
5036
            mangling,
5037
            WasmImport::FutureIntrinsic {
5038
                interface: None,
5039
                func: import_func,
5040
                ty: Some(import_types[1]),
5041
                intrinsic: FutureIntrinsic::Read,
5042
                exported: false,
5043
                async_: true,
5044
            },
5045
        );
5046
        assert_eq!(module, "$root");
5047
        assert_eq!(name, "[async-lower][future-read-1]import-func");
5048
5049
        let (module, name) = resolve.wasm_import_name(
5050
            mangling,
5051
            WasmImport::FutureIntrinsic {
5052
                interface: None,
5053
                func: import_func,
5054
                ty: Some(import_types[1]),
5055
                intrinsic: FutureIntrinsic::Forward,
5056
                exported: false,
5057
                async_: false,
5058
            },
5059
        );
5060
        assert_eq!(module, "$root");
5061
        assert_eq!(name, "[future-forward-1]import-func");
5062
5063
        let (module, name) = resolve.wasm_import_name(
5064
            mangling,
5065
            WasmImport::StreamIntrinsic {
5066
                interface: None,
5067
                func: import_func,
5068
                ty: Some(import_types[2]),
5069
                intrinsic: StreamIntrinsic::Forward,
5070
                exported: false,
5071
                async_: false,
5072
            },
5073
        );
5074
        assert_eq!(module, "$root");
5075
        assert_eq!(name, "[stream-forward-2]import-func");
5076
5077
        let (module, name) = resolve.wasm_import_name(
5078
            mangling,
5079
            WasmImport::StreamIntrinsic {
5080
                interface: None,
5081
                func: import_func,
5082
                ty: Some(import_types[2]),
5083
                intrinsic: StreamIntrinsic::CancelRead,
5084
                exported: false,
5085
                async_: true,
5086
            },
5087
        );
5088
        assert_eq!(module, "$root");
5089
        assert_eq!(name, "[async-lower][stream-cancel-read-2]import-func");
5090
5091
        let (module, name) = resolve.wasm_import_name(
5092
            mangling,
5093
            WasmImport::FutureIntrinsic {
5094
                interface: None,
5095
                func: export_func,
5096
                ty: None,
5097
                intrinsic: FutureIntrinsic::DropReadable,
5098
                exported: true,
5099
                async_: false,
5100
            },
5101
        );
5102
        assert_eq!(module, "[export]$root");
5103
        assert_eq!(name, "[future-drop-readable-unit]export-func");
5104
5105
        let (module, name) = resolve.wasm_import_name(
5106
            mangling,
5107
            WasmImport::StreamIntrinsic {
5108
                interface: None,
5109
                func: export_func,
5110
                ty: None,
5111
                intrinsic: StreamIntrinsic::Write,
5112
                exported: true,
5113
                async_: true,
5114
            },
5115
        );
5116
        assert_eq!(module, "[export]$root");
5117
        assert_eq!(name, "[async-lower][stream-write-unit]export-func");
5118
5119
        let (module, name) = resolve.wasm_import_name(
5120
            mangling,
5121
            WasmImport::StreamIntrinsic {
5122
                interface: Some(&interface_key),
5123
                func: interface_func,
5124
                ty: Some(interface_types[1]),
5125
                intrinsic: StreamIntrinsic::Read,
5126
                exported: true,
5127
                async_: false,
5128
            },
5129
        );
5130
        assert_eq!(
5131
            module,
5132
            format!("[export]{}", resolve.name_world_key(&interface_key))
5133
        );
5134
        assert_eq!(name, "[stream-read-1]iface-func");
5135
5136
        Ok(())
5137
    }
5138
5139
    /// When there are multiple packages and there's no main package, don't
5140
    /// pick a world just based on it being the only one that matches.
5141
    #[test]
5142
    fn select_world_multiple_packages() -> Result<()> {
5143
        use wit_parser::Resolve;
5144
5145
        let mut resolve = Resolve::default();
5146
5147
        // Just one world in one package; we always succeed.
5148
        let stuff = resolve.push_str(
5149
            "./my-test.wit",
5150
            r#"
5151
                    package test:stuff;
5152
5153
                    world foo {
5154
                        // ...
5155
                    }
5156
                "#,
5157
        )?;
5158
        assert!(resolve.select_world(&[stuff], None).is_ok());
5159
        assert!(resolve.select_world(&[stuff], Some("foo")).is_ok());
5160
5161
        // Multiple packages, but still just one total world. Lookups
5162
        // without a main package now fail.
5163
        let empty = resolve.push_str(
5164
            "./my-test.wit",
5165
            r#"
5166
                    package test:empty;
5167
                "#,
5168
        )?;
5169
        assert!(resolve.select_world(&[stuff, empty], None).is_err());
5170
        assert!(resolve.select_world(&[stuff, empty], Some("foo")).is_err());
5171
        assert!(resolve.select_world(&[empty], None).is_err());
5172
        assert!(resolve.select_world(&[empty], Some("foo")).is_err());
5173
5174
        Ok(())
5175
    }
5176
5177
    /// Test selecting a world with multiple versions of a package name.
5178
    #[test]
5179
    fn select_world_versions() -> Result<()> {
5180
        use wit_parser::Resolve;
5181
5182
        let mut resolve = Resolve::default();
5183
5184
        let _id = resolve.push_str(
5185
            "./my-test.wit",
5186
            r#"
5187
                    package example:distraction;
5188
                "#,
5189
        )?;
5190
5191
        // When selecting with a version it's ok to drop the version when
5192
        // there's only a single copy of that package in `Resolve`.
5193
        let versions_1 = resolve.push_str(
5194
            "./my-test.wit",
5195
            r#"
5196
                    package example:versions@1.0.0;
5197
5198
                    world foo { /* ... */ }
5199
                "#,
5200
        )?;
5201
        assert!(resolve.select_world(&[versions_1], Some("foo")).is_ok());
5202
        assert!(
5203
            resolve
5204
                .select_world(&[versions_1], Some("foo@1.0.0"))
5205
                .is_err()
5206
        );
5207
        assert!(
5208
            resolve
5209
                .select_world(&[versions_1], Some("example:versions/foo"))
5210
                .is_ok()
5211
        );
5212
        assert!(
5213
            resolve
5214
                .select_world(&[versions_1], Some("example:versions/foo@1.0.0"))
5215
                .is_ok()
5216
        );
5217
5218
        // However when a single package has multiple versions in a resolve
5219
        // it's required to specify the version to select which one.
5220
        let versions_2 = resolve.push_str(
5221
            "./my-test.wit",
5222
            r#"
5223
                    package example:versions@2.0.0;
5224
5225
                    world foo { /* ... */ }
5226
                "#,
5227
        )?;
5228
        assert!(
5229
            resolve
5230
                .select_world(&[versions_1, versions_2], Some("foo"))
5231
                .is_err()
5232
        );
5233
        assert!(
5234
            resolve
5235
                .select_world(&[versions_1, versions_2], Some("foo@1.0.0"))
5236
                .is_err()
5237
        );
5238
        assert!(
5239
            resolve
5240
                .select_world(&[versions_1, versions_2], Some("foo@2.0.0"))
5241
                .is_err()
5242
        );
5243
        assert!(
5244
            resolve
5245
                .select_world(&[versions_1, versions_2], Some("example:versions/foo"))
5246
                .is_err()
5247
        );
5248
        assert!(
5249
            resolve
5250
                .select_world(
5251
                    &[versions_1, versions_2],
5252
                    Some("example:versions/foo@1.0.0")
5253
                )
5254
                .is_ok()
5255
        );
5256
        assert!(
5257
            resolve
5258
                .select_world(
5259
                    &[versions_1, versions_2],
5260
                    Some("example:versions/foo@2.0.0")
5261
                )
5262
                .is_ok()
5263
        );
5264
5265
        Ok(())
5266
    }
5267
5268
    /// Test overriding a main package using name qualification
5269
    #[test]
5270
    fn select_world_override_qualification() -> Result<()> {
5271
        use wit_parser::Resolve;
5272
5273
        let mut resolve = Resolve::default();
5274
5275
        let other = resolve.push_str(
5276
            "./my-test.wit",
5277
            r#"
5278
                    package example:other;
5279
5280
                    world foo { }
5281
                "#,
5282
        )?;
5283
5284
        // A fully-qualified name overrides a main package.
5285
        let fq = resolve.push_str(
5286
            "./my-test.wit",
5287
            r#"
5288
                    package example:fq;
5289
5290
                    world bar { }
5291
                "#,
5292
        )?;
5293
        assert!(resolve.select_world(&[other, fq], Some("foo")).is_err());
5294
        assert!(resolve.select_world(&[other, fq], Some("bar")).is_err());
5295
        assert!(
5296
            resolve
5297
                .select_world(&[other, fq], Some("example:other/foo"))
5298
                .is_ok()
5299
        );
5300
        assert!(
5301
            resolve
5302
                .select_world(&[other, fq], Some("example:fq/bar"))
5303
                .is_ok()
5304
        );
5305
        assert!(
5306
            resolve
5307
                .select_world(&[other, fq], Some("example:other/bar"))
5308
                .is_err()
5309
        );
5310
        assert!(
5311
            resolve
5312
                .select_world(&[other, fq], Some("example:fq/foo"))
5313
                .is_err()
5314
        );
5315
5316
        Ok(())
5317
    }
5318
5319
    /// Test selecting with fully-qualified world names.
5320
    #[test]
5321
    fn select_world_fully_qualified() -> Result<()> {
5322
        use wit_parser::Resolve;
5323
5324
        let mut resolve = Resolve::default();
5325
5326
        let distraction = resolve.push_str(
5327
            "./my-test.wit",
5328
            r#"
5329
                    package example:distraction;
5330
                "#,
5331
        )?;
5332
5333
        // If a package has multiple worlds, then we can't guess the world
5334
        // even if we know the package.
5335
        let multiworld = resolve.push_str(
5336
            "./my-test.wit",
5337
            r#"
5338
                    package example:multiworld;
5339
5340
                    world foo { /* ... */ }
5341
5342
                    world bar { /* ... */ }
5343
                "#,
5344
        )?;
5345
        assert!(
5346
            resolve
5347
                .select_world(&[distraction, multiworld], None)
5348
                .is_err()
5349
        );
5350
        assert!(
5351
            resolve
5352
                .select_world(&[distraction, multiworld], Some("foo"))
5353
                .is_err()
5354
        );
5355
        assert!(
5356
            resolve
5357
                .select_world(&[distraction, multiworld], Some("example:multiworld/foo"))
5358
                .is_ok()
5359
        );
5360
        assert!(
5361
            resolve
5362
                .select_world(&[distraction, multiworld], Some("bar"))
5363
                .is_err()
5364
        );
5365
        assert!(
5366
            resolve
5367
                .select_world(&[distraction, multiworld], Some("example:multiworld/bar"))
5368
                .is_ok()
5369
        );
5370
5371
        Ok(())
5372
    }
5373
5374
    /// Test `select_world` with single and multiple packages.
5375
    #[test]
5376
    fn select_world_packages() -> Result<()> {
5377
        use wit_parser::Resolve;
5378
5379
        let mut resolve = Resolve::default();
5380
5381
        // If there's a single package and only one world, that world is
5382
        // the obvious choice.
5383
        let wit1 = resolve.push_str(
5384
            "./my-test.wit",
5385
            r#"
5386
                    package example:wit1;
5387
5388
                    world foo {
5389
                        // ...
5390
                    }
5391
                "#,
5392
        )?;
5393
        assert!(resolve.select_world(&[wit1], None).is_ok());
5394
        assert!(resolve.select_world(&[wit1], Some("foo")).is_ok());
5395
        assert!(
5396
            resolve
5397
                .select_world(&[wit1], Some("example:wit1/foo"))
5398
                .is_ok()
5399
        );
5400
        assert!(resolve.select_world(&[wit1], Some("bar")).is_err());
5401
        assert!(
5402
            resolve
5403
                .select_world(&[wit1], Some("example:wit2/foo"))
5404
                .is_err()
5405
        );
5406
5407
        // If there are multiple packages, we need to be told which package
5408
        // to use.
5409
        let wit2 = resolve.push_str(
5410
            "./my-test.wit",
5411
            r#"
5412
                    package example:wit2;
5413
5414
                    world foo { /* ... */ }
5415
                "#,
5416
        )?;
5417
        assert!(resolve.select_world(&[wit1, wit2], None).is_err());
5418
        assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
5419
        assert!(
5420
            resolve
5421
                .select_world(&[wit1, wit2], Some("example:wit1/foo"))
5422
                .is_ok()
5423
        );
5424
        assert!(resolve.select_world(&[wit2], None).is_ok());
5425
        assert!(resolve.select_world(&[wit2], Some("foo")).is_ok());
5426
        assert!(
5427
            resolve
5428
                .select_world(&[wit2], Some("example:wit1/foo"))
5429
                .is_ok()
5430
        );
5431
        assert!(resolve.select_world(&[wit1, wit2], Some("bar")).is_err());
5432
        assert!(
5433
            resolve
5434
                .select_world(&[wit1, wit2], Some("example:wit2/foo"))
5435
                .is_ok()
5436
        );
5437
        assert!(resolve.select_world(&[wit2], Some("bar")).is_err());
5438
        assert!(
5439
            resolve
5440
                .select_world(&[wit2], Some("example:wit2/foo"))
5441
                .is_ok()
5442
        );
5443
5444
        Ok(())
5445
    }
5446
5447
    #[test]
5448
    fn span_preservation() -> Result<()> {
5449
        let mut resolve = Resolve::default();
5450
        let pkg = resolve.push_str(
5451
            "test.wit",
5452
            r#"
5453
                package foo:bar;
5454
5455
                interface my-iface {
5456
                    type my-type = u32;
5457
                    my-func: func();
5458
                }
5459
5460
                world my-world {
5461
                    export my-export: func();
5462
                }
5463
            "#,
5464
        )?;
5465
5466
        let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5467
        assert!(resolve.interfaces[iface_id].span.is_known());
5468
5469
        let type_id = resolve.interfaces[iface_id].types["my-type"];
5470
        assert!(resolve.types[type_id].span.is_known());
5471
5472
        assert!(
5473
            resolve.interfaces[iface_id].functions["my-func"]
5474
                .span
5475
                .is_known()
5476
        );
5477
5478
        let world_id = resolve.packages[pkg].worlds["my-world"];
5479
        assert!(resolve.worlds[world_id].span.is_known());
5480
5481
        let WorldItem::Function(f) =
5482
            &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5483
        else {
5484
            panic!("expected function");
5485
        };
5486
        assert!(f.span.is_known());
5487
5488
        Ok(())
5489
    }
5490
5491
    #[test]
5492
    fn span_preservation_through_merge() -> Result<()> {
5493
        let mut resolve1 = Resolve::default();
5494
        resolve1.push_str(
5495
            "test1.wit",
5496
            r#"
5497
                package foo:bar;
5498
5499
                interface iface1 {
5500
                    type type1 = u32;
5501
                    func1: func();
5502
                }
5503
            "#,
5504
        )?;
5505
5506
        let mut resolve2 = Resolve::default();
5507
        let pkg2 = resolve2.push_str(
5508
            "test2.wit",
5509
            r#"
5510
                package foo:baz;
5511
5512
                interface iface2 {
5513
                    type type2 = string;
5514
                    func2: func();
5515
                }
5516
            "#,
5517
        )?;
5518
5519
        let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5520
        let remap = resolve1.merge(resolve2)?;
5521
        let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5522
5523
        assert!(resolve1.interfaces[iface2_id].span.is_known());
5524
5525
        let type2_id = resolve1.interfaces[iface2_id].types["type2"];
5526
        assert!(resolve1.types[type2_id].span.is_known());
5527
5528
        assert!(
5529
            resolve1.interfaces[iface2_id].functions["func2"]
5530
                .span
5531
                .is_known()
5532
        );
5533
5534
        Ok(())
5535
    }
5536
5537
    #[test]
5538
    fn span_preservation_through_include() -> Result<()> {
5539
        let mut resolve = Resolve::default();
5540
        let pkg = resolve.push_str(
5541
            "test.wit",
5542
            r#"
5543
                package foo:bar;
5544
5545
                world base {
5546
                    export my-func: func();
5547
                }
5548
5549
                world extended {
5550
                    include base;
5551
                }
5552
            "#,
5553
        )?;
5554
5555
        let base_id = resolve.packages[pkg].worlds["base"];
5556
        let extended_id = resolve.packages[pkg].worlds["extended"];
5557
5558
        let WorldItem::Function(base_func) =
5559
            &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5560
        else {
5561
            panic!("expected function");
5562
        };
5563
        assert!(base_func.span.is_known());
5564
5565
        let WorldItem::Function(extended_func) =
5566
            &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5567
        else {
5568
            panic!("expected function");
5569
        };
5570
        assert!(extended_func.span.is_known());
5571
5572
        Ok(())
5573
    }
5574
5575
    #[test]
5576
    fn span_preservation_through_include_with_rename() -> Result<()> {
5577
        let mut resolve = Resolve::default();
5578
        let pkg = resolve.push_str(
5579
            "test.wit",
5580
            r#"
5581
                package foo:bar;
5582
5583
                world base {
5584
                    export original-name: func();
5585
                }
5586
5587
                world extended {
5588
                    include base with { original-name as renamed-func }
5589
                }
5590
            "#,
5591
        )?;
5592
5593
        let extended_id = resolve.packages[pkg].worlds["extended"];
5594
5595
        let WorldItem::Function(f) =
5596
            &resolve.worlds[extended_id].exports[&WorldKey::Name("renamed-func".to_string())]
5597
        else {
5598
            panic!("expected function");
5599
        };
5600
        assert!(f.span.is_known());
5601
5602
        assert!(
5603
            !resolve.worlds[extended_id]
5604
                .exports
5605
                .contains_key(&WorldKey::Name("original-name".to_string()))
5606
        );
5607
5608
        Ok(())
5609
    }
5610
5611
    /// Test that spans work when included world is defined after the including world
5612
    #[test]
5613
    fn span_preservation_through_include_reverse_order() -> Result<()> {
5614
        let mut resolve = Resolve::default();
5615
        let pkg = resolve.push_str(
5616
            "test.wit",
5617
            r#"
5618
                package foo:bar;
5619
5620
                world extended {
5621
                    include base;
5622
                }
5623
5624
                world base {
5625
                    export my-func: func();
5626
                }
5627
            "#,
5628
        )?;
5629
5630
        let base_id = resolve.packages[pkg].worlds["base"];
5631
        let extended_id = resolve.packages[pkg].worlds["extended"];
5632
5633
        let WorldItem::Function(base_func) =
5634
            &resolve.worlds[base_id].exports[&WorldKey::Name("my-func".to_string())]
5635
        else {
5636
            panic!("expected function");
5637
        };
5638
        assert!(base_func.span.is_known());
5639
5640
        let WorldItem::Function(extended_func) =
5641
            &resolve.worlds[extended_id].exports[&WorldKey::Name("my-func".to_string())]
5642
        else {
5643
            panic!("expected function");
5644
        };
5645
        assert!(extended_func.span.is_known());
5646
5647
        Ok(())
5648
    }
5649
5650
    #[test]
5651
    fn span_line_numbers() -> Result<()> {
5652
        let mut resolve = Resolve::default();
5653
        let pkg = resolve.push_source(
5654
            "test.wit",
5655
            "package foo:bar;
5656
5657
interface my-iface {
5658
    type my-type = u32;
5659
    my-func: func();
5660
}
5661
5662
world my-world {
5663
    export my-export: func();
5664
}
5665
",
5666
        )?;
5667
5668
        let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5669
        let iface_span = resolve.interfaces[iface_id].span;
5670
        let iface_loc = resolve.render_location(iface_span);
5671
        assert!(
5672
            iface_loc.contains(":3:"),
5673
            "interface location was {iface_loc}"
5674
        );
5675
5676
        let type_id = resolve.interfaces[iface_id].types["my-type"];
5677
        let type_span = resolve.types[type_id].span;
5678
        let type_loc = resolve.render_location(type_span);
5679
        assert!(type_loc.contains(":4:"), "type location was {type_loc}");
5680
5681
        let func_span = resolve.interfaces[iface_id].functions["my-func"].span;
5682
        let func_loc = resolve.render_location(func_span);
5683
        assert!(func_loc.contains(":5:"), "function location was {func_loc}");
5684
5685
        let world_id = resolve.packages[pkg].worlds["my-world"];
5686
        let world_span = resolve.worlds[world_id].span;
5687
        let world_loc = resolve.render_location(world_span);
5688
        assert!(world_loc.contains(":8:"), "world location was {world_loc}");
5689
5690
        let WorldItem::Function(export_func) =
5691
            &resolve.worlds[world_id].exports[&WorldKey::Name("my-export".to_string())]
5692
        else {
5693
            panic!("expected function");
5694
        };
5695
        let export_loc = resolve.render_location(export_func.span);
5696
        assert!(
5697
            export_loc.contains(":9:"),
5698
            "export location was {export_loc}"
5699
        );
5700
5701
        Ok(())
5702
    }
5703
5704
    #[test]
5705
    fn span_line_numbers_through_merge() -> Result<()> {
5706
        let mut resolve1 = Resolve::default();
5707
        resolve1.push_source(
5708
            "first.wit",
5709
            "package foo:first;
5710
5711
interface iface1 {
5712
    func1: func();
5713
}
5714
",
5715
        )?;
5716
5717
        let mut resolve2 = Resolve::default();
5718
        let pkg2 = resolve2.push_source(
5719
            "second.wit",
5720
            "package foo:second;
5721
5722
interface iface2 {
5723
    func2: func();
5724
}
5725
",
5726
        )?;
5727
5728
        let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5729
        let remap = resolve1.merge(resolve2)?;
5730
        let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
5731
5732
        let iface2_span = resolve1.interfaces[iface2_id].span;
5733
        let iface2_loc = resolve1.render_location(iface2_span);
5734
        assert!(
5735
            iface2_loc.contains("second.wit"),
5736
            "should reference second.wit, got {iface2_loc}"
5737
        );
5738
        assert!(
5739
            iface2_loc.contains(":3:"),
5740
            "interface should be on line 3, got {iface2_loc}"
5741
        );
5742
5743
        let func2_span = resolve1.interfaces[iface2_id].functions["func2"].span;
5744
        let func2_loc = resolve1.render_location(func2_span);
5745
        assert!(
5746
            func2_loc.contains("second.wit"),
5747
            "should reference second.wit, got {func2_loc}"
5748
        );
5749
        assert!(
5750
            func2_loc.contains(":4:"),
5751
            "function should be on line 4, got {func2_loc}"
5752
        );
5753
5754
        Ok(())
5755
    }
5756
5757
    #[test]
5758
    fn span_line_numbers_multiple_sources() -> Result<()> {
5759
        let mut resolve = Resolve::default();
5760
5761
        let pkg1 = resolve.push_source(
5762
            "first.wit",
5763
            "package test:first;
5764
5765
interface first-iface {
5766
    first-func: func();
5767
}
5768
",
5769
        )?;
5770
5771
        let pkg2 = resolve.push_source(
5772
            "second.wit",
5773
            "package test:second;
5774
5775
interface second-iface {
5776
    second-func: func();
5777
}
5778
",
5779
        )?;
5780
5781
        let iface1_id = resolve.packages[pkg1].interfaces["first-iface"];
5782
        let iface1_span = resolve.interfaces[iface1_id].span;
5783
        let iface1_loc = resolve.render_location(iface1_span);
5784
        assert!(
5785
            iface1_loc.contains("first.wit"),
5786
            "should reference first.wit, got {iface1_loc}"
5787
        );
5788
        assert!(
5789
            iface1_loc.contains(":3:"),
5790
            "interface should be on line 3, got {iface1_loc}"
5791
        );
5792
5793
        let func1_span = resolve.interfaces[iface1_id].functions["first-func"].span;
5794
        let func1_loc = resolve.render_location(func1_span);
5795
        assert!(
5796
            func1_loc.contains("first.wit"),
5797
            "should reference first.wit, got {func1_loc}"
5798
        );
5799
        assert!(
5800
            func1_loc.contains(":4:"),
5801
            "function should be on line 4, got {func1_loc}"
5802
        );
5803
5804
        let iface2_id = resolve.packages[pkg2].interfaces["second-iface"];
5805
        let iface2_span = resolve.interfaces[iface2_id].span;
5806
        let iface2_loc = resolve.render_location(iface2_span);
5807
        assert!(
5808
            iface2_loc.contains("second.wit"),
5809
            "should reference second.wit, got {iface2_loc}"
5810
        );
5811
        assert!(
5812
            iface2_loc.contains(":3:"),
5813
            "interface should be on line 3, got {iface2_loc}"
5814
        );
5815
5816
        let func2_span = resolve.interfaces[iface2_id].functions["second-func"].span;
5817
        let func2_loc = resolve.render_location(func2_span);
5818
        assert!(
5819
            func2_loc.contains("second.wit"),
5820
            "should reference second.wit, got {func2_loc}"
5821
        );
5822
        assert!(
5823
            func2_loc.contains(":4:"),
5824
            "function should be on line 4, got {func2_loc}"
5825
        );
5826
5827
        Ok(())
5828
    }
5829
5830
    #[test]
5831
    fn span_preservation_for_fields_and_cases() -> Result<()> {
5832
        use crate::TypeDefKind;
5833
5834
        let mut resolve = Resolve::default();
5835
        let pkg = resolve.push_str(
5836
            "test.wit",
5837
            r#"
5838
                package foo:bar;
5839
5840
                interface my-iface {
5841
                    record my-record {
5842
                        field1: u32,
5843
                        field2: string,
5844
                    }
5845
5846
                    flags my-flags {
5847
                        flag1,
5848
                        flag2,
5849
                    }
5850
5851
                    variant my-variant {
5852
                        case1,
5853
                        case2(u32),
5854
                    }
5855
5856
                    enum my-enum {
5857
                        val1,
5858
                        val2,
5859
                    }
5860
                }
5861
            "#,
5862
        )?;
5863
5864
        let iface_id = resolve.packages[pkg].interfaces["my-iface"];
5865
5866
        // Check record fields have spans
5867
        let record_id = resolve.interfaces[iface_id].types["my-record"];
5868
        let TypeDefKind::Record(record) = &resolve.types[record_id].kind else {
5869
            panic!("expected record");
5870
        };
5871
        assert!(record.fields[0].span.is_known(), "field1 should have span");
5872
        assert!(record.fields[1].span.is_known(), "field2 should have span");
5873
5874
        // Check flags have spans
5875
        let flags_id = resolve.interfaces[iface_id].types["my-flags"];
5876
        let TypeDefKind::Flags(flags) = &resolve.types[flags_id].kind else {
5877
            panic!("expected flags");
5878
        };
5879
        assert!(flags.flags[0].span.is_known(), "flag1 should have span");
5880
        assert!(flags.flags[1].span.is_known(), "flag2 should have span");
5881
5882
        // Check variant cases have spans
5883
        let variant_id = resolve.interfaces[iface_id].types["my-variant"];
5884
        let TypeDefKind::Variant(variant) = &resolve.types[variant_id].kind else {
5885
            panic!("expected variant");
5886
        };
5887
        assert!(variant.cases[0].span.is_known(), "case1 should have span");
5888
        assert!(variant.cases[1].span.is_known(), "case2 should have span");
5889
5890
        // Check enum cases have spans
5891
        let enum_id = resolve.interfaces[iface_id].types["my-enum"];
5892
        let TypeDefKind::Enum(e) = &resolve.types[enum_id].kind else {
5893
            panic!("expected enum");
5894
        };
5895
        assert!(e.cases[0].span.is_known(), "val1 should have span");
5896
        assert!(e.cases[1].span.is_known(), "val2 should have span");
5897
5898
        Ok(())
5899
    }
5900
5901
    #[test]
5902
    fn span_preservation_for_fields_through_merge() -> Result<()> {
5903
        use crate::TypeDefKind;
5904
5905
        let mut resolve1 = Resolve::default();
5906
        resolve1.push_str(
5907
            "test1.wit",
5908
            r#"
5909
                package foo:bar;
5910
5911
                interface iface1 {
5912
                    record rec1 {
5913
                        f1: u32,
5914
                    }
5915
                }
5916
            "#,
5917
        )?;
5918
5919
        let mut resolve2 = Resolve::default();
5920
        let pkg2 = resolve2.push_str(
5921
            "test2.wit",
5922
            r#"
5923
                package foo:baz;
5924
5925
                interface iface2 {
5926
                    record rec2 {
5927
                        f2: string,
5928
                    }
5929
5930
                    variant var2 {
5931
                        c2,
5932
                    }
5933
                }
5934
            "#,
5935
        )?;
5936
5937
        let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
5938
        let rec2_old_id = resolve2.interfaces[iface2_old_id].types["rec2"];
5939
        let var2_old_id = resolve2.interfaces[iface2_old_id].types["var2"];
5940
5941
        let remap = resolve1.merge(resolve2)?;
5942
5943
        let rec2_id = remap.types[rec2_old_id.index()].unwrap();
5944
        let TypeDefKind::Record(record) = &resolve1.types[rec2_id].kind else {
5945
            panic!("expected record");
5946
        };
5947
        assert!(
5948
            record.fields[0].span.is_known(),
5949
            "field should have span after merge"
5950
        );
5951
5952
        let var2_id = remap.types[var2_old_id.index()].unwrap();
5953
        let TypeDefKind::Variant(variant) = &resolve1.types[var2_id].kind else {
5954
            panic!("expected variant");
5955
        };
5956
        assert!(
5957
            variant.cases[0].span.is_known(),
5958
            "case should have span after merge"
5959
        );
5960
5961
        Ok(())
5962
    }
5963
5964
    #[test]
5965
    fn param_spans_point_to_names() -> Result<()> {
5966
        let source = "\
5967
package foo:bar;
5968
5969
interface iface {
5970
    my-func: func(a: u32, b: string);
5971
}
5972
";
5973
        let mut resolve = Resolve::default();
5974
        let pkg = resolve.push_str("test.wit", source)?;
5975
5976
        let iface_id = resolve.packages[pkg].interfaces["iface"];
5977
        let func = &resolve.interfaces[iface_id].functions["my-func"];
5978
        assert_eq!(func.params.len(), 2);
5979
        for param in &func.params {
5980
            let start = param.span.start() as usize;
5981
            let end = param.span.end() as usize;
5982
            let snippet = &source[start..end];
5983
            assert_eq!(
5984
                snippet, param.name,
5985
                "param `{}` span points to {:?}",
5986
                param.name, snippet
5987
            );
5988
        }
5989
5990
        Ok(())
5991
    }
5992
5993
    #[test]
5994
    fn push_groups_resolves_dep_before_main() -> Result<()> {
5995
        // push_groups must topologically sort main + deps internally and succeed
5996
        // even when the dep is listed after main in the caller's mental model.
5997
        let dep = {
5998
            let mut map = SourceMap::default();
5999
            map.push_str(
6000
                "file:///dep.wit",
6001
                "package foo:dep;\ninterface i { type t = u32; }",
6002
            );
6003
            map.parse().map_err(|(_, e)| e)?
6004
        };
6005
        let main = {
6006
            let mut map = SourceMap::default();
6007
            map.push_str(
6008
                "file:///main.wit",
6009
                "package foo:main;\ninterface j { use foo:dep/i.{t}; type u = t; }",
6010
            );
6011
            map.parse().map_err(|(_, e)| e)?
6012
        };
6013
        let mut resolve = Resolve::default();
6014
        resolve.push_groups(main, Vec::from([dep]))?;
6015
        assert_eq!(resolve.packages.len(), 2);
6016
        Ok(())
6017
    }
6018
6019
    #[test]
6020
    fn push_groups_cycle_error_contains_location() {
6021
        // A cross-group cycle must produce an error message with a file URI and
6022
        // line/col. This validates that source maps are merged into resolve.source_map
6023
        // *before* toposort runs, so the span in the cycle error is resolvable.
6024
        let a = {
6025
            let mut map = SourceMap::default();
6026
            map.push_str(
6027
                "file:///a.wit",
6028
                "package foo:a;\ninterface i { use foo:b/j.{}; }",
6029
            );
6030
            map.parse().unwrap()
6031
        };
6032
        let b = {
6033
            let mut map = SourceMap::default();
6034
            map.push_str(
6035
                "file:///b.wit",
6036
                "package foo:b;\ninterface j { use foo:a/i.{}; }",
6037
            );
6038
            map.parse().unwrap()
6039
        };
6040
        let mut resolve = Resolve::default();
6041
        let err = resolve.push_groups(a, Vec::from([b])).unwrap_err();
6042
        let msg = err.render(&resolve.source_map);
6043
        assert!(
6044
            msg.contains("file:///"),
6045
            "cycle error should contain a file URI, got: {msg}"
6046
        );
6047
    }
6048
6049
    #[test]
6050
    fn param_spans_preserved_through_merge() -> Result<()> {
6051
        let mut resolve1 = Resolve::default();
6052
        resolve1.push_str(
6053
            "test1.wit",
6054
            r#"
6055
                package foo:bar;
6056
6057
                interface iface1 {
6058
                    f1: func(x: u32);
6059
                }
6060
            "#,
6061
        )?;
6062
6063
        let mut resolve2 = Resolve::default();
6064
        let pkg2 = resolve2.push_str(
6065
            "test2.wit",
6066
            r#"
6067
                package foo:baz;
6068
6069
                interface iface2 {
6070
                    f2: func(y: string, z: bool);
6071
                }
6072
            "#,
6073
        )?;
6074
6075
        let iface2_old_id = resolve2.packages[pkg2].interfaces["iface2"];
6076
6077
        let remap = resolve1.merge(resolve2)?;
6078
6079
        let iface2_id = remap.interfaces[iface2_old_id.index()].unwrap();
6080
        let func = &resolve1.interfaces[iface2_id].functions["f2"];
6081
        for param in &func.params {
6082
            assert!(
6083
                param.span.is_known(),
6084
                "param `{}` should have span after merge",
6085
                param.name
6086
            );
6087
        }
6088
6089
        Ok(())
6090
    }
6091
6092
    /// Demonstrates the round-trip property: starting from a world with only
6093
    /// exports, `importize` turns them into imports, then `exportize` turns
6094
    /// them back. The resulting world has the same set of exports (by key)
6095
    /// as the original.
6096
    #[test]
6097
    fn exportize_importize_roundtrip() -> Result<()> {
6098
        let mut resolve = Resolve::default();
6099
        let pkg = resolve.push_str(
6100
            "test.wit",
6101
            r#"
6102
                package foo:bar;
6103
6104
                interface types {
6105
                    type my-type = u32;
6106
                }
6107
6108
                interface api {
6109
                    use types.{my-type};
6110
                    do-something: func(a: my-type) -> my-type;
6111
                }
6112
6113
                world w {
6114
                    export api;
6115
                }
6116
            "#,
6117
        )?;
6118
        let world_id = resolve.packages[pkg].worlds["w"];
6119
6120
        // Snapshot original export keys.
6121
        let original_export_keys: Vec<String> = resolve.worlds[world_id]
6122
            .exports
6123
            .keys()
6124
            .map(|k| resolve.name_world_key(k))
6125
            .collect();
6126
        assert!(!original_export_keys.is_empty());
6127
        assert!(resolve.worlds[world_id].imports.iter().all(|(_, item)| {
6128
            // Before importize the only imports should be elaborated
6129
            // interface deps (all interface items).
6130
            matches!(item, WorldItem::Interface { .. })
6131
        }));
6132
6133
        // importize: exports -> imports, no exports remain.
6134
        resolve.importize(world_id, Some("w-temp".to_string()))?;
6135
        assert!(
6136
            resolve.worlds[world_id].exports.is_empty(),
6137
            "importize should leave no exports"
6138
        );
6139
        // The original exports should now appear as imports.
6140
        for key in &original_export_keys {
6141
            assert!(
6142
                resolve.worlds[world_id]
6143
                    .imports
6144
                    .keys()
6145
                    .any(|k| resolve.name_world_key(k) == *key),
6146
                "expected `{key}` to be an import after importize"
6147
            );
6148
        }
6149
6150
        // exportize: imports -> exports, round-tripping back.
6151
        resolve.exportize(world_id, Some("w-final".to_string()), None)?;
6152
        assert!(
6153
            !resolve.worlds[world_id].exports.is_empty(),
6154
            "exportize should produce exports"
6155
        );
6156
        // The original export keys should be present as exports again.
6157
        let final_export_keys: Vec<String> = resolve.worlds[world_id]
6158
            .exports
6159
            .keys()
6160
            .map(|k| resolve.name_world_key(k))
6161
            .collect();
6162
        for key in &original_export_keys {
6163
            assert!(
6164
                final_export_keys.contains(key),
6165
                "expected `{key}` to be an export after round-trip, got exports: {final_export_keys:?}"
6166
            );
6167
        }
6168
6169
        Ok(())
6170
    }
6171
6172
    #[test]
6173
    fn include_with_renames_resource_accessors() -> Result<()> {
6174
        let mut resolve = Resolve::default();
6175
        let pkg = resolve.push_str(
6176
            "test.wit",
6177
            r#"
6178
                package foo:foo;
6179
6180
                world base {
6181
                    resource r {
6182
                        p: get() -> u32;
6183
                        p: set(v: u32);
6184
                        s: static get() -> u32;
6185
                        s: static set(v: u32);
6186
                        m: func();
6187
                    }
6188
                }
6189
6190
                world derived {
6191
                    include base with { r as r2 }
6192
                }
6193
            "#,
6194
        )?;
6195
6196
        let world_id = resolve.packages[pkg].worlds["derived"];
6197
        let mut imports: Vec<String> = resolve.worlds[world_id]
6198
            .imports
6199
            .keys()
6200
            .map(|k| resolve.name_world_key(k))
6201
            .collect();
6202
        imports.sort();
6203
6204
        let mut expected: Vec<String> = [
6205
            "r2",
6206
            "[method][get]r2.p",
6207
            "[method][set]r2.p",
6208
            "[static][get]r2.s",
6209
            "[static][set]r2.s",
6210
            "[method]r2.m",
6211
        ]
6212
        .iter()
6213
        .map(|s| s.to_string())
6214
        .collect();
6215
        expected.sort();
6216
6217
        assert_eq!(imports, expected);
6218
        Ok(())
6219
    }
6220
}