Coverage Report

Created: 2025-12-04 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wit-parser/src/ast/resolve.rs
Line
Count
Source
1
use super::{ParamList, WorldOrInterface};
2
use crate::ast::toposort::toposort;
3
use crate::*;
4
use anyhow::bail;
5
use std::collections::{HashMap, HashSet};
6
use std::mem;
7
8
#[derive(Default)]
9
pub struct Resolver<'a> {
10
    /// Current package name learned through the ASTs pushed onto this resolver.
11
    package_name: Option<(PackageName, Span)>,
12
13
    /// Package docs.
14
    package_docs: Docs,
15
16
    /// All non-`package` WIT decls are going to be resolved together.
17
    decl_lists: Vec<ast::DeclList<'a>>,
18
19
    // Arenas that get plumbed to the final `UnresolvedPackage`
20
    types: Arena<TypeDef>,
21
    interfaces: Arena<Interface>,
22
    worlds: Arena<World>,
23
24
    // Interning structure for types which-need-not-be-named such as
25
    // `list<string>` and such.
26
    anon_types: HashMap<Key, TypeId>,
27
28
    /// The index within `self.ast_items` that lookups should go through. This
29
    /// is updated as the ASTs are walked.
30
    cur_ast_index: usize,
31
32
    /// A map per `ast::DeclList` which keeps track of the file's top level
33
    /// names in scope. This maps each name onto either a world or an interface,
34
    /// handling things like `use` at the top level.
35
    ast_items: Vec<IndexMap<&'a str, AstItem>>,
36
37
    /// A map for the entire package being created of all names defined within,
38
    /// along with the ID they're mapping to.
39
    package_items: IndexMap<&'a str, AstItem>,
40
41
    /// A per-interface map of name to item-in-the-interface. This is the same
42
    /// length as `self.types` and is pushed to whenever `self.types` is pushed
43
    /// to.
44
    interface_types: Vec<IndexMap<&'a str, (TypeOrItem, Span)>>,
45
46
    /// Metadata about foreign dependencies which are not defined in this
47
    /// package. This map is keyed by the name of the package being imported
48
    /// from. The next level of key is the name of the interface being imported
49
    /// from, and the final value is the assigned ID of the interface.
50
    foreign_deps: IndexMap<PackageName, IndexMap<&'a str, AstItem>>,
51
52
    /// All interfaces that are present within `self.foreign_deps`.
53
    foreign_interfaces: HashSet<InterfaceId>,
54
55
    foreign_worlds: HashSet<WorldId>,
56
57
    /// The current type lookup scope which will eventually make its way into
58
    /// `self.interface_types`.
59
    type_lookup: IndexMap<&'a str, (TypeOrItem, Span)>,
60
61
    /// An assigned span for where all types inserted into `self.types` as
62
    /// imported from foreign interfaces. These types all show up first in the
63
    /// `self.types` arena and this span is used to generate an error message
64
    /// pointing to it if the item isn't actually defined.
65
    unknown_type_spans: Vec<Span>,
66
67
    /// Spans for each world in `self.worlds`
68
    world_spans: Vec<WorldSpan>,
69
70
    /// Spans for each type in `self.types`
71
    type_spans: Vec<Span>,
72
73
    /// The span of each interface's definition which is used for error
74
    /// reporting during the final `Resolve` phase.
75
    interface_spans: Vec<InterfaceSpan>,
76
77
    /// Spans per entry in `self.foreign_deps` for where the dependency was
78
    /// introduced to print an error message if necessary.
79
    foreign_dep_spans: Vec<Span>,
80
81
    /// A list of `TypeDefKind::Unknown` types which are required to be
82
    /// resources when this package is resolved against its dependencies.
83
    required_resource_types: Vec<(TypeId, Span)>,
84
}
85
86
#[derive(PartialEq, Eq, Hash)]
87
enum Key {
88
    Variant(Vec<(String, Option<Type>)>),
89
    BorrowHandle(TypeId),
90
    Record(Vec<(String, Type)>),
91
    Flags(Vec<String>),
92
    Tuple(Vec<Type>),
93
    Enum(Vec<String>),
94
    List(Type),
95
    FixedSizeList(Type, u32),
96
    Option(Type),
97
    Result(Option<Type>, Option<Type>),
98
    Future(Option<Type>),
99
    Stream(Option<Type>),
100
}
101
102
enum TypeItem<'a, 'b> {
103
    Use(&'b ast::Use<'a>),
104
    Def(&'b ast::TypeDef<'a>),
105
}
106
107
enum TypeOrItem {
108
    Type(TypeId),
109
    Item(&'static str),
110
}
111
112
impl<'a> Resolver<'a> {
113
22.2k
    pub(super) fn push(&mut self, file: ast::PackageFile<'a>) -> Result<()> {
114
        // As each WIT file is pushed into this resolver keep track of the
115
        // current package name assigned. Only one file needs to mention it, but
116
        // if multiple mention it then they must all match.
117
22.2k
        if let Some(cur) = &file.package_id {
118
16.5k
            let cur_name = cur.package_name();
119
16.5k
            if let Some((prev, _)) = &self.package_name {
120
3.45k
                if cur_name != *prev {
121
0
                    bail!(Error::new(
122
0
                        cur.span,
123
0
                        format!(
124
0
                            "package identifier `{cur_name}` does not match \
125
0
                             previous package name of `{prev}`"
126
0
                        ),
127
0
                    ))
128
3.45k
                }
129
13.1k
            }
130
16.5k
            self.package_name = Some((cur_name, cur.span));
131
132
            // At most one 'package' item can have doc comments.
133
16.5k
            let docs = self.docs(&cur.docs);
134
16.5k
            if docs.contents.is_some() {
135
0
                if self.package_docs.contents.is_some() {
136
0
                    bail!(Error::new(
137
0
                        cur.docs.span,
138
0
                        "found doc comments on multiple 'package' items"
139
0
                    ))
140
0
                }
141
0
                self.package_docs = docs;
142
16.5k
            }
143
5.69k
        }
144
145
        // Ensure that there are no nested packages in `file`. Note that for
146
        // top level files nested packages are handled separately in `ast.rs`
147
        // with their own resolver.
148
71.5k
        for item in file.decl_list.items.iter() {
149
71.5k
            let span = match item {
150
0
                ast::AstItem::Package(pkg) => pkg.package_id.as_ref().unwrap().span,
151
71.5k
                _ => continue,
152
            };
153
0
            bail!(Error::new(
154
0
                span,
155
0
                "nested packages must be placed at the top-level"
156
0
            ))
157
        }
158
159
22.2k
        self.decl_lists.push(file.decl_list);
160
22.2k
        Ok(())
161
22.2k
    }
162
163
13.1k
    pub(crate) fn resolve(&mut self) -> Result<UnresolvedPackage> {
164
        // At least one of the WIT files must have a `package` annotation.
165
13.1k
        let (name, package_name_span) = match &self.package_name {
166
13.1k
            Some(name) => name.clone(),
167
            None => {
168
0
                bail!("no `package` header was found in any WIT file for this package")
169
            }
170
        };
171
172
        // First populate information about foreign dependencies and the general
173
        // structure of the package. This should resolve the "base" of many
174
        // `use` statements and additionally generate a topological ordering of
175
        // all interfaces in the package to visit.
176
13.1k
        let decl_lists = mem::take(&mut self.decl_lists);
177
13.1k
        self.populate_foreign_deps(&decl_lists);
178
13.1k
        let (iface_order, world_order) = self.populate_ast_items(&decl_lists)?;
179
13.1k
        self.populate_foreign_types(&decl_lists)?;
180
181
        // Use the topological ordering of all interfaces to resolve all
182
        // interfaces in-order. Note that a reverse-mapping from ID to AST is
183
        // generated here to assist with this.
184
13.1k
        let mut iface_id_to_ast = IndexMap::new();
185
13.1k
        let mut world_id_to_ast = IndexMap::new();
186
22.2k
        for (i, decl_list) in decl_lists.iter().enumerate() {
187
71.5k
            for item in decl_list.items.iter() {
188
71.5k
                match item {
189
51.7k
                    ast::AstItem::Interface(iface) => {
190
51.7k
                        let id = match self.ast_items[i][iface.name.name] {
191
51.7k
                            AstItem::Interface(id) => id,
192
0
                            AstItem::World(_) => unreachable!(),
193
                        };
194
51.7k
                        iface_id_to_ast.insert(id, (iface, i));
195
                    }
196
17.4k
                    ast::AstItem::World(world) => {
197
17.4k
                        let id = match self.ast_items[i][world.name.name] {
198
17.4k
                            AstItem::World(id) => id,
199
0
                            AstItem::Interface(_) => unreachable!(),
200
                        };
201
17.4k
                        world_id_to_ast.insert(id, (world, i));
202
                    }
203
2.37k
                    ast::AstItem::Use(_) => {}
204
0
                    ast::AstItem::Package(_) => unreachable!(),
205
                }
206
            }
207
        }
208
209
64.8k
        for id in iface_order {
210
51.7k
            let (interface, i) = &iface_id_to_ast[&id];
211
51.7k
            self.cur_ast_index = *i;
212
51.7k
            self.resolve_interface(id, &interface.items, &interface.docs, &interface.attributes)?;
213
        }
214
215
30.6k
        for id in world_order {
216
17.4k
            let (world, i) = &world_id_to_ast[&id];
217
17.4k
            self.cur_ast_index = *i;
218
17.4k
            self.resolve_world(id, world)?;
219
        }
220
221
13.1k
        self.decl_lists = decl_lists;
222
        Ok(UnresolvedPackage {
223
13.1k
            package_name_span,
224
13.1k
            name,
225
13.1k
            docs: mem::take(&mut self.package_docs),
226
13.1k
            worlds: mem::take(&mut self.worlds),
227
13.1k
            types: mem::take(&mut self.types),
228
13.1k
            interfaces: mem::take(&mut self.interfaces),
229
13.1k
            foreign_deps: self
230
13.1k
                .foreign_deps
231
13.1k
                .iter()
232
13.1k
                .map(|(name, deps)| {
233
                    (
234
1.87k
                        name.clone(),
235
1.87k
                        deps.iter()
236
2.17k
                            .map(|(name, id)| (name.to_string(), *id))
237
1.87k
                            .collect(),
238
                    )
239
1.87k
                })
240
13.1k
                .collect(),
241
13.1k
            unknown_type_spans: mem::take(&mut self.unknown_type_spans),
242
13.1k
            interface_spans: mem::take(&mut self.interface_spans),
243
13.1k
            world_spans: mem::take(&mut self.world_spans),
244
13.1k
            type_spans: mem::take(&mut self.type_spans),
245
13.1k
            foreign_dep_spans: mem::take(&mut self.foreign_dep_spans),
246
13.1k
            required_resource_types: mem::take(&mut self.required_resource_types),
247
        })
248
13.1k
    }
249
250
    /// Registers all foreign dependencies made within the ASTs provided.
251
    ///
252
    /// This will populate the `self.foreign_{deps,interfaces,worlds}` maps with all
253
    /// `UsePath::Package` entries.
254
13.1k
    fn populate_foreign_deps(&mut self, decl_lists: &[ast::DeclList<'a>]) {
255
13.1k
        let mut foreign_deps = mem::take(&mut self.foreign_deps);
256
13.1k
        let mut foreign_interfaces = mem::take(&mut self.foreign_interfaces);
257
13.1k
        let mut foreign_worlds = mem::take(&mut self.foreign_worlds);
258
35.4k
        for decl_list in decl_lists {
259
22.2k
            decl_list
260
22.2k
                .for_each_path(&mut |_, _attrs, path, _names, world_or_iface| {
261
15.2k
                    let (id, name) = match path {
262
9.22k
                        ast::UsePath::Package { id, name } => (id, name),
263
6.00k
                        _ => return Ok(()),
264
                    };
265
266
9.22k
                    let deps = foreign_deps.entry(id.package_name()).or_insert_with(|| {
267
1.87k
                        self.foreign_dep_spans.push(id.span);
268
1.87k
                        IndexMap::new()
269
1.87k
                    });
270
9.22k
                    let id = *deps.entry(name.name).or_insert_with(|| {
271
2.17k
                        match world_or_iface {
272
                            WorldOrInterface::World => {
273
0
                                log::trace!(
274
0
                                    "creating a world for foreign dep: {}/{}",
275
0
                                    id.package_name(),
276
                                    name.name
277
                                );
278
0
                                AstItem::World(self.alloc_world(name.span))
279
                            }
280
                            WorldOrInterface::Interface | WorldOrInterface::Unknown => {
281
                                // Currently top-level `use` always assumes an interface, so the
282
                                // `Unknown` case is the same as `Interface`.
283
2.17k
                                log::trace!(
284
0
                                    "creating an interface for foreign dep: {}/{}",
285
0
                                    id.package_name(),
286
                                    name.name
287
                                );
288
2.17k
                                AstItem::Interface(self.alloc_interface(name.span))
289
                            }
290
                        }
291
2.17k
                    });
292
293
9.22k
                    let _ = match id {
294
9.22k
                        AstItem::Interface(id) => foreign_interfaces.insert(id),
295
0
                        AstItem::World(id) => foreign_worlds.insert(id),
296
                    };
297
298
9.22k
                    Ok(())
299
15.2k
                })
300
22.2k
                .unwrap();
301
        }
302
13.1k
        self.foreign_deps = foreign_deps;
303
13.1k
        self.foreign_interfaces = foreign_interfaces;
304
13.1k
        self.foreign_worlds = foreign_worlds;
305
13.1k
    }
306
307
56.8k
    fn alloc_interface(&mut self, span: Span) -> InterfaceId {
308
56.8k
        self.interface_types.push(IndexMap::new());
309
56.8k
        self.interface_spans.push(InterfaceSpan {
310
56.8k
            span,
311
56.8k
            funcs: Vec::new(),
312
56.8k
        });
313
56.8k
        self.interfaces.alloc(Interface {
314
56.8k
            name: None,
315
56.8k
            types: IndexMap::new(),
316
56.8k
            docs: Docs::default(),
317
56.8k
            stability: Default::default(),
318
56.8k
            functions: IndexMap::new(),
319
56.8k
            package: None,
320
56.8k
        })
321
56.8k
    }
322
323
17.4k
    fn alloc_world(&mut self, span: Span) -> WorldId {
324
17.4k
        self.world_spans.push(WorldSpan {
325
17.4k
            span,
326
17.4k
            imports: Vec::new(),
327
17.4k
            exports: Vec::new(),
328
17.4k
            includes: Vec::new(),
329
17.4k
        });
330
17.4k
        self.worlds.alloc(World {
331
17.4k
            name: String::new(),
332
17.4k
            docs: Docs::default(),
333
17.4k
            exports: IndexMap::new(),
334
17.4k
            imports: IndexMap::new(),
335
17.4k
            package: None,
336
17.4k
            includes: Default::default(),
337
17.4k
            include_names: Default::default(),
338
17.4k
            stability: Default::default(),
339
17.4k
        })
340
17.4k
    }
341
342
    /// This method will create a `World` and an `Interface` for all items
343
    /// present in the specified set of ASTs. Additionally maps for each AST are
344
    /// generated for resolving use-paths later on.
345
13.1k
    fn populate_ast_items(
346
13.1k
        &mut self,
347
13.1k
        decl_lists: &[ast::DeclList<'a>],
348
13.1k
    ) -> Result<(Vec<InterfaceId>, Vec<WorldId>)> {
349
13.1k
        let mut package_items = IndexMap::new();
350
351
        // Validate that all worlds and interfaces have unique names within this
352
        // package across all ASTs which make up the package.
353
13.1k
        let mut names = HashMap::new();
354
13.1k
        let mut decl_list_namespaces = Vec::new();
355
13.1k
        let mut order = IndexMap::new();
356
35.4k
        for decl_list in decl_lists {
357
22.2k
            let mut decl_list_ns = IndexMap::new();
358
71.5k
            for item in decl_list.items.iter() {
359
71.5k
                match item {
360
51.7k
                    ast::AstItem::Interface(i) => {
361
51.7k
                        if package_items.insert(i.name.name, i.name.span).is_some() {
362
0
                            bail!(Error::new(
363
0
                                i.name.span,
364
0
                                format!("duplicate item named `{}`", i.name.name),
365
0
                            ))
366
51.7k
                        }
367
51.7k
                        let prev = decl_list_ns.insert(i.name.name, ());
368
51.7k
                        assert!(prev.is_none());
369
51.7k
                        let prev = order.insert(i.name.name, Vec::new());
370
51.7k
                        assert!(prev.is_none());
371
51.7k
                        let prev = names.insert(i.name.name, item);
372
51.7k
                        assert!(prev.is_none());
373
                    }
374
17.4k
                    ast::AstItem::World(w) => {
375
17.4k
                        if package_items.insert(w.name.name, w.name.span).is_some() {
376
0
                            bail!(Error::new(
377
0
                                w.name.span,
378
0
                                format!("duplicate item named `{}`", w.name.name),
379
0
                            ))
380
17.4k
                        }
381
17.4k
                        let prev = decl_list_ns.insert(w.name.name, ());
382
17.4k
                        assert!(prev.is_none());
383
17.4k
                        let prev = order.insert(w.name.name, Vec::new());
384
17.4k
                        assert!(prev.is_none());
385
17.4k
                        let prev = names.insert(w.name.name, item);
386
17.4k
                        assert!(prev.is_none());
387
                    }
388
                    // These are processed down below.
389
2.37k
                    ast::AstItem::Use(_) => {}
390
391
0
                    ast::AstItem::Package(_) => unreachable!(),
392
                }
393
            }
394
22.2k
            decl_list_namespaces.push(decl_list_ns);
395
        }
396
397
        // Next record dependencies between interfaces as induced via `use`
398
        // paths. This step is used to perform a topological sort of all
399
        // interfaces to ensure there are no cycles and to generate an ordering
400
        // which we can resolve in.
401
        enum ItemSource<'a> {
402
            Foreign,
403
            Local(ast::Id<'a>),
404
        }
405
406
35.4k
        for decl_list in decl_lists {
407
            // Record, in the context of this file, what all names are defined
408
            // at the top level and whether they point to other items in this
409
            // package or foreign items. Foreign deps are ignored for
410
            // topological ordering.
411
22.2k
            let mut decl_list_ns = IndexMap::new();
412
71.5k
            for item in decl_list.items.iter() {
413
71.5k
                let (name, src) = match item {
414
2.37k
                    ast::AstItem::Use(u) => {
415
2.37k
                        let name = u.as_.as_ref().unwrap_or(u.item.name());
416
2.37k
                        let src = match &u.item {
417
1.12k
                            ast::UsePath::Id(id) => ItemSource::Local(id.clone()),
418
1.25k
                            ast::UsePath::Package { .. } => ItemSource::Foreign,
419
                        };
420
2.37k
                        (name, src)
421
                    }
422
51.7k
                    ast::AstItem::Interface(i) => (&i.name, ItemSource::Local(i.name.clone())),
423
17.4k
                    ast::AstItem::World(w) => (&w.name, ItemSource::Local(w.name.clone())),
424
0
                    ast::AstItem::Package(_) => unreachable!(),
425
                };
426
71.5k
                if decl_list_ns.insert(name.name, (name.span, src)).is_some() {
427
0
                    bail!(Error::new(
428
0
                        name.span,
429
0
                        format!("duplicate name `{}` in this file", name.name),
430
0
                    ));
431
71.5k
                }
432
            }
433
434
            // With this file's namespace information look at all `use` paths
435
            // and record dependencies between interfaces.
436
22.2k
            decl_list.for_each_path(&mut |iface, _attrs, path, _names, _| {
437
                // If this import isn't contained within an interface then it's
438
                // in a world and it doesn't need to participate in our
439
                // topo-sort.
440
15.2k
                let iface = match iface {
441
9.73k
                    Some(name) => name,
442
5.49k
                    None => return Ok(()),
443
                };
444
9.73k
                let used_name = match path {
445
2.90k
                    ast::UsePath::Id(id) => id,
446
6.83k
                    ast::UsePath::Package { .. } => return Ok(()),
447
                };
448
2.90k
                match decl_list_ns.get(used_name.name) {
449
30
                    Some((_, ItemSource::Foreign)) => return Ok(()),
450
1.39k
                    Some((_, ItemSource::Local(id))) => {
451
1.39k
                        order[iface.name].push(id.clone());
452
1.39k
                    }
453
1.47k
                    None => match package_items.get(used_name.name) {
454
1.47k
                        Some(_) => {
455
1.47k
                            order[iface.name].push(used_name.clone());
456
1.47k
                        }
457
                        None => {
458
0
                            bail!(Error::new(
459
0
                                used_name.span,
460
0
                                format!(
461
0
                                    "interface or world `{name}` not found in package",
462
0
                                    name = used_name.name
463
0
                                ),
464
0
                            ))
465
                        }
466
                    },
467
                }
468
2.87k
                Ok(())
469
15.2k
            })?;
470
        }
471
472
13.1k
        let order = toposort("interface or world", &order)?;
473
13.1k
        log::debug!("toposort for interfaces and worlds in order: {order:?}");
474
475
        // Allocate interfaces in-order now that the ordering is defined. This
476
        // is then used to build up internal maps for each AST which are stored
477
        // in `self.ast_items`.
478
13.1k
        let mut ids = IndexMap::new();
479
13.1k
        let mut iface_id_order = Vec::new();
480
13.1k
        let mut world_id_order = Vec::new();
481
82.3k
        for name in order {
482
69.2k
            match names.get(name).unwrap() {
483
                ast::AstItem::Interface(_) => {
484
51.7k
                    let id = self.alloc_interface(package_items[name]);
485
51.7k
                    self.interfaces[id].name = Some(name.to_string());
486
51.7k
                    let prev = ids.insert(name, AstItem::Interface(id));
487
51.7k
                    assert!(prev.is_none());
488
51.7k
                    iface_id_order.push(id);
489
                }
490
                ast::AstItem::World(_) => {
491
17.4k
                    let id = self.alloc_world(package_items[name]);
492
17.4k
                    self.worlds[id].name = name.to_string();
493
17.4k
                    let prev = ids.insert(name, AstItem::World(id));
494
17.4k
                    assert!(prev.is_none());
495
17.4k
                    world_id_order.push(id);
496
                }
497
0
                ast::AstItem::Use(_) | ast::AstItem::Package(_) => unreachable!(),
498
            };
499
        }
500
35.4k
        for decl_list in decl_lists {
501
22.2k
            let mut items = IndexMap::new();
502
71.5k
            for item in decl_list.items.iter() {
503
71.5k
                let (name, ast_item) = match item {
504
2.37k
                    ast::AstItem::Use(u) => {
505
2.37k
                        if !u.attributes.is_empty() {
506
0
                            bail!(Error::new(
507
0
                                u.span,
508
0
                                format!("attributes not allowed on top-level use"),
509
0
                            ))
510
2.37k
                        }
511
2.37k
                        let name = u.as_.as_ref().unwrap_or(u.item.name());
512
2.37k
                        let item = match &u.item {
513
1.12k
                            ast::UsePath::Id(name) => *ids.get(name.name).ok_or_else(|| {
514
0
                                Error::new(
515
0
                                    name.span,
516
0
                                    format!(
517
0
                                        "interface or world `{name}` does not exist",
518
                                        name = name.name
519
                                    ),
520
                                )
521
0
                            })?,
522
1.25k
                            ast::UsePath::Package { id, name } => {
523
1.25k
                                self.foreign_deps[&id.package_name()][name.name]
524
                            }
525
                        };
526
2.37k
                        (name.name, item)
527
                    }
528
51.7k
                    ast::AstItem::Interface(i) => {
529
51.7k
                        let iface_item = ids[i.name.name];
530
51.7k
                        assert!(matches!(iface_item, AstItem::Interface(_)));
531
51.7k
                        (i.name.name, iface_item)
532
                    }
533
17.4k
                    ast::AstItem::World(w) => {
534
17.4k
                        let world_item = ids[w.name.name];
535
17.4k
                        assert!(matches!(world_item, AstItem::World(_)));
536
17.4k
                        (w.name.name, world_item)
537
                    }
538
0
                    ast::AstItem::Package(_) => unreachable!(),
539
                };
540
71.5k
                let prev = items.insert(name, ast_item);
541
71.5k
                assert!(prev.is_none());
542
543
                // Items defined via `use` don't go into the package namespace,
544
                // only the file namespace.
545
71.5k
                if !matches!(item, ast::AstItem::Use(_)) {
546
69.2k
                    let prev = self.package_items.insert(name, ast_item);
547
69.2k
                    assert!(prev.is_none());
548
2.37k
                }
549
            }
550
22.2k
            self.ast_items.push(items);
551
        }
552
13.1k
        Ok((iface_id_order, world_id_order))
553
13.1k
    }
554
555
    /// Generate a `Type::Unknown` entry for all types imported from foreign
556
    /// packages.
557
    ///
558
    /// This is done after all interfaces are generated so `self.resolve_path`
559
    /// can be used to determine if what's being imported from is a foreign
560
    /// interface or not.
561
13.1k
    fn populate_foreign_types(&mut self, decl_lists: &[ast::DeclList<'a>]) -> Result<()> {
562
22.2k
        for (i, decl_list) in decl_lists.iter().enumerate() {
563
22.2k
            self.cur_ast_index = i;
564
22.2k
            decl_list.for_each_path(&mut |_, attrs, path, names, _| {
565
15.2k
                let names = match names {
566
11.7k
                    Some(names) => names,
567
3.49k
                    None => return Ok(()),
568
                };
569
11.7k
                let stability = self.stability(attrs)?;
570
11.7k
                let (item, name, span) = self.resolve_ast_item_path(path)?;
571
11.7k
                let iface = self.extract_iface_from_item(&item, &name, span)?;
572
11.7k
                if !self.foreign_interfaces.contains(&iface) {
573
4.16k
                    return Ok(());
574
7.57k
                }
575
576
7.57k
                let lookup = &mut self.interface_types[iface.index()];
577
15.9k
                for name in names {
578
                    // If this name has already been defined then use that prior
579
                    // definition, otherwise create a new type with an unknown
580
                    // representation and insert it into the various maps.
581
8.40k
                    if lookup.contains_key(name.name.name) {
582
6.34k
                        continue;
583
2.05k
                    }
584
2.05k
                    let id = self.types.alloc(TypeDef {
585
2.05k
                        docs: Docs::default(),
586
2.05k
                        stability: stability.clone(),
587
2.05k
                        kind: TypeDefKind::Unknown,
588
2.05k
                        name: Some(name.name.name.to_string()),
589
2.05k
                        owner: TypeOwner::Interface(iface),
590
2.05k
                    });
591
2.05k
                    self.unknown_type_spans.push(name.name.span);
592
2.05k
                    self.type_spans.push(name.name.span);
593
2.05k
                    lookup.insert(name.name.name, (TypeOrItem::Type(id), name.name.span));
594
2.05k
                    self.interfaces[iface]
595
2.05k
                        .types
596
2.05k
                        .insert(name.name.name.to_string(), id);
597
                }
598
599
7.57k
                Ok(())
600
15.2k
            })?;
601
        }
602
13.1k
        Ok(())
603
13.1k
    }
604
605
17.4k
    fn resolve_world(&mut self, world_id: WorldId, world: &ast::World<'a>) -> Result<WorldId> {
606
17.4k
        let docs = self.docs(&world.docs);
607
17.4k
        self.worlds[world_id].docs = docs;
608
17.4k
        let stability = self.stability(&world.attributes)?;
609
17.4k
        self.worlds[world_id].stability = stability;
610
611
17.4k
        self.resolve_types(
612
17.4k
            TypeOwner::World(world_id),
613
53.8k
            world.items.iter().filter_map(|i| match i {
614
3.01k
                ast::WorldItem::Use(u) => Some(TypeItem::Use(u)),
615
35.4k
                ast::WorldItem::Type(t) => Some(TypeItem::Def(t)),
616
15.3k
                ast::WorldItem::Import(_) | ast::WorldItem::Export(_) => None,
617
                // should be handled in `wit-parser::resolve`
618
0
                ast::WorldItem::Include(_) => None,
619
53.8k
            }),
620
0
        )?;
621
622
        // resolve include items
623
26.9k
        let items = world.items.iter().filter_map(|i| match i {
624
0
            ast::WorldItem::Include(i) => Some(i),
625
26.9k
            _ => None,
626
26.9k
        });
627
17.4k
        for include in items {
628
0
            self.resolve_include(world_id, include)?;
629
        }
630
631
17.4k
        let mut export_spans = Vec::new();
632
17.4k
        let mut import_spans = Vec::new();
633
19.6k
        for (name, (item, span)) in self.type_lookup.iter() {
634
19.6k
            match *item {
635
19.6k
                TypeOrItem::Type(id) => {
636
19.6k
                    let prev = self.worlds[world_id]
637
19.6k
                        .imports
638
19.6k
                        .insert(WorldKey::Name(name.to_string()), WorldItem::Type(id));
639
19.6k
                    if prev.is_some() {
640
0
                        bail!(Error::new(
641
0
                            *span,
642
0
                            format!("import `{name}` conflicts with prior import of same name"),
643
0
                        ))
644
19.6k
                    }
645
19.6k
                    import_spans.push(*span);
646
                }
647
0
                TypeOrItem::Item(_) => unreachable!(),
648
            }
649
        }
650
651
17.4k
        let mut imported_interfaces = HashSet::new();
652
17.4k
        let mut exported_interfaces = HashSet::new();
653
26.9k
        for item in world.items.iter() {
654
17.7k
            let (docs, attrs, kind, desc, spans, interfaces) = match item {
655
4.85k
                ast::WorldItem::Import(import) => (
656
4.85k
                    &import.docs,
657
4.85k
                    &import.attributes,
658
4.85k
                    &import.kind,
659
4.85k
                    "import",
660
4.85k
                    &mut import_spans,
661
4.85k
                    &mut imported_interfaces,
662
4.85k
                ),
663
2.83k
                ast::WorldItem::Export(export) => (
664
2.83k
                    &export.docs,
665
2.83k
                    &export.attributes,
666
2.83k
                    &export.kind,
667
2.83k
                    "export",
668
2.83k
                    &mut export_spans,
669
2.83k
                    &mut exported_interfaces,
670
2.83k
                ),
671
672
                ast::WorldItem::Type(ast::TypeDef {
673
791
                    name,
674
791
                    ty: ast::Type::Resource(r),
675
                    ..
676
                }) => {
677
1.37k
                    for func in r.funcs.iter() {
678
1.37k
                        import_spans.push(func.named_func().name.span);
679
1.37k
                        let func = self.resolve_resource_func(func, name)?;
680
1.37k
                        let prev = self.worlds[world_id]
681
1.37k
                            .imports
682
1.37k
                            .insert(WorldKey::Name(func.name.clone()), WorldItem::Function(func));
683
                        // Resource names themselves are unique, and methods are
684
                        // uniquely named, so this should be possible to assert
685
                        // at this point and never trip.
686
1.37k
                        assert!(prev.is_none());
687
                    }
688
791
                    continue;
689
                }
690
691
                // handled in `resolve_types`
692
                ast::WorldItem::Use(_) | ast::WorldItem::Type(_) | ast::WorldItem::Include(_) => {
693
18.4k
                    continue;
694
                }
695
            };
696
697
7.68k
            let world_item = self.resolve_world_item(docs, attrs, kind)?;
698
7.68k
            let key = match kind {
699
                // Interfaces are always named exactly as they are in the WIT.
700
2.94k
                ast::ExternKind::Interface(name, _) => WorldKey::Name(name.name.to_string()),
701
702
                // Functions, however, might get mangled (e.g. with async)
703
                // meaning that the item's name comes from the function, not
704
                // from the in-WIT name.
705
                ast::ExternKind::Func(..) => {
706
3.61k
                    let func = match &world_item {
707
3.61k
                        WorldItem::Function(f) => f,
708
0
                        _ => unreachable!(),
709
                    };
710
3.61k
                    WorldKey::Name(func.name.clone())
711
                }
712
713
1.12k
                ast::ExternKind::Path(path) => {
714
1.12k
                    let (item, name, span) = self.resolve_ast_item_path(path)?;
715
1.12k
                    let id = self.extract_iface_from_item(&item, &name, span)?;
716
1.12k
                    WorldKey::Interface(id)
717
                }
718
            };
719
7.68k
            if let WorldItem::Interface { id, .. } = world_item {
720
4.06k
                if !interfaces.insert(id) {
721
0
                    bail!(Error::new(
722
0
                        kind.span(),
723
0
                        format!("interface cannot be {desc}ed more than once"),
724
0
                    ))
725
4.06k
                }
726
3.61k
            }
727
7.68k
            let dst = if desc == "import" {
728
4.85k
                &mut self.worlds[world_id].imports
729
            } else {
730
2.83k
                &mut self.worlds[world_id].exports
731
            };
732
7.68k
            let prev = dst.insert(key.clone(), world_item);
733
7.68k
            if let Some(prev) = prev {
734
0
                let prev = match prev {
735
0
                    WorldItem::Interface { .. } => "interface",
736
0
                    WorldItem::Function(..) => "func",
737
0
                    WorldItem::Type(..) => "type",
738
                };
739
0
                let name = match key {
740
0
                    WorldKey::Name(name) => name,
741
0
                    WorldKey::Interface(..) => unreachable!(),
742
                };
743
0
                bail!(Error::new(
744
0
                    kind.span(),
745
0
                    format!("{desc} `{name}` conflicts with prior {prev} of same name",),
746
0
                ))
747
7.68k
            }
748
7.68k
            spans.push(kind.span());
749
        }
750
17.4k
        self.world_spans[world_id.index()].imports = import_spans;
751
17.4k
        self.world_spans[world_id.index()].exports = export_spans;
752
17.4k
        self.type_lookup.clear();
753
754
17.4k
        Ok(world_id)
755
17.4k
    }
756
757
7.68k
    fn resolve_world_item(
758
7.68k
        &mut self,
759
7.68k
        docs: &ast::Docs<'a>,
760
7.68k
        attrs: &[ast::Attribute<'a>],
761
7.68k
        kind: &ast::ExternKind<'a>,
762
7.68k
    ) -> Result<WorldItem> {
763
7.68k
        match kind {
764
2.94k
            ast::ExternKind::Interface(name, items) => {
765
2.94k
                let prev = mem::take(&mut self.type_lookup);
766
2.94k
                let id = self.alloc_interface(name.span);
767
2.94k
                self.resolve_interface(id, items, docs, attrs)?;
768
2.94k
                self.type_lookup = prev;
769
2.94k
                let stability = self.interfaces[id].stability.clone();
770
2.94k
                Ok(WorldItem::Interface { id, stability })
771
            }
772
1.12k
            ast::ExternKind::Path(path) => {
773
1.12k
                let stability = self.stability(attrs)?;
774
1.12k
                let (item, name, span) = self.resolve_ast_item_path(path)?;
775
1.12k
                let id = self.extract_iface_from_item(&item, &name, span)?;
776
1.12k
                Ok(WorldItem::Interface { id, stability })
777
            }
778
3.61k
            ast::ExternKind::Func(name, func) => {
779
3.61k
                let func = self.resolve_function(
780
3.61k
                    docs,
781
3.61k
                    attrs,
782
3.61k
                    &name.name,
783
3.61k
                    func,
784
3.61k
                    if func.async_ {
785
1.25k
                        FunctionKind::AsyncFreestanding
786
                    } else {
787
2.35k
                        FunctionKind::Freestanding
788
                    },
789
0
                )?;
790
3.61k
                Ok(WorldItem::Function(func))
791
            }
792
        }
793
7.68k
    }
794
795
54.6k
    fn resolve_interface(
796
54.6k
        &mut self,
797
54.6k
        interface_id: InterfaceId,
798
54.6k
        fields: &[ast::InterfaceItem<'a>],
799
54.6k
        docs: &ast::Docs<'a>,
800
54.6k
        attrs: &[ast::Attribute<'a>],
801
54.6k
    ) -> Result<()> {
802
54.6k
        let docs = self.docs(docs);
803
54.6k
        self.interfaces[interface_id].docs = docs;
804
54.6k
        let stability = self.stability(attrs)?;
805
54.6k
        self.interfaces[interface_id].stability = stability;
806
807
54.6k
        self.resolve_types(
808
54.6k
            TypeOwner::Interface(interface_id),
809
91.3k
            fields.iter().filter_map(|i| match i {
810
20.4k
                ast::InterfaceItem::Use(u) => Some(TypeItem::Use(u)),
811
39.4k
                ast::InterfaceItem::TypeDef(t) => Some(TypeItem::Def(t)),
812
31.4k
                ast::InterfaceItem::Func(_) => None,
813
91.3k
            }),
814
0
        )?;
815
816
54.6k
        for (name, (ty, _)) in self.type_lookup.iter() {
817
31.5k
            match *ty {
818
31.5k
                TypeOrItem::Type(id) => {
819
31.5k
                    self.interfaces[interface_id]
820
31.5k
                        .types
821
31.5k
                        .insert(name.to_string(), id);
822
31.5k
                }
823
0
                TypeOrItem::Item(_) => unreachable!(),
824
            }
825
        }
826
827
        // Finally process all function definitions now that all types are
828
        // defined.
829
54.6k
        let mut funcs = Vec::new();
830
100k
        for field in fields {
831
19.7k
            match field {
832
15.7k
                ast::InterfaceItem::Func(f) => {
833
15.7k
                    self.define_interface_name(&f.name, TypeOrItem::Item("function"))?;
834
15.7k
                    funcs.push(self.resolve_function(
835
15.7k
                        &f.docs,
836
15.7k
                        &f.attributes,
837
15.7k
                        &f.name.name,
838
15.7k
                        &f.func,
839
15.7k
                        if f.func.async_ {
840
9.59k
                            FunctionKind::AsyncFreestanding
841
                        } else {
842
6.14k
                            FunctionKind::Freestanding
843
                        },
844
0
                    )?);
845
15.7k
                    self.interface_spans[interface_id.index()]
846
15.7k
                        .funcs
847
15.7k
                        .push(f.name.span);
848
                }
849
10.2k
                ast::InterfaceItem::Use(_) => {}
850
                ast::InterfaceItem::TypeDef(ast::TypeDef {
851
1.68k
                    name,
852
1.68k
                    ty: ast::Type::Resource(r),
853
                    ..
854
                }) => {
855
2.79k
                    for func in r.funcs.iter() {
856
2.79k
                        funcs.push(self.resolve_resource_func(func, name)?);
857
2.79k
                        self.interface_spans[interface_id.index()]
858
2.79k
                            .funcs
859
2.79k
                            .push(func.named_func().name.span);
860
                    }
861
                }
862
18.0k
                ast::InterfaceItem::TypeDef(_) => {}
863
            }
864
        }
865
73.2k
        for func in funcs {
866
18.5k
            let prev = self.interfaces[interface_id]
867
18.5k
                .functions
868
18.5k
                .insert(func.name.clone(), func);
869
18.5k
            assert!(prev.is_none());
870
        }
871
872
54.6k
        let lookup = mem::take(&mut self.type_lookup);
873
54.6k
        self.interface_types[interface_id.index()] = lookup;
874
875
54.6k
        Ok(())
876
54.6k
    }
877
878
72.1k
    fn resolve_types<'b>(
879
72.1k
        &mut self,
880
72.1k
        owner: TypeOwner,
881
72.1k
        fields: impl Iterator<Item = TypeItem<'a, 'b>> + Clone,
882
72.1k
    ) -> Result<()>
883
72.1k
    where
884
72.1k
        'a: 'b,
885
    {
886
72.1k
        assert!(self.type_lookup.is_empty());
887
888
        // First, populate our namespace with `use` statements
889
72.1k
        for field in fields.clone() {
890
49.1k
            match field {
891
11.7k
                TypeItem::Use(u) => {
892
11.7k
                    self.resolve_use(owner, u)?;
893
                }
894
37.4k
                TypeItem::Def(_) => {}
895
            }
896
        }
897
898
        // Next determine dependencies between types, perform a topological
899
        // sort, and then define all types. This will define types in a
900
        // topological fashion, forbid cycles, and weed out references to
901
        // undefined types all in one go.
902
72.1k
        let mut type_deps = IndexMap::new();
903
72.1k
        let mut type_defs = IndexMap::new();
904
121k
        for field in fields {
905
49.1k
            match field {
906
37.4k
                TypeItem::Def(t) => {
907
37.4k
                    let prev = type_defs.insert(t.name.name, Some(t));
908
37.4k
                    if prev.is_some() {
909
0
                        bail!(Error::new(
910
0
                            t.name.span,
911
0
                            format!("name `{}` is defined more than once", t.name.name),
912
0
                        ))
913
37.4k
                    }
914
37.4k
                    let mut deps = Vec::new();
915
37.4k
                    collect_deps(&t.ty, &mut deps);
916
37.4k
                    type_deps.insert(t.name.name, deps);
917
                }
918
11.7k
                TypeItem::Use(u) => {
919
13.7k
                    for name in u.names.iter() {
920
13.7k
                        let name = name.as_.as_ref().unwrap_or(&name.name);
921
13.7k
                        type_deps.insert(name.name, Vec::new());
922
13.7k
                        type_defs.insert(name.name, None);
923
13.7k
                    }
924
                }
925
            }
926
        }
927
72.1k
        let order = toposort("type", &type_deps).map_err(attach_old_float_type_context)?;
928
123k
        for ty in order {
929
51.2k
            let def = match type_defs.swap_remove(&ty).unwrap() {
930
37.4k
                Some(def) => def,
931
13.7k
                None => continue,
932
            };
933
37.4k
            let docs = self.docs(&def.docs);
934
37.4k
            let stability = self.stability(&def.attributes)?;
935
37.4k
            let kind = self.resolve_type_def(&def.ty, &stability)?;
936
37.4k
            let id = self.types.alloc(TypeDef {
937
37.4k
                docs,
938
37.4k
                stability,
939
37.4k
                kind,
940
37.4k
                name: Some(def.name.name.to_string()),
941
37.4k
                owner,
942
37.4k
            });
943
37.4k
            self.type_spans.push(def.name.span);
944
37.4k
            self.define_interface_name(&def.name, TypeOrItem::Type(id))?;
945
        }
946
72.1k
        return Ok(());
947
948
0
        fn attach_old_float_type_context(err: ast::toposort::Error) -> anyhow::Error {
949
0
            let name = match &err {
950
0
                ast::toposort::Error::NonexistentDep { name, .. } => name,
951
0
                _ => return err.into(),
952
            };
953
0
            let new = match name.as_str() {
954
0
                "float32" => "f32",
955
0
                "float64" => "f64",
956
0
                _ => return err.into(),
957
            };
958
959
0
            let context = format!(
960
0
                "the `{name}` type has been renamed to `{new}` and is \
961
0
                 no longer accepted, but the `WIT_REQUIRE_F32_F64=0` \
962
0
                 environment variable can be used to temporarily \
963
0
                 disable this error"
964
            );
965
0
            anyhow::Error::from(err).context(context)
966
0
        }
967
72.1k
    }
<wit_parser::ast::resolve::Resolver>::resolve_types::<core::iter::adapters::filter_map::FilterMap<core::slice::iter::Iter<wit_parser::ast::InterfaceItem>, <wit_parser::ast::resolve::Resolver>::resolve_interface::{closure#0}>>
Line
Count
Source
878
54.6k
    fn resolve_types<'b>(
879
54.6k
        &mut self,
880
54.6k
        owner: TypeOwner,
881
54.6k
        fields: impl Iterator<Item = TypeItem<'a, 'b>> + Clone,
882
54.6k
    ) -> Result<()>
883
54.6k
    where
884
54.6k
        'a: 'b,
885
    {
886
54.6k
        assert!(self.type_lookup.is_empty());
887
888
        // First, populate our namespace with `use` statements
889
54.6k
        for field in fields.clone() {
890
29.9k
            match field {
891
10.2k
                TypeItem::Use(u) => {
892
10.2k
                    self.resolve_use(owner, u)?;
893
                }
894
19.7k
                TypeItem::Def(_) => {}
895
            }
896
        }
897
898
        // Next determine dependencies between types, perform a topological
899
        // sort, and then define all types. This will define types in a
900
        // topological fashion, forbid cycles, and weed out references to
901
        // undefined types all in one go.
902
54.6k
        let mut type_deps = IndexMap::new();
903
54.6k
        let mut type_defs = IndexMap::new();
904
84.6k
        for field in fields {
905
29.9k
            match field {
906
19.7k
                TypeItem::Def(t) => {
907
19.7k
                    let prev = type_defs.insert(t.name.name, Some(t));
908
19.7k
                    if prev.is_some() {
909
0
                        bail!(Error::new(
910
0
                            t.name.span,
911
0
                            format!("name `{}` is defined more than once", t.name.name),
912
0
                        ))
913
19.7k
                    }
914
19.7k
                    let mut deps = Vec::new();
915
19.7k
                    collect_deps(&t.ty, &mut deps);
916
19.7k
                    type_deps.insert(t.name.name, deps);
917
                }
918
10.2k
                TypeItem::Use(u) => {
919
11.8k
                    for name in u.names.iter() {
920
11.8k
                        let name = name.as_.as_ref().unwrap_or(&name.name);
921
11.8k
                        type_deps.insert(name.name, Vec::new());
922
11.8k
                        type_defs.insert(name.name, None);
923
11.8k
                    }
924
                }
925
            }
926
        }
927
54.6k
        let order = toposort("type", &type_deps).map_err(attach_old_float_type_context)?;
928
86.2k
        for ty in order {
929
31.5k
            let def = match type_defs.swap_remove(&ty).unwrap() {
930
19.7k
                Some(def) => def,
931
11.8k
                None => continue,
932
            };
933
19.7k
            let docs = self.docs(&def.docs);
934
19.7k
            let stability = self.stability(&def.attributes)?;
935
19.7k
            let kind = self.resolve_type_def(&def.ty, &stability)?;
936
19.7k
            let id = self.types.alloc(TypeDef {
937
19.7k
                docs,
938
19.7k
                stability,
939
19.7k
                kind,
940
19.7k
                name: Some(def.name.name.to_string()),
941
19.7k
                owner,
942
19.7k
            });
943
19.7k
            self.type_spans.push(def.name.span);
944
19.7k
            self.define_interface_name(&def.name, TypeOrItem::Type(id))?;
945
        }
946
54.6k
        return Ok(());
947
948
        fn attach_old_float_type_context(err: ast::toposort::Error) -> anyhow::Error {
949
            let name = match &err {
950
                ast::toposort::Error::NonexistentDep { name, .. } => name,
951
                _ => return err.into(),
952
            };
953
            let new = match name.as_str() {
954
                "float32" => "f32",
955
                "float64" => "f64",
956
                _ => return err.into(),
957
            };
958
959
            let context = format!(
960
                "the `{name}` type has been renamed to `{new}` and is \
961
                 no longer accepted, but the `WIT_REQUIRE_F32_F64=0` \
962
                 environment variable can be used to temporarily \
963
                 disable this error"
964
            );
965
            anyhow::Error::from(err).context(context)
966
        }
967
54.6k
    }
<wit_parser::ast::resolve::Resolver>::resolve_types::<core::iter::adapters::filter_map::FilterMap<core::slice::iter::Iter<wit_parser::ast::WorldItem>, <wit_parser::ast::resolve::Resolver>::resolve_world::{closure#0}>>
Line
Count
Source
878
17.4k
    fn resolve_types<'b>(
879
17.4k
        &mut self,
880
17.4k
        owner: TypeOwner,
881
17.4k
        fields: impl Iterator<Item = TypeItem<'a, 'b>> + Clone,
882
17.4k
    ) -> Result<()>
883
17.4k
    where
884
17.4k
        'a: 'b,
885
    {
886
17.4k
        assert!(self.type_lookup.is_empty());
887
888
        // First, populate our namespace with `use` statements
889
19.2k
        for field in fields.clone() {
890
19.2k
            match field {
891
1.50k
                TypeItem::Use(u) => {
892
1.50k
                    self.resolve_use(owner, u)?;
893
                }
894
17.7k
                TypeItem::Def(_) => {}
895
            }
896
        }
897
898
        // Next determine dependencies between types, perform a topological
899
        // sort, and then define all types. This will define types in a
900
        // topological fashion, forbid cycles, and weed out references to
901
        // undefined types all in one go.
902
17.4k
        let mut type_deps = IndexMap::new();
903
17.4k
        let mut type_defs = IndexMap::new();
904
36.6k
        for field in fields {
905
19.2k
            match field {
906
17.7k
                TypeItem::Def(t) => {
907
17.7k
                    let prev = type_defs.insert(t.name.name, Some(t));
908
17.7k
                    if prev.is_some() {
909
0
                        bail!(Error::new(
910
0
                            t.name.span,
911
0
                            format!("name `{}` is defined more than once", t.name.name),
912
0
                        ))
913
17.7k
                    }
914
17.7k
                    let mut deps = Vec::new();
915
17.7k
                    collect_deps(&t.ty, &mut deps);
916
17.7k
                    type_deps.insert(t.name.name, deps);
917
                }
918
1.50k
                TypeItem::Use(u) => {
919
1.92k
                    for name in u.names.iter() {
920
1.92k
                        let name = name.as_.as_ref().unwrap_or(&name.name);
921
1.92k
                        type_deps.insert(name.name, Vec::new());
922
1.92k
                        type_defs.insert(name.name, None);
923
1.92k
                    }
924
                }
925
            }
926
        }
927
17.4k
        let order = toposort("type", &type_deps).map_err(attach_old_float_type_context)?;
928
37.1k
        for ty in order {
929
19.6k
            let def = match type_defs.swap_remove(&ty).unwrap() {
930
17.7k
                Some(def) => def,
931
1.92k
                None => continue,
932
            };
933
17.7k
            let docs = self.docs(&def.docs);
934
17.7k
            let stability = self.stability(&def.attributes)?;
935
17.7k
            let kind = self.resolve_type_def(&def.ty, &stability)?;
936
17.7k
            let id = self.types.alloc(TypeDef {
937
17.7k
                docs,
938
17.7k
                stability,
939
17.7k
                kind,
940
17.7k
                name: Some(def.name.name.to_string()),
941
17.7k
                owner,
942
17.7k
            });
943
17.7k
            self.type_spans.push(def.name.span);
944
17.7k
            self.define_interface_name(&def.name, TypeOrItem::Type(id))?;
945
        }
946
17.4k
        return Ok(());
947
948
        fn attach_old_float_type_context(err: ast::toposort::Error) -> anyhow::Error {
949
            let name = match &err {
950
                ast::toposort::Error::NonexistentDep { name, .. } => name,
951
                _ => return err.into(),
952
            };
953
            let new = match name.as_str() {
954
                "float32" => "f32",
955
                "float64" => "f64",
956
                _ => return err.into(),
957
            };
958
959
            let context = format!(
960
                "the `{name}` type has been renamed to `{new}` and is \
961
                 no longer accepted, but the `WIT_REQUIRE_F32_F64=0` \
962
                 environment variable can be used to temporarily \
963
                 disable this error"
964
            );
965
            anyhow::Error::from(err).context(context)
966
        }
967
17.4k
    }
968
969
11.7k
    fn resolve_use(&mut self, owner: TypeOwner, u: &ast::Use<'a>) -> Result<()> {
970
11.7k
        let (item, name, span) = self.resolve_ast_item_path(&u.from)?;
971
11.7k
        let use_from = self.extract_iface_from_item(&item, &name, span)?;
972
11.7k
        let stability = self.stability(&u.attributes)?;
973
974
13.7k
        for name in u.names.iter() {
975
13.7k
            let lookup = &self.interface_types[use_from.index()];
976
13.7k
            let id = match lookup.get(name.name.name) {
977
13.7k
                Some((TypeOrItem::Type(id), _)) => *id,
978
0
                Some((TypeOrItem::Item(s), _)) => {
979
0
                    bail!(Error::new(
980
0
                        name.name.span,
981
0
                        format!("cannot import {s} `{}`", name.name.name),
982
0
                    ))
983
                }
984
0
                None => bail!(Error::new(
985
0
                    name.name.span,
986
0
                    format!("name `{}` is not defined", name.name.name),
987
0
                )),
988
            };
989
13.7k
            self.type_spans.push(name.name.span);
990
13.7k
            let name = name.as_.as_ref().unwrap_or(&name.name);
991
13.7k
            let id = self.types.alloc(TypeDef {
992
13.7k
                docs: Docs::default(),
993
13.7k
                stability: stability.clone(),
994
13.7k
                kind: TypeDefKind::Type(Type::Id(id)),
995
13.7k
                name: Some(name.name.to_string()),
996
13.7k
                owner,
997
13.7k
            });
998
13.7k
            self.define_interface_name(name, TypeOrItem::Type(id))?;
999
        }
1000
11.7k
        Ok(())
1001
11.7k
    }
1002
1003
    /// For each name in the `include`, resolve the path of the include, add it to the self.includes
1004
0
    fn resolve_include(&mut self, world_id: WorldId, i: &ast::Include<'a>) -> Result<()> {
1005
0
        let stability = self.stability(&i.attributes)?;
1006
0
        let (item, name, span) = self.resolve_ast_item_path(&i.from)?;
1007
0
        let include_from = self.extract_world_from_item(&item, &name, span)?;
1008
0
        self.worlds[world_id]
1009
0
            .includes
1010
0
            .push((stability, include_from));
1011
0
        self.worlds[world_id].include_names.push(
1012
0
            i.names
1013
0
                .iter()
1014
0
                .map(|n| IncludeName {
1015
0
                    name: n.name.name.to_string(),
1016
0
                    as_: n.as_.name.to_string(),
1017
0
                })
1018
0
                .collect(),
1019
        );
1020
0
        self.world_spans[world_id.index()].includes.push(span);
1021
0
        Ok(())
1022
0
    }
1023
1024
4.16k
    fn resolve_resource_func(
1025
4.16k
        &mut self,
1026
4.16k
        func: &ast::ResourceFunc<'_>,
1027
4.16k
        resource: &ast::Id<'_>,
1028
4.16k
    ) -> Result<Function> {
1029
4.16k
        let resource_id = match self.type_lookup.get(resource.name) {
1030
4.16k
            Some((TypeOrItem::Type(id), _)) => *id,
1031
0
            _ => panic!("type lookup for resource failed"),
1032
        };
1033
        let (name, kind);
1034
4.16k
        let named_func = func.named_func();
1035
4.16k
        let async_ = named_func.func.async_;
1036
4.16k
        match func {
1037
2.20k
            ast::ResourceFunc::Method(f) => {
1038
2.20k
                name = format!("[method]{}.{}", resource.name, f.name.name);
1039
2.20k
                kind = if async_ {
1040
1.57k
                    FunctionKind::AsyncMethod(resource_id)
1041
                } else {
1042
625
                    FunctionKind::Method(resource_id)
1043
                };
1044
            }
1045
1.43k
            ast::ResourceFunc::Static(f) => {
1046
1.43k
                name = format!("[static]{}.{}", resource.name, f.name.name);
1047
1.43k
                kind = if async_ {
1048
887
                    FunctionKind::AsyncStatic(resource_id)
1049
                } else {
1050
543
                    FunctionKind::Static(resource_id)
1051
                };
1052
            }
1053
            ast::ResourceFunc::Constructor(_) => {
1054
530
                assert!(!async_); // should not be possible to parse
1055
530
                name = format!("[constructor]{}", resource.name);
1056
530
                kind = FunctionKind::Constructor(resource_id);
1057
            }
1058
        }
1059
4.16k
        self.resolve_function(
1060
4.16k
            &named_func.docs,
1061
4.16k
            &named_func.attributes,
1062
4.16k
            &name,
1063
4.16k
            &named_func.func,
1064
4.16k
            kind,
1065
        )
1066
4.16k
    }
1067
1068
23.5k
    fn resolve_function(
1069
23.5k
        &mut self,
1070
23.5k
        docs: &ast::Docs<'_>,
1071
23.5k
        attrs: &[ast::Attribute<'_>],
1072
23.5k
        name: &str,
1073
23.5k
        func: &ast::Func,
1074
23.5k
        kind: FunctionKind,
1075
23.5k
    ) -> Result<Function> {
1076
23.5k
        let docs = self.docs(docs);
1077
23.5k
        let stability = self.stability(attrs)?;
1078
23.5k
        let params = self.resolve_params(&func.params, &kind, func.span)?;
1079
23.5k
        let result = self.resolve_result(&func.result, &kind, func.span)?;
1080
23.5k
        Ok(Function {
1081
23.5k
            docs,
1082
23.5k
            stability,
1083
23.5k
            name: name.to_string(),
1084
23.5k
            kind,
1085
23.5k
            params,
1086
23.5k
            result,
1087
23.5k
        })
1088
23.5k
    }
1089
1090
25.7k
    fn resolve_ast_item_path(&self, path: &ast::UsePath<'a>) -> Result<(AstItem, String, Span)> {
1091
25.7k
        match path {
1092
9.77k
            ast::UsePath::Id(id) => {
1093
9.77k
                let item = self.ast_items[self.cur_ast_index]
1094
9.77k
                    .get(id.name)
1095
9.77k
                    .or_else(|| self.package_items.get(id.name));
1096
9.77k
                match item {
1097
9.77k
                    Some(item) => Ok((*item, id.name.into(), id.span)),
1098
                    None => {
1099
0
                        bail!(Error::new(
1100
0
                            id.span,
1101
0
                            format!("interface or world `{}` does not exist", id.name),
1102
0
                        ))
1103
                    }
1104
                }
1105
            }
1106
15.9k
            ast::UsePath::Package { id, name } => Ok((
1107
15.9k
                self.foreign_deps[&id.package_name()][name.name],
1108
15.9k
                name.name.into(),
1109
15.9k
                name.span,
1110
15.9k
            )),
1111
        }
1112
25.7k
    }
1113
1114
25.7k
    fn extract_iface_from_item(
1115
25.7k
        &self,
1116
25.7k
        item: &AstItem,
1117
25.7k
        name: &str,
1118
25.7k
        span: Span,
1119
25.7k
    ) -> Result<InterfaceId> {
1120
25.7k
        match item {
1121
25.7k
            AstItem::Interface(id) => Ok(*id),
1122
            AstItem::World(_) => {
1123
0
                bail!(Error::new(
1124
0
                    span,
1125
0
                    format!("name `{name}` is defined as a world, not an interface"),
1126
0
                ))
1127
            }
1128
        }
1129
25.7k
    }
1130
1131
0
    fn extract_world_from_item(&self, item: &AstItem, name: &str, span: Span) -> Result<WorldId> {
1132
0
        match item {
1133
0
            AstItem::World(id) => Ok(*id),
1134
            AstItem::Interface(_) => {
1135
0
                bail!(Error::new(
1136
0
                    span,
1137
0
                    format!("name `{name}` is defined as an interface, not a world"),
1138
0
                ))
1139
            }
1140
        }
1141
0
    }
1142
1143
66.9k
    fn define_interface_name(&mut self, name: &ast::Id<'a>, item: TypeOrItem) -> Result<()> {
1144
66.9k
        let prev = self.type_lookup.insert(name.name, (item, name.span));
1145
66.9k
        if prev.is_some() {
1146
0
            bail!(Error::new(
1147
0
                name.span,
1148
0
                format!("name `{}` is defined more than once", name.name),
1149
0
            ))
1150
        } else {
1151
66.9k
            Ok(())
1152
        }
1153
66.9k
    }
1154
1155
419k
    fn resolve_type_def(
1156
419k
        &mut self,
1157
419k
        ty: &ast::Type<'_>,
1158
419k
        stability: &Stability,
1159
419k
    ) -> Result<TypeDefKind> {
1160
419k
        Ok(match ty {
1161
96.9k
            ast::Type::Bool(_) => TypeDefKind::Type(Type::Bool),
1162
6.39k
            ast::Type::U8(_) => TypeDefKind::Type(Type::U8),
1163
1.94k
            ast::Type::U16(_) => TypeDefKind::Type(Type::U16),
1164
3.44k
            ast::Type::U32(_) => TypeDefKind::Type(Type::U32),
1165
2.88k
            ast::Type::U64(_) => TypeDefKind::Type(Type::U64),
1166
3.07k
            ast::Type::S8(_) => TypeDefKind::Type(Type::S8),
1167
1.54k
            ast::Type::S16(_) => TypeDefKind::Type(Type::S16),
1168
2.47k
            ast::Type::S32(_) => TypeDefKind::Type(Type::S32),
1169
11.4k
            ast::Type::S64(_) => TypeDefKind::Type(Type::S64),
1170
5.17k
            ast::Type::F32(_) => TypeDefKind::Type(Type::F32),
1171
8.18k
            ast::Type::F64(_) => TypeDefKind::Type(Type::F64),
1172
9.99k
            ast::Type::Char(_) => TypeDefKind::Type(Type::Char),
1173
2.32k
            ast::Type::String(_) => TypeDefKind::Type(Type::String),
1174
18.4k
            ast::Type::ErrorContext(_) => TypeDefKind::Type(Type::ErrorContext),
1175
2.36k
            ast::Type::Name(name) => {
1176
2.36k
                let id = self.resolve_type_name(name)?;
1177
2.36k
                TypeDefKind::Type(Type::Id(id))
1178
            }
1179
6.24k
            ast::Type::List(list) => {
1180
6.24k
                let ty = self.resolve_type(&list.ty, stability)?;
1181
6.24k
                TypeDefKind::List(ty)
1182
            }
1183
106k
            ast::Type::FixedSizeList(list) => {
1184
106k
                let ty = self.resolve_type(&list.ty, stability)?;
1185
106k
                TypeDefKind::FixedSizeList(ty, list.size)
1186
            }
1187
354
            ast::Type::Handle(handle) => TypeDefKind::Handle(match handle {
1188
354
                ast::Handle::Own { resource } => Handle::Own(self.validate_resource(resource)?),
1189
0
                ast::Handle::Borrow { resource } => {
1190
0
                    Handle::Borrow(self.validate_resource(resource)?)
1191
                }
1192
            }),
1193
2.48k
            ast::Type::Resource(resource) => {
1194
                // Validate here that the resource doesn't have any duplicate-ly
1195
                // named methods and that there's at most one constructor.
1196
2.48k
                let mut ctors = 0;
1197
2.48k
                let mut names = HashSet::new();
1198
4.16k
                for func in resource.funcs.iter() {
1199
4.16k
                    match func {
1200
2.20k
                        ast::ResourceFunc::Method(f) | ast::ResourceFunc::Static(f) => {
1201
3.63k
                            if !names.insert(&f.name.name) {
1202
0
                                bail!(Error::new(
1203
0
                                    f.name.span,
1204
0
                                    format!("duplicate function name `{}`", f.name.name),
1205
0
                                ))
1206
3.63k
                            }
1207
                        }
1208
530
                        ast::ResourceFunc::Constructor(f) => {
1209
530
                            ctors += 1;
1210
530
                            if ctors > 1 {
1211
0
                                bail!(Error::new(f.name.span, "duplicate constructors"))
1212
530
                            }
1213
                        }
1214
                    }
1215
                }
1216
1217
2.48k
                TypeDefKind::Resource
1218
            }
1219
4.13k
            ast::Type::Record(record) => {
1220
4.13k
                let fields = record
1221
4.13k
                    .fields
1222
4.13k
                    .iter()
1223
11.3k
                    .map(|field| {
1224
                        Ok(Field {
1225
11.3k
                            docs: self.docs(&field.docs),
1226
11.3k
                            name: field.name.name.to_string(),
1227
11.3k
                            ty: self.resolve_type(&field.ty, stability)?,
1228
                        })
1229
11.3k
                    })
1230
4.13k
                    .collect::<Result<Vec<_>>>()?;
1231
4.13k
                TypeDefKind::Record(Record { fields })
1232
            }
1233
1.25k
            ast::Type::Flags(flags) => {
1234
1.25k
                let flags = flags
1235
1.25k
                    .flags
1236
1.25k
                    .iter()
1237
1.25k
                    .map(|flag| Flag {
1238
3.86k
                        docs: self.docs(&flag.docs),
1239
3.86k
                        name: flag.name.name.to_string(),
1240
3.86k
                    })
1241
1.25k
                    .collect::<Vec<_>>();
1242
1.25k
                TypeDefKind::Flags(Flags { flags })
1243
            }
1244
22.3k
            ast::Type::Tuple(t) => {
1245
22.3k
                let types = t
1246
22.3k
                    .types
1247
22.3k
                    .iter()
1248
80.1k
                    .map(|ty| self.resolve_type(ty, stability))
1249
22.3k
                    .collect::<Result<Vec<_>>>()?;
1250
22.3k
                TypeDefKind::Tuple(Tuple { types })
1251
            }
1252
5.84k
            ast::Type::Variant(variant) => {
1253
5.84k
                if variant.cases.is_empty() {
1254
0
                    bail!(Error::new(variant.span, "empty variant"))
1255
5.84k
                }
1256
5.84k
                let cases = variant
1257
5.84k
                    .cases
1258
5.84k
                    .iter()
1259
20.2k
                    .map(|case| {
1260
                        Ok(Case {
1261
20.2k
                            docs: self.docs(&case.docs),
1262
20.2k
                            name: case.name.name.to_string(),
1263
20.2k
                            ty: self.resolve_optional_type(case.ty.as_ref(), stability)?,
1264
                        })
1265
20.2k
                    })
1266
5.84k
                    .collect::<Result<Vec<_>>>()?;
1267
5.84k
                TypeDefKind::Variant(Variant { cases })
1268
            }
1269
21.8k
            ast::Type::Enum(e) => {
1270
21.8k
                if e.cases.is_empty() {
1271
0
                    bail!(Error::new(e.span, "empty enum"))
1272
21.8k
                }
1273
21.8k
                let cases = e
1274
21.8k
                    .cases
1275
21.8k
                    .iter()
1276
100k
                    .map(|case| {
1277
100k
                        Ok(EnumCase {
1278
100k
                            docs: self.docs(&case.docs),
1279
100k
                            name: case.name.name.to_string(),
1280
100k
                        })
1281
100k
                    })
1282
21.8k
                    .collect::<Result<Vec<_>>>()?;
1283
21.8k
                TypeDefKind::Enum(Enum { cases })
1284
            }
1285
28.5k
            ast::Type::Option(ty) => TypeDefKind::Option(self.resolve_type(&ty.ty, stability)?),
1286
30.0k
            ast::Type::Result(r) => TypeDefKind::Result(Result_ {
1287
30.0k
                ok: self.resolve_optional_type(r.ok.as_deref(), stability)?,
1288
30.0k
                err: self.resolve_optional_type(r.err.as_deref(), stability)?,
1289
            }),
1290
7.83k
            ast::Type::Future(t) => {
1291
7.83k
                TypeDefKind::Future(self.resolve_optional_type(t.ty.as_deref(), stability)?)
1292
            }
1293
5.00k
            ast::Type::Stream(s) => {
1294
5.00k
                TypeDefKind::Stream(self.resolve_optional_type(s.ty.as_deref(), stability)?)
1295
            }
1296
        })
1297
419k
    }
1298
1299
2.71k
    fn resolve_type_name(&mut self, name: &ast::Id<'_>) -> Result<TypeId> {
1300
2.71k
        match self.type_lookup.get(name.name) {
1301
2.71k
            Some((TypeOrItem::Type(id), _)) => Ok(*id),
1302
0
            Some((TypeOrItem::Item(s), _)) => bail!(Error::new(
1303
0
                name.span,
1304
0
                format!("cannot use {s} `{name}` as a type", name = name.name),
1305
0
            )),
1306
0
            None => bail!(Error::new(
1307
0
                name.span,
1308
0
                format!("name `{name}` is not defined", name = name.name),
1309
0
            )),
1310
        }
1311
2.71k
    }
1312
1313
354
    fn validate_resource(&mut self, name: &ast::Id<'_>) -> Result<TypeId> {
1314
354
        let id = self.resolve_type_name(name)?;
1315
354
        let mut cur = id;
1316
        loop {
1317
378
            match self.types[cur].kind {
1318
338
                TypeDefKind::Resource => break Ok(id),
1319
24
                TypeDefKind::Type(Type::Id(ty)) => cur = ty,
1320
                TypeDefKind::Unknown => {
1321
16
                    self.required_resource_types.push((cur, name.span));
1322
16
                    break Ok(id);
1323
                }
1324
0
                _ => bail!(Error::new(
1325
0
                    name.span,
1326
0
                    format!("type `{}` used in a handle must be a resource", name.name),
1327
0
                )),
1328
            }
1329
        }
1330
354
    }
1331
1332
    /// If `stability` is `Stability::Unknown`, recursively inspect the
1333
    /// specified `kind` until we either bottom out or find a type which has a
1334
    /// stability that's _not_ unknown.  If we find such a type, return a clone
1335
    /// of its stability; otherwise return `Stability::Unknown`.
1336
    ///
1337
    /// The idea here is that e.g. `option<T>` should inherit `T`'s stability.
1338
    /// This gets a little ambiguous in the case of e.g. `tuple<T, U, V>`; for
1339
    /// now, we just pick the first one has a known stability, if any.
1340
384k
    fn find_stability(&self, kind: &TypeDefKind, stability: &Stability) -> Stability {
1341
458k
        fn find_in_type(types: &Arena<TypeDef>, ty: Type) -> Option<&Stability> {
1342
458k
            if let Type::Id(id) = ty {
1343
200k
                let ty = &types[id];
1344
200k
                if !matches!(&ty.stability, Stability::Unknown) {
1345
372
                    Some(&ty.stability)
1346
                } else {
1347
                    // Note that this type isn't searched recursively since the
1348
                    // creation of `id` should already have searched its
1349
                    // recursive edges, so there's no need to search again.
1350
199k
                    None
1351
                }
1352
            } else {
1353
258k
                None
1354
            }
1355
458k
        }
1356
1357
382k
        fn find_in_kind<'a>(
1358
382k
            types: &'a Arena<TypeDef>,
1359
382k
            kind: &TypeDefKind,
1360
382k
        ) -> Option<&'a Stability> {
1361
2.54k
            match kind {
1362
174k
                TypeDefKind::Type(ty) => find_in_type(types, *ty),
1363
2.20k
                TypeDefKind::Handle(Handle::Borrow(id) | Handle::Own(id)) => {
1364
2.54k
                    find_in_type(types, Type::Id(*id))
1365
                }
1366
79.1k
                TypeDefKind::Tuple(t) => t.types.iter().find_map(|ty| find_in_type(types, *ty)),
1367
6.18k
                TypeDefKind::List(ty)
1368
106k
                | TypeDefKind::FixedSizeList(ty, _)
1369
141k
                | TypeDefKind::Option(ty) => find_in_type(types, *ty),
1370
7.79k
                TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
1371
12.7k
                    ty.as_ref().and_then(|ty| find_in_type(types, *ty))
1372
                }
1373
29.5k
                TypeDefKind::Result(r) => {
1374
29.5k
                    r.ok.as_ref()
1375
29.5k
                        .and_then(|ty| find_in_type(types, *ty))
1376
29.5k
                        .or_else(|| r.err.as_ref().and_then(|ty| find_in_type(types, *ty)))
1377
                }
1378
                // Assume these are named types which will be annotated with an
1379
                // explicit stability if applicable:
1380
                TypeDefKind::Resource
1381
                | TypeDefKind::Variant(_)
1382
                | TypeDefKind::Record(_)
1383
                | TypeDefKind::Flags(_)
1384
                | TypeDefKind::Enum(_)
1385
0
                | TypeDefKind::Unknown => None,
1386
            }
1387
382k
        }
1388
1389
384k
        if let Stability::Unknown = stability {
1390
382k
            find_in_kind(&self.types, kind)
1391
382k
                .cloned()
1392
382k
                .unwrap_or(Stability::Unknown)
1393
        } else {
1394
1.76k
            stability.clone()
1395
        }
1396
384k
    }
1397
1398
382k
    fn resolve_type(&mut self, ty: &super::Type<'_>, stability: &Stability) -> Result<Type> {
1399
        // Resources must be declared at the top level to have their methods
1400
        // processed appropriately, but resources also shouldn't show up
1401
        // recursively so assert that's not happening here.
1402
382k
        match ty {
1403
0
            ast::Type::Resource(_) => unreachable!(),
1404
382k
            _ => {}
1405
        }
1406
382k
        let kind = self.resolve_type_def(ty, stability)?;
1407
382k
        let stability = self.find_stability(&kind, stability);
1408
382k
        Ok(self.anon_type_def(
1409
382k
            TypeDef {
1410
382k
                kind,
1411
382k
                name: None,
1412
382k
                docs: Docs::default(),
1413
382k
                stability,
1414
382k
                owner: TypeOwner::None,
1415
382k
            },
1416
382k
            ty.span(),
1417
382k
        ))
1418
382k
    }
1419
1420
93.2k
    fn resolve_optional_type(
1421
93.2k
        &mut self,
1422
93.2k
        ty: Option<&super::Type<'_>>,
1423
93.2k
        stability: &Stability,
1424
93.2k
    ) -> Result<Option<Type>> {
1425
93.2k
        match ty {
1426
79.6k
            Some(ty) => Ok(Some(self.resolve_type(ty, stability)?)),
1427
13.6k
            None => Ok(None),
1428
        }
1429
93.2k
    }
1430
1431
384k
    fn anon_type_def(&mut self, ty: TypeDef, span: Span) -> Type {
1432
208k
        let key = match &ty.kind {
1433
175k
            TypeDefKind::Type(t) => return *t,
1434
0
            TypeDefKind::Variant(v) => Key::Variant(
1435
0
                v.cases
1436
0
                    .iter()
1437
0
                    .map(|case| (case.name.clone(), case.ty))
1438
0
                    .collect::<Vec<_>>(),
1439
            ),
1440
2.20k
            TypeDefKind::Handle(Handle::Borrow(h)) => Key::BorrowHandle(*h),
1441
            // An anonymous `own<T>` type is the same as a reference to the type
1442
            // `T`, so avoid creating anonymous type and return that here
1443
            // directly. Note that this additionally avoids creating distinct
1444
            // anonymous types for `list<T>` and `list<own<T>>` for example.
1445
346
            TypeDefKind::Handle(Handle::Own(id)) => return Type::Id(*id),
1446
0
            TypeDefKind::Resource => unreachable!("anonymous resources aren't supported"),
1447
0
            TypeDefKind::Record(r) => Key::Record(
1448
0
                r.fields
1449
0
                    .iter()
1450
0
                    .map(|case| (case.name.clone(), case.ty))
1451
0
                    .collect::<Vec<_>>(),
1452
            ),
1453
0
            TypeDefKind::Flags(r) => {
1454
0
                Key::Flags(r.flags.iter().map(|f| f.name.clone()).collect::<Vec<_>>())
1455
            }
1456
22.2k
            TypeDefKind::Tuple(t) => Key::Tuple(t.types.clone()),
1457
0
            TypeDefKind::Enum(r) => {
1458
0
                Key::Enum(r.cases.iter().map(|f| f.name.clone()).collect::<Vec<_>>())
1459
            }
1460
6.19k
            TypeDefKind::List(ty) => Key::List(*ty),
1461
106k
            TypeDefKind::FixedSizeList(ty, size) => Key::FixedSizeList(*ty, *size),
1462
28.4k
            TypeDefKind::Option(t) => Key::Option(*t),
1463
29.7k
            TypeDefKind::Result(r) => Key::Result(r.ok, r.err),
1464
7.81k
            TypeDefKind::Future(ty) => Key::Future(*ty),
1465
4.99k
            TypeDefKind::Stream(ty) => Key::Stream(*ty),
1466
0
            TypeDefKind::Unknown => unreachable!(),
1467
        };
1468
208k
        let id = self.anon_types.entry(key).or_insert_with(|| {
1469
89.9k
            self.type_spans.push(span);
1470
89.9k
            self.types.alloc(ty)
1471
89.9k
        });
1472
208k
        Type::Id(*id)
1473
384k
    }
1474
1475
285k
    fn docs(&mut self, doc: &super::Docs<'_>) -> Docs {
1476
285k
        let mut docs = vec![];
1477
1478
285k
        for doc in doc.docs.iter() {
1479
0
            let contents = match doc.strip_prefix("/**") {
1480
0
                Some(doc) => doc.strip_suffix("*/").unwrap(),
1481
0
                None => doc.trim_start_matches('/'),
1482
            };
1483
1484
0
            docs.push(contents.trim_end());
1485
        }
1486
1487
        // Scan the (non-empty) doc lines to find the minimum amount of leading whitespace.
1488
        // This amount of whitespace will be removed from the start of all doc lines,
1489
        // normalizing the output while retaining intentional spacing added by the original authors.
1490
285k
        let min_leading_ws = docs
1491
285k
            .iter()
1492
285k
            .filter(|doc| !doc.is_empty())
1493
285k
            .map(|doc| doc.bytes().take_while(|c| c.is_ascii_whitespace()).count())
1494
285k
            .min()
1495
285k
            .unwrap_or(0);
1496
1497
285k
        if min_leading_ws > 0 {
1498
0
            let leading_ws_pattern = " ".repeat(min_leading_ws);
1499
0
            docs = docs
1500
0
                .iter()
1501
0
                .map(|doc| doc.strip_prefix(&leading_ws_pattern).unwrap_or(doc))
1502
0
                .collect();
1503
285k
        }
1504
1505
285k
        let contents = if docs.is_empty() {
1506
285k
            None
1507
        } else {
1508
            // NB: this notably, through the use of `lines`, normalizes `\r\n`
1509
            // to `\n`.
1510
0
            let mut contents = String::new();
1511
0
            for doc in docs {
1512
0
                if doc.is_empty() {
1513
0
                    contents.push_str("\n");
1514
0
                } else {
1515
0
                    for line in doc.lines() {
1516
0
                        contents.push_str(line);
1517
0
                        contents.push_str("\n");
1518
0
                    }
1519
                }
1520
            }
1521
0
            while contents.ends_with("\n") {
1522
0
                contents.pop();
1523
0
            }
1524
0
            Some(contents)
1525
        };
1526
285k
        Docs { contents }
1527
285k
    }
1528
1529
157k
    fn stability(&mut self, attrs: &[ast::Attribute<'_>]) -> Result<Stability> {
1530
540
        match attrs {
1531
157k
            [] => Ok(Stability::Unknown),
1532
1533
2.36k
            [ast::Attribute::Since { version, .. }] => Ok(Stability::Stable {
1534
2.36k
                since: version.clone(),
1535
2.36k
                deprecated: None,
1536
2.36k
            }),
1537
1538
            [
1539
540
                ast::Attribute::Since { version, .. },
1540
                ast::Attribute::Deprecated {
1541
540
                    version: deprecated,
1542
                    ..
1543
                },
1544
            ]
1545
            | [
1546
                ast::Attribute::Deprecated {
1547
515
                    version: deprecated,
1548
                    ..
1549
                },
1550
515
                ast::Attribute::Since { version, .. },
1551
1.05k
            ] => Ok(Stability::Stable {
1552
1.05k
                since: version.clone(),
1553
1.05k
                deprecated: Some(deprecated.clone()),
1554
1.05k
            }),
1555
1556
1.06k
            [ast::Attribute::Unstable { feature, .. }] => Ok(Stability::Unstable {
1557
1.06k
                feature: feature.name.to_string(),
1558
1.06k
                deprecated: None,
1559
1.06k
            }),
1560
1561
            [
1562
0
                ast::Attribute::Unstable { feature, .. },
1563
0
                ast::Attribute::Deprecated { version, .. },
1564
            ]
1565
            | [
1566
0
                ast::Attribute::Deprecated { version, .. },
1567
0
                ast::Attribute::Unstable { feature, .. },
1568
0
            ] => Ok(Stability::Unstable {
1569
0
                feature: feature.name.to_string(),
1570
0
                deprecated: Some(version.clone()),
1571
0
            }),
1572
0
            [ast::Attribute::Deprecated { span, .. }] => {
1573
0
                bail!(Error::new(
1574
0
                    *span,
1575
0
                    "must pair @deprecated with either @since or @unstable",
1576
0
                ))
1577
            }
1578
0
            [_, b, ..] => {
1579
0
                bail!(Error::new(
1580
0
                    b.span(),
1581
0
                    "unsupported combination of attributes",
1582
0
                ))
1583
            }
1584
        }
1585
157k
    }
1586
1587
23.5k
    fn resolve_params(
1588
23.5k
        &mut self,
1589
23.5k
        params: &ParamList<'_>,
1590
23.5k
        kind: &FunctionKind,
1591
23.5k
        span: Span,
1592
23.5k
    ) -> Result<Vec<(String, Type)>> {
1593
23.5k
        let mut ret = IndexMap::new();
1594
23.5k
        match *kind {
1595
            // These kinds of methods don't have any adjustments to the
1596
            // parameters, so do nothing here.
1597
            FunctionKind::Freestanding
1598
            | FunctionKind::AsyncFreestanding
1599
            | FunctionKind::Constructor(_)
1600
            | FunctionKind::Static(_)
1601
21.3k
            | FunctionKind::AsyncStatic(_) => {}
1602
1603
            // Methods automatically get a `self` initial argument so insert
1604
            // that here before processing the normal parameters.
1605
2.20k
            FunctionKind::Method(id) | FunctionKind::AsyncMethod(id) => {
1606
2.20k
                let kind = TypeDefKind::Handle(Handle::Borrow(id));
1607
2.20k
                let stability = self.find_stability(&kind, &Stability::Unknown);
1608
2.20k
                let shared = self.anon_type_def(
1609
2.20k
                    TypeDef {
1610
2.20k
                        docs: Docs::default(),
1611
2.20k
                        stability,
1612
2.20k
                        kind,
1613
2.20k
                        name: None,
1614
2.20k
                        owner: TypeOwner::None,
1615
2.20k
                    },
1616
2.20k
                    span,
1617
2.20k
                );
1618
2.20k
                ret.insert("self".to_string(), shared);
1619
2.20k
            }
1620
        }
1621
76.1k
        for (name, ty) in params {
1622
52.6k
            let prev = ret.insert(
1623
52.6k
                name.name.to_string(),
1624
52.6k
                self.resolve_type(ty, &Stability::Unknown)?,
1625
            );
1626
52.6k
            if prev.is_some() {
1627
0
                bail!(Error::new(
1628
0
                    name.span,
1629
0
                    format!("param `{}` is defined more than once", name.name),
1630
0
                ))
1631
52.6k
            }
1632
        }
1633
23.5k
        Ok(ret.into_iter().collect())
1634
23.5k
    }
1635
1636
23.5k
    fn resolve_result(
1637
23.5k
        &mut self,
1638
23.5k
        result: &Option<ast::Type<'_>>,
1639
23.5k
        kind: &FunctionKind,
1640
23.5k
        _span: Span,
1641
23.5k
    ) -> Result<Option<Type>> {
1642
23.5k
        match *kind {
1643
            // These kinds of methods don't have any adjustments to the return
1644
            // values, so plumb them through as-is.
1645
            FunctionKind::Freestanding
1646
            | FunctionKind::AsyncFreestanding
1647
            | FunctionKind::Method(_)
1648
            | FunctionKind::AsyncMethod(_)
1649
            | FunctionKind::Static(_)
1650
22.9k
            | FunctionKind::AsyncStatic(_) => match result {
1651
16.7k
                Some(ty) => Ok(Some(self.resolve_type(ty, &Stability::Unknown)?)),
1652
6.25k
                None => Ok(None),
1653
            },
1654
1655
530
            FunctionKind::Constructor(id) => match result {
1656
                // When constructors don't define a return type, they're
1657
                // implicitly assumed to return an owned handle to the type
1658
                // they construct.
1659
530
                None => Ok(Some(Type::Id(id))),
1660
1661
                // If a constructor does define a return type, it must be in the
1662
                // form of `-> result<R, E?>` where `R` is the resource being
1663
                // constructed and `E` is an optional error type.
1664
0
                Some(ty) => Ok(Some(self.resolve_constructor_result(id, ty)?)),
1665
            },
1666
        }
1667
23.5k
    }
1668
1669
0
    fn resolve_constructor_result(
1670
0
        &mut self,
1671
0
        resource_id: TypeId,
1672
0
        result_ast: &ast::Type<'_>,
1673
0
    ) -> Result<Type> {
1674
0
        let result = self.resolve_type(result_ast, &Stability::Unknown)?;
1675
0
        let ok_type = match result {
1676
0
            Type::Id(id) => match &self.types[id].kind {
1677
0
                TypeDefKind::Result(r) => Some(r.ok),
1678
0
                _ => None,
1679
            },
1680
0
            _ => None,
1681
        };
1682
0
        let Some(ok_type) = ok_type else {
1683
0
            bail!(Error::new(
1684
0
                result_ast.span(),
1685
0
                "if a constructor return type is declared it must be a `result`",
1686
0
            ));
1687
        };
1688
0
        match ok_type {
1689
0
            Some(Type::Id(ok_id)) if resource_id == ok_id => Ok(result),
1690
            _ => {
1691
0
                let ok_span =
1692
0
                    if let ast::Type::Result(ast::Result_ { ok: Some(ok), .. }) = result_ast {
1693
0
                        ok.span()
1694
                    } else {
1695
0
                        result_ast.span()
1696
                    };
1697
0
                bail!(Error::new(
1698
0
                    ok_span,
1699
0
                    "the `ok` type must be the resource being constructed",
1700
0
                ));
1701
            }
1702
        }
1703
0
    }
1704
}
1705
1706
103k
fn collect_deps<'a>(ty: &ast::Type<'a>, deps: &mut Vec<ast::Id<'a>>) {
1707
103k
    match ty {
1708
        ast::Type::Bool(_)
1709
        | ast::Type::U8(_)
1710
        | ast::Type::U16(_)
1711
        | ast::Type::U32(_)
1712
        | ast::Type::U64(_)
1713
        | ast::Type::S8(_)
1714
        | ast::Type::S16(_)
1715
        | ast::Type::S32(_)
1716
        | ast::Type::S64(_)
1717
        | ast::Type::F32(_)
1718
        | ast::Type::F64(_)
1719
        | ast::Type::Char(_)
1720
        | ast::Type::String(_)
1721
        | ast::Type::Flags(_)
1722
        | ast::Type::Enum(_)
1723
73.1k
        | ast::Type::ErrorContext(_) => {}
1724
1.22k
        ast::Type::Name(name) => deps.push(name.clone()),
1725
20
        ast::Type::Handle(handle) => match handle {
1726
20
            ast::Handle::Own { resource } => deps.push(resource.clone()),
1727
0
            ast::Handle::Borrow { resource } => deps.push(resource.clone()),
1728
        },
1729
2.48k
        ast::Type::Resource(_) => {}
1730
4.13k
        ast::Type::Record(record) => {
1731
11.3k
            for field in record.fields.iter() {
1732
11.3k
                collect_deps(&field.ty, deps);
1733
11.3k
            }
1734
        }
1735
5.75k
        ast::Type::Tuple(t) => {
1736
24.2k
            for ty in t.types.iter() {
1737
24.2k
                collect_deps(ty, deps);
1738
24.2k
            }
1739
        }
1740
5.84k
        ast::Type::Variant(variant) => {
1741
20.2k
            for case in variant.cases.iter() {
1742
20.2k
                if let Some(ty) = &case.ty {
1743
17.2k
                    collect_deps(ty, deps);
1744
17.2k
                }
1745
            }
1746
        }
1747
5.13k
        ast::Type::Option(ast::Option_ { ty, .. })
1748
532
        | ast::Type::List(ast::List { ty, .. })
1749
5.86k
        | ast::Type::FixedSizeList(ast::FixedSizeList { ty, .. }) => collect_deps(ty, deps),
1750
4.45k
        ast::Type::Result(r) => {
1751
4.45k
            if let Some(ty) = &r.ok {
1752
3.49k
                collect_deps(ty, deps);
1753
3.49k
            }
1754
4.45k
            if let Some(ty) = &r.err {
1755
3.53k
                collect_deps(ty, deps);
1756
3.53k
            }
1757
        }
1758
548
        ast::Type::Future(t) => {
1759
548
            if let Some(t) = &t.ty {
1760
229
                collect_deps(t, deps)
1761
319
            }
1762
        }
1763
345
        ast::Type::Stream(s) => {
1764
345
            if let Some(t) = &s.ty {
1765
345
                collect_deps(t, deps)
1766
0
            }
1767
        }
1768
    }
1769
103k
}