wit_parser/ast/
resolve.rs

1use super::{ParamList, WorldOrInterface};
2use crate::ast::toposort::toposort;
3use crate::*;
4use anyhow::bail;
5use std::collections::{HashMap, HashSet};
6use std::mem;
7
8#[derive(Default)]
9pub 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)]
87enum 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
102enum TypeItem<'a, 'b> {
103    Use(&'b ast::Use<'a>),
104    Def(&'b ast::TypeDef<'a>),
105}
106
107enum TypeOrItem {
108    Type(TypeId),
109    Item(&'static str),
110}
111
112impl<'a> Resolver<'a> {
113    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        if let Some(cur) = &file.package_id {
118            let cur_name = cur.package_name();
119            if let Some((prev, _)) = &self.package_name {
120                if cur_name != *prev {
121                    bail!(Error::new(
122                        cur.span,
123                        format!(
124                            "package identifier `{cur_name}` does not match \
125                             previous package name of `{prev}`"
126                        ),
127                    ))
128                }
129            }
130            self.package_name = Some((cur_name, cur.span));
131
132            // At most one 'package' item can have doc comments.
133            let docs = self.docs(&cur.docs);
134            if docs.contents.is_some() {
135                if self.package_docs.contents.is_some() {
136                    bail!(Error::new(
137                        cur.docs.span,
138                        "found doc comments on multiple 'package' items"
139                    ))
140                }
141                self.package_docs = docs;
142            }
143        }
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        for item in file.decl_list.items.iter() {
149            let span = match item {
150                ast::AstItem::Package(pkg) => pkg.package_id.as_ref().unwrap().span,
151                _ => continue,
152            };
153            bail!(Error::new(
154                span,
155                "nested packages must be placed at the top-level"
156            ))
157        }
158
159        self.decl_lists.push(file.decl_list);
160        Ok(())
161    }
162
163    pub(crate) fn resolve(&mut self) -> Result<UnresolvedPackage> {
164        // At least one of the WIT files must have a `package` annotation.
165        let (name, package_name_span) = match &self.package_name {
166            Some(name) => name.clone(),
167            None => {
168                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        let decl_lists = mem::take(&mut self.decl_lists);
177        self.populate_foreign_deps(&decl_lists);
178        let (iface_order, world_order) = self.populate_ast_items(&decl_lists)?;
179        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        let mut iface_id_to_ast = IndexMap::new();
185        let mut world_id_to_ast = IndexMap::new();
186        for (i, decl_list) in decl_lists.iter().enumerate() {
187            for item in decl_list.items.iter() {
188                match item {
189                    ast::AstItem::Interface(iface) => {
190                        let id = match self.ast_items[i][iface.name.name] {
191                            AstItem::Interface(id) => id,
192                            AstItem::World(_) => unreachable!(),
193                        };
194                        iface_id_to_ast.insert(id, (iface, i));
195                    }
196                    ast::AstItem::World(world) => {
197                        let id = match self.ast_items[i][world.name.name] {
198                            AstItem::World(id) => id,
199                            AstItem::Interface(_) => unreachable!(),
200                        };
201                        world_id_to_ast.insert(id, (world, i));
202                    }
203                    ast::AstItem::Use(_) => {}
204                    ast::AstItem::Package(_) => unreachable!(),
205                }
206            }
207        }
208
209        for id in iface_order {
210            let (interface, i) = &iface_id_to_ast[&id];
211            self.cur_ast_index = *i;
212            self.resolve_interface(id, &interface.items, &interface.docs, &interface.attributes)?;
213        }
214
215        for id in world_order {
216            let (world, i) = &world_id_to_ast[&id];
217            self.cur_ast_index = *i;
218            self.resolve_world(id, world)?;
219        }
220
221        self.decl_lists = decl_lists;
222        Ok(UnresolvedPackage {
223            package_name_span,
224            name,
225            docs: mem::take(&mut self.package_docs),
226            worlds: mem::take(&mut self.worlds),
227            types: mem::take(&mut self.types),
228            interfaces: mem::take(&mut self.interfaces),
229            foreign_deps: self
230                .foreign_deps
231                .iter()
232                .map(|(name, deps)| {
233                    (
234                        name.clone(),
235                        deps.iter()
236                            .map(|(name, id)| (name.to_string(), *id))
237                            .collect(),
238                    )
239                })
240                .collect(),
241            unknown_type_spans: mem::take(&mut self.unknown_type_spans),
242            interface_spans: mem::take(&mut self.interface_spans),
243            world_spans: mem::take(&mut self.world_spans),
244            type_spans: mem::take(&mut self.type_spans),
245            foreign_dep_spans: mem::take(&mut self.foreign_dep_spans),
246            required_resource_types: mem::take(&mut self.required_resource_types),
247        })
248    }
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    fn populate_foreign_deps(&mut self, decl_lists: &[ast::DeclList<'a>]) {
255        let mut foreign_deps = mem::take(&mut self.foreign_deps);
256        let mut foreign_interfaces = mem::take(&mut self.foreign_interfaces);
257        let mut foreign_worlds = mem::take(&mut self.foreign_worlds);
258        for decl_list in decl_lists {
259            decl_list
260                .for_each_path(&mut |_, _attrs, path, _names, world_or_iface| {
261                    let (id, name) = match path {
262                        ast::UsePath::Package { id, name } => (id, name),
263                        _ => return Ok(()),
264                    };
265
266                    let deps = foreign_deps.entry(id.package_name()).or_insert_with(|| {
267                        self.foreign_dep_spans.push(id.span);
268                        IndexMap::new()
269                    });
270                    let id = *deps.entry(name.name).or_insert_with(|| {
271                        match world_or_iface {
272                            WorldOrInterface::World => {
273                                log::trace!(
274                                    "creating a world for foreign dep: {}/{}",
275                                    id.package_name(),
276                                    name.name
277                                );
278                                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                                log::trace!(
284                                    "creating an interface for foreign dep: {}/{}",
285                                    id.package_name(),
286                                    name.name
287                                );
288                                AstItem::Interface(self.alloc_interface(name.span))
289                            }
290                        }
291                    });
292
293                    let _ = match id {
294                        AstItem::Interface(id) => foreign_interfaces.insert(id),
295                        AstItem::World(id) => foreign_worlds.insert(id),
296                    };
297
298                    Ok(())
299                })
300                .unwrap();
301        }
302        self.foreign_deps = foreign_deps;
303        self.foreign_interfaces = foreign_interfaces;
304        self.foreign_worlds = foreign_worlds;
305    }
306
307    fn alloc_interface(&mut self, span: Span) -> InterfaceId {
308        self.interface_types.push(IndexMap::new());
309        self.interface_spans.push(InterfaceSpan {
310            span,
311            funcs: Vec::new(),
312        });
313        self.interfaces.alloc(Interface {
314            name: None,
315            types: IndexMap::new(),
316            docs: Docs::default(),
317            stability: Default::default(),
318            functions: IndexMap::new(),
319            package: None,
320        })
321    }
322
323    fn alloc_world(&mut self, span: Span) -> WorldId {
324        self.world_spans.push(WorldSpan {
325            span,
326            imports: Vec::new(),
327            exports: Vec::new(),
328            includes: Vec::new(),
329        });
330        self.worlds.alloc(World {
331            name: String::new(),
332            docs: Docs::default(),
333            exports: IndexMap::new(),
334            imports: IndexMap::new(),
335            package: None,
336            includes: Default::default(),
337            include_names: Default::default(),
338            stability: Default::default(),
339        })
340    }
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    fn populate_ast_items(
346        &mut self,
347        decl_lists: &[ast::DeclList<'a>],
348    ) -> Result<(Vec<InterfaceId>, Vec<WorldId>)> {
349        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        let mut names = HashMap::new();
354        let mut decl_list_namespaces = Vec::new();
355        let mut order = IndexMap::new();
356        for decl_list in decl_lists {
357            let mut decl_list_ns = IndexMap::new();
358            for item in decl_list.items.iter() {
359                match item {
360                    ast::AstItem::Interface(i) => {
361                        if package_items.insert(i.name.name, i.name.span).is_some() {
362                            bail!(Error::new(
363                                i.name.span,
364                                format!("duplicate item named `{}`", i.name.name),
365                            ))
366                        }
367                        let prev = decl_list_ns.insert(i.name.name, ());
368                        assert!(prev.is_none());
369                        let prev = order.insert(i.name.name, Vec::new());
370                        assert!(prev.is_none());
371                        let prev = names.insert(i.name.name, item);
372                        assert!(prev.is_none());
373                    }
374                    ast::AstItem::World(w) => {
375                        if package_items.insert(w.name.name, w.name.span).is_some() {
376                            bail!(Error::new(
377                                w.name.span,
378                                format!("duplicate item named `{}`", w.name.name),
379                            ))
380                        }
381                        let prev = decl_list_ns.insert(w.name.name, ());
382                        assert!(prev.is_none());
383                        let prev = order.insert(w.name.name, Vec::new());
384                        assert!(prev.is_none());
385                        let prev = names.insert(w.name.name, item);
386                        assert!(prev.is_none());
387                    }
388                    // These are processed down below.
389                    ast::AstItem::Use(_) => {}
390
391                    ast::AstItem::Package(_) => unreachable!(),
392                }
393            }
394            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        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            let mut decl_list_ns = IndexMap::new();
412            for item in decl_list.items.iter() {
413                let (name, src) = match item {
414                    ast::AstItem::Use(u) => {
415                        let name = u.as_.as_ref().unwrap_or(u.item.name());
416                        let src = match &u.item {
417                            ast::UsePath::Id(id) => ItemSource::Local(id.clone()),
418                            ast::UsePath::Package { .. } => ItemSource::Foreign,
419                        };
420                        (name, src)
421                    }
422                    ast::AstItem::Interface(i) => (&i.name, ItemSource::Local(i.name.clone())),
423                    ast::AstItem::World(w) => (&w.name, ItemSource::Local(w.name.clone())),
424                    ast::AstItem::Package(_) => unreachable!(),
425                };
426                if decl_list_ns.insert(name.name, (name.span, src)).is_some() {
427                    bail!(Error::new(
428                        name.span,
429                        format!("duplicate name `{}` in this file", name.name),
430                    ));
431                }
432            }
433
434            // With this file's namespace information look at all `use` paths
435            // and record dependencies between interfaces.
436            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                let iface = match iface {
441                    Some(name) => name,
442                    None => return Ok(()),
443                };
444                let used_name = match path {
445                    ast::UsePath::Id(id) => id,
446                    ast::UsePath::Package { .. } => return Ok(()),
447                };
448                match decl_list_ns.get(used_name.name) {
449                    Some((_, ItemSource::Foreign)) => return Ok(()),
450                    Some((_, ItemSource::Local(id))) => {
451                        order[iface.name].push(id.clone());
452                    }
453                    None => match package_items.get(used_name.name) {
454                        Some(_) => {
455                            order[iface.name].push(used_name.clone());
456                        }
457                        None => {
458                            bail!(Error::new(
459                                used_name.span,
460                                format!(
461                                    "interface or world `{name}` not found in package",
462                                    name = used_name.name
463                                ),
464                            ))
465                        }
466                    },
467                }
468                Ok(())
469            })?;
470        }
471
472        let order = toposort("interface or world", &order)?;
473        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        let mut ids = IndexMap::new();
479        let mut iface_id_order = Vec::new();
480        let mut world_id_order = Vec::new();
481        for name in order {
482            match names.get(name).unwrap() {
483                ast::AstItem::Interface(_) => {
484                    let id = self.alloc_interface(package_items[name]);
485                    self.interfaces[id].name = Some(name.to_string());
486                    let prev = ids.insert(name, AstItem::Interface(id));
487                    assert!(prev.is_none());
488                    iface_id_order.push(id);
489                }
490                ast::AstItem::World(_) => {
491                    let id = self.alloc_world(package_items[name]);
492                    self.worlds[id].name = name.to_string();
493                    let prev = ids.insert(name, AstItem::World(id));
494                    assert!(prev.is_none());
495                    world_id_order.push(id);
496                }
497                ast::AstItem::Use(_) | ast::AstItem::Package(_) => unreachable!(),
498            };
499        }
500        for decl_list in decl_lists {
501            let mut items = IndexMap::new();
502            for item in decl_list.items.iter() {
503                let (name, ast_item) = match item {
504                    ast::AstItem::Use(u) => {
505                        if !u.attributes.is_empty() {
506                            bail!(Error::new(
507                                u.span,
508                                format!("attributes not allowed on top-level use"),
509                            ))
510                        }
511                        let name = u.as_.as_ref().unwrap_or(u.item.name());
512                        let item = match &u.item {
513                            ast::UsePath::Id(name) => *ids.get(name.name).ok_or_else(|| {
514                                Error::new(
515                                    name.span,
516                                    format!(
517                                        "interface or world `{name}` does not exist",
518                                        name = name.name
519                                    ),
520                                )
521                            })?,
522                            ast::UsePath::Package { id, name } => {
523                                self.foreign_deps[&id.package_name()][name.name]
524                            }
525                        };
526                        (name.name, item)
527                    }
528                    ast::AstItem::Interface(i) => {
529                        let iface_item = ids[i.name.name];
530                        assert!(matches!(iface_item, AstItem::Interface(_)));
531                        (i.name.name, iface_item)
532                    }
533                    ast::AstItem::World(w) => {
534                        let world_item = ids[w.name.name];
535                        assert!(matches!(world_item, AstItem::World(_)));
536                        (w.name.name, world_item)
537                    }
538                    ast::AstItem::Package(_) => unreachable!(),
539                };
540                let prev = items.insert(name, ast_item);
541                assert!(prev.is_none());
542
543                // Items defined via `use` don't go into the package namespace,
544                // only the file namespace.
545                if !matches!(item, ast::AstItem::Use(_)) {
546                    let prev = self.package_items.insert(name, ast_item);
547                    assert!(prev.is_none());
548                }
549            }
550            self.ast_items.push(items);
551        }
552        Ok((iface_id_order, world_id_order))
553    }
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    fn populate_foreign_types(&mut self, decl_lists: &[ast::DeclList<'a>]) -> Result<()> {
562        for (i, decl_list) in decl_lists.iter().enumerate() {
563            self.cur_ast_index = i;
564            decl_list.for_each_path(&mut |_, attrs, path, names, _| {
565                let names = match names {
566                    Some(names) => names,
567                    None => return Ok(()),
568                };
569                let stability = self.stability(attrs)?;
570                let (item, name, span) = self.resolve_ast_item_path(path)?;
571                let iface = self.extract_iface_from_item(&item, &name, span)?;
572                if !self.foreign_interfaces.contains(&iface) {
573                    return Ok(());
574                }
575
576                let lookup = &mut self.interface_types[iface.index()];
577                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                    if lookup.contains_key(name.name.name) {
582                        continue;
583                    }
584                    let id = self.types.alloc(TypeDef {
585                        docs: Docs::default(),
586                        stability: stability.clone(),
587                        kind: TypeDefKind::Unknown,
588                        name: Some(name.name.name.to_string()),
589                        owner: TypeOwner::Interface(iface),
590                    });
591                    self.unknown_type_spans.push(name.name.span);
592                    self.type_spans.push(name.name.span);
593                    lookup.insert(name.name.name, (TypeOrItem::Type(id), name.name.span));
594                    self.interfaces[iface]
595                        .types
596                        .insert(name.name.name.to_string(), id);
597                }
598
599                Ok(())
600            })?;
601        }
602        Ok(())
603    }
604
605    fn resolve_world(&mut self, world_id: WorldId, world: &ast::World<'a>) -> Result<WorldId> {
606        let docs = self.docs(&world.docs);
607        self.worlds[world_id].docs = docs;
608        let stability = self.stability(&world.attributes)?;
609        self.worlds[world_id].stability = stability;
610
611        self.resolve_types(
612            TypeOwner::World(world_id),
613            world.items.iter().filter_map(|i| match i {
614                ast::WorldItem::Use(u) => Some(TypeItem::Use(u)),
615                ast::WorldItem::Type(t) => Some(TypeItem::Def(t)),
616                ast::WorldItem::Import(_) | ast::WorldItem::Export(_) => None,
617                // should be handled in `wit-parser::resolve`
618                ast::WorldItem::Include(_) => None,
619            }),
620        )?;
621
622        // resolve include items
623        let items = world.items.iter().filter_map(|i| match i {
624            ast::WorldItem::Include(i) => Some(i),
625            _ => None,
626        });
627        for include in items {
628            self.resolve_include(world_id, include)?;
629        }
630
631        let mut export_spans = Vec::new();
632        let mut import_spans = Vec::new();
633        let mut import_names = HashMap::new();
634        let mut export_names = HashMap::new();
635        for (name, (item, span)) in self.type_lookup.iter() {
636            match *item {
637                TypeOrItem::Type(id) => {
638                    let prev = import_names.insert(*name, "import");
639                    if let Some(prev) = prev {
640                        bail!(Error::new(
641                            *span,
642                            format!("import `{name}` conflicts with prior {prev} of same name",),
643                        ))
644                    }
645                    self.worlds[world_id]
646                        .imports
647                        .insert(WorldKey::Name(name.to_string()), WorldItem::Type(id));
648                    import_spans.push(*span);
649                }
650                TypeOrItem::Item(_) => unreachable!(),
651            }
652        }
653
654        let mut imported_interfaces = HashSet::new();
655        let mut exported_interfaces = HashSet::new();
656        for item in world.items.iter() {
657            let (docs, attrs, kind, desc, spans, interfaces, names) = match item {
658                ast::WorldItem::Import(import) => (
659                    &import.docs,
660                    &import.attributes,
661                    &import.kind,
662                    "import",
663                    &mut import_spans,
664                    &mut imported_interfaces,
665                    &mut import_names,
666                ),
667                ast::WorldItem::Export(export) => (
668                    &export.docs,
669                    &export.attributes,
670                    &export.kind,
671                    "export",
672                    &mut export_spans,
673                    &mut exported_interfaces,
674                    &mut export_names,
675                ),
676
677                ast::WorldItem::Type(ast::TypeDef {
678                    name,
679                    ty: ast::Type::Resource(r),
680                    ..
681                }) => {
682                    for func in r.funcs.iter() {
683                        import_spans.push(func.named_func().name.span);
684                        let func = self.resolve_resource_func(func, name)?;
685                        let prev = self.worlds[world_id]
686                            .imports
687                            .insert(WorldKey::Name(func.name.clone()), WorldItem::Function(func));
688                        // Resource names themselves are unique, and methods are
689                        // uniquely named, so this should be possible to assert
690                        // at this point and never trip.
691                        assert!(prev.is_none());
692                    }
693                    continue;
694                }
695
696                // handled in `resolve_types`
697                ast::WorldItem::Use(_) | ast::WorldItem::Type(_) | ast::WorldItem::Include(_) => {
698                    continue
699                }
700            };
701            let key = match kind {
702                ast::ExternKind::Interface(name, _) | ast::ExternKind::Func(name, _) => {
703                    let prev = names.insert(name.name, desc);
704                    if let Some(prev) = prev {
705                        bail!(Error::new(
706                            kind.span(),
707                            format!(
708                                "{desc} `{name}` conflicts with prior {prev} of same name",
709                                name = name.name
710                            ),
711                        ))
712                    }
713                    WorldKey::Name(name.name.to_string())
714                }
715                ast::ExternKind::Path(path) => {
716                    let (item, name, span) = self.resolve_ast_item_path(path)?;
717                    let id = self.extract_iface_from_item(&item, &name, span)?;
718                    WorldKey::Interface(id)
719                }
720            };
721            let world_item = self.resolve_world_item(docs, attrs, kind)?;
722            if let WorldItem::Interface { id, .. } = world_item {
723                if !interfaces.insert(id) {
724                    bail!(Error::new(
725                        kind.span(),
726                        format!("interface cannot be {desc}ed more than once"),
727                    ))
728                }
729            }
730            let dst = if desc == "import" {
731                &mut self.worlds[world_id].imports
732            } else {
733                &mut self.worlds[world_id].exports
734            };
735            let prev = dst.insert(key, world_item);
736            assert!(prev.is_none());
737            spans.push(kind.span());
738        }
739        self.world_spans[world_id.index()].imports = import_spans;
740        self.world_spans[world_id.index()].exports = export_spans;
741        self.type_lookup.clear();
742
743        Ok(world_id)
744    }
745
746    fn resolve_world_item(
747        &mut self,
748        docs: &ast::Docs<'a>,
749        attrs: &[ast::Attribute<'a>],
750        kind: &ast::ExternKind<'a>,
751    ) -> Result<WorldItem> {
752        match kind {
753            ast::ExternKind::Interface(name, items) => {
754                let prev = mem::take(&mut self.type_lookup);
755                let id = self.alloc_interface(name.span);
756                self.resolve_interface(id, items, docs, attrs)?;
757                self.type_lookup = prev;
758                let stability = self.interfaces[id].stability.clone();
759                Ok(WorldItem::Interface { id, stability })
760            }
761            ast::ExternKind::Path(path) => {
762                let stability = self.stability(attrs)?;
763                let (item, name, span) = self.resolve_ast_item_path(path)?;
764                let id = self.extract_iface_from_item(&item, &name, span)?;
765                Ok(WorldItem::Interface { id, stability })
766            }
767            ast::ExternKind::Func(name, func) => {
768                let prefix = if func.async_ { "[async]" } else { "" };
769                let name = format!("{prefix}{}", name.name);
770                let func = self.resolve_function(
771                    docs,
772                    attrs,
773                    &name,
774                    func,
775                    if func.async_ {
776                        FunctionKind::AsyncFreestanding
777                    } else {
778                        FunctionKind::Freestanding
779                    },
780                )?;
781                Ok(WorldItem::Function(func))
782            }
783        }
784    }
785
786    fn resolve_interface(
787        &mut self,
788        interface_id: InterfaceId,
789        fields: &[ast::InterfaceItem<'a>],
790        docs: &ast::Docs<'a>,
791        attrs: &[ast::Attribute<'a>],
792    ) -> Result<()> {
793        let docs = self.docs(docs);
794        self.interfaces[interface_id].docs = docs;
795        let stability = self.stability(attrs)?;
796        self.interfaces[interface_id].stability = stability;
797
798        self.resolve_types(
799            TypeOwner::Interface(interface_id),
800            fields.iter().filter_map(|i| match i {
801                ast::InterfaceItem::Use(u) => Some(TypeItem::Use(u)),
802                ast::InterfaceItem::TypeDef(t) => Some(TypeItem::Def(t)),
803                ast::InterfaceItem::Func(_) => None,
804            }),
805        )?;
806
807        for (name, (ty, _)) in self.type_lookup.iter() {
808            match *ty {
809                TypeOrItem::Type(id) => {
810                    self.interfaces[interface_id]
811                        .types
812                        .insert(name.to_string(), id);
813                }
814                TypeOrItem::Item(_) => unreachable!(),
815            }
816        }
817
818        // Finally process all function definitions now that all types are
819        // defined.
820        let mut funcs = Vec::new();
821        for field in fields {
822            match field {
823                ast::InterfaceItem::Func(f) => {
824                    self.define_interface_name(&f.name, TypeOrItem::Item("function"))?;
825                    let prefix = if f.func.async_ { "[async]" } else { "" };
826                    let name = format!("{prefix}{}", f.name.name);
827                    funcs.push(self.resolve_function(
828                        &f.docs,
829                        &f.attributes,
830                        &name,
831                        &f.func,
832                        if f.func.async_ {
833                            FunctionKind::AsyncFreestanding
834                        } else {
835                            FunctionKind::Freestanding
836                        },
837                    )?);
838                    self.interface_spans[interface_id.index()]
839                        .funcs
840                        .push(f.name.span);
841                }
842                ast::InterfaceItem::Use(_) => {}
843                ast::InterfaceItem::TypeDef(ast::TypeDef {
844                    name,
845                    ty: ast::Type::Resource(r),
846                    ..
847                }) => {
848                    for func in r.funcs.iter() {
849                        funcs.push(self.resolve_resource_func(func, name)?);
850                        self.interface_spans[interface_id.index()]
851                            .funcs
852                            .push(func.named_func().name.span);
853                    }
854                }
855                ast::InterfaceItem::TypeDef(_) => {}
856            }
857        }
858        for func in funcs {
859            let prev = self.interfaces[interface_id]
860                .functions
861                .insert(func.name.clone(), func);
862            assert!(prev.is_none());
863        }
864
865        let lookup = mem::take(&mut self.type_lookup);
866        self.interface_types[interface_id.index()] = lookup;
867
868        Ok(())
869    }
870
871    fn resolve_types<'b>(
872        &mut self,
873        owner: TypeOwner,
874        fields: impl Iterator<Item = TypeItem<'a, 'b>> + Clone,
875    ) -> Result<()>
876    where
877        'a: 'b,
878    {
879        assert!(self.type_lookup.is_empty());
880
881        // First, populate our namespace with `use` statements
882        for field in fields.clone() {
883            match field {
884                TypeItem::Use(u) => {
885                    self.resolve_use(owner, u)?;
886                }
887                TypeItem::Def(_) => {}
888            }
889        }
890
891        // Next determine dependencies between types, perform a topological
892        // sort, and then define all types. This will define types in a
893        // topological fashion, forbid cycles, and weed out references to
894        // undefined types all in one go.
895        let mut type_deps = IndexMap::new();
896        let mut type_defs = IndexMap::new();
897        for field in fields {
898            match field {
899                TypeItem::Def(t) => {
900                    let prev = type_defs.insert(t.name.name, Some(t));
901                    if prev.is_some() {
902                        bail!(Error::new(
903                            t.name.span,
904                            format!("name `{}` is defined more than once", t.name.name),
905                        ))
906                    }
907                    let mut deps = Vec::new();
908                    collect_deps(&t.ty, &mut deps);
909                    type_deps.insert(t.name.name, deps);
910                }
911                TypeItem::Use(u) => {
912                    for name in u.names.iter() {
913                        let name = name.as_.as_ref().unwrap_or(&name.name);
914                        type_deps.insert(name.name, Vec::new());
915                        type_defs.insert(name.name, None);
916                    }
917                }
918            }
919        }
920        let order = toposort("type", &type_deps).map_err(attach_old_float_type_context)?;
921        for ty in order {
922            let def = match type_defs.swap_remove(&ty).unwrap() {
923                Some(def) => def,
924                None => continue,
925            };
926            let docs = self.docs(&def.docs);
927            let stability = self.stability(&def.attributes)?;
928            let kind = self.resolve_type_def(&def.ty, &stability)?;
929            let id = self.types.alloc(TypeDef {
930                docs,
931                stability,
932                kind,
933                name: Some(def.name.name.to_string()),
934                owner,
935            });
936            self.type_spans.push(def.name.span);
937            self.define_interface_name(&def.name, TypeOrItem::Type(id))?;
938        }
939        return Ok(());
940
941        fn attach_old_float_type_context(err: ast::toposort::Error) -> anyhow::Error {
942            let name = match &err {
943                ast::toposort::Error::NonexistentDep { name, .. } => name,
944                _ => return err.into(),
945            };
946            let new = match name.as_str() {
947                "float32" => "f32",
948                "float64" => "f64",
949                _ => return err.into(),
950            };
951
952            let context = format!(
953                "the `{name}` type has been renamed to `{new}` and is \
954                 no longer accepted, but the `WIT_REQUIRE_F32_F64=0` \
955                 environment variable can be used to temporarily \
956                 disable this error"
957            );
958            anyhow::Error::from(err).context(context)
959        }
960    }
961
962    fn resolve_use(&mut self, owner: TypeOwner, u: &ast::Use<'a>) -> Result<()> {
963        let (item, name, span) = self.resolve_ast_item_path(&u.from)?;
964        let use_from = self.extract_iface_from_item(&item, &name, span)?;
965        let stability = self.stability(&u.attributes)?;
966
967        for name in u.names.iter() {
968            let lookup = &self.interface_types[use_from.index()];
969            let id = match lookup.get(name.name.name) {
970                Some((TypeOrItem::Type(id), _)) => *id,
971                Some((TypeOrItem::Item(s), _)) => {
972                    bail!(Error::new(
973                        name.name.span,
974                        format!("cannot import {s} `{}`", name.name.name),
975                    ))
976                }
977                None => bail!(Error::new(
978                    name.name.span,
979                    format!("name `{}` is not defined", name.name.name),
980                )),
981            };
982            self.type_spans.push(name.name.span);
983            let name = name.as_.as_ref().unwrap_or(&name.name);
984            let id = self.types.alloc(TypeDef {
985                docs: Docs::default(),
986                stability: stability.clone(),
987                kind: TypeDefKind::Type(Type::Id(id)),
988                name: Some(name.name.to_string()),
989                owner,
990            });
991            self.define_interface_name(name, TypeOrItem::Type(id))?;
992        }
993        Ok(())
994    }
995
996    /// For each name in the `include`, resolve the path of the include, add it to the self.includes
997    fn resolve_include(&mut self, world_id: WorldId, i: &ast::Include<'a>) -> Result<()> {
998        let stability = self.stability(&i.attributes)?;
999        let (item, name, span) = self.resolve_ast_item_path(&i.from)?;
1000        let include_from = self.extract_world_from_item(&item, &name, span)?;
1001        self.worlds[world_id]
1002            .includes
1003            .push((stability, include_from));
1004        self.worlds[world_id].include_names.push(
1005            i.names
1006                .iter()
1007                .map(|n| IncludeName {
1008                    name: n.name.name.to_string(),
1009                    as_: n.as_.name.to_string(),
1010                })
1011                .collect(),
1012        );
1013        self.world_spans[world_id.index()].includes.push(span);
1014        Ok(())
1015    }
1016
1017    fn resolve_resource_func(
1018        &mut self,
1019        func: &ast::ResourceFunc<'_>,
1020        resource: &ast::Id<'_>,
1021    ) -> Result<Function> {
1022        let resource_id = match self.type_lookup.get(resource.name) {
1023            Some((TypeOrItem::Type(id), _)) => *id,
1024            _ => panic!("type lookup for resource failed"),
1025        };
1026        let (name, kind);
1027        let named_func = func.named_func();
1028        let async_ = named_func.func.async_;
1029        match func {
1030            ast::ResourceFunc::Method(f) => {
1031                let prefix = if async_ { "[async method]" } else { "[method]" };
1032                name = format!("{prefix}{}.{}", resource.name, f.name.name);
1033                kind = if async_ {
1034                    FunctionKind::AsyncMethod(resource_id)
1035                } else {
1036                    FunctionKind::Method(resource_id)
1037                };
1038            }
1039            ast::ResourceFunc::Static(f) => {
1040                let prefix = if async_ { "[async static]" } else { "[static]" };
1041                name = format!("{prefix}{}.{}", resource.name, f.name.name);
1042                kind = if async_ {
1043                    FunctionKind::AsyncStatic(resource_id)
1044                } else {
1045                    FunctionKind::Static(resource_id)
1046                };
1047            }
1048            ast::ResourceFunc::Constructor(_) => {
1049                assert!(!async_); // should not be possible to parse
1050                name = format!("[constructor]{}", resource.name);
1051                kind = FunctionKind::Constructor(resource_id);
1052            }
1053        }
1054        self.resolve_function(
1055            &named_func.docs,
1056            &named_func.attributes,
1057            &name,
1058            &named_func.func,
1059            kind,
1060        )
1061    }
1062
1063    fn resolve_function(
1064        &mut self,
1065        docs: &ast::Docs<'_>,
1066        attrs: &[ast::Attribute<'_>],
1067        name: &str,
1068        func: &ast::Func,
1069        kind: FunctionKind,
1070    ) -> Result<Function> {
1071        let docs = self.docs(docs);
1072        let stability = self.stability(attrs)?;
1073        let params = self.resolve_params(&func.params, &kind, func.span)?;
1074        let result = self.resolve_result(&func.result, &kind, func.span)?;
1075        Ok(Function {
1076            docs,
1077            stability,
1078            name: name.to_string(),
1079            kind,
1080            params,
1081            result,
1082        })
1083    }
1084
1085    fn resolve_ast_item_path(&self, path: &ast::UsePath<'a>) -> Result<(AstItem, String, Span)> {
1086        match path {
1087            ast::UsePath::Id(id) => {
1088                let item = self.ast_items[self.cur_ast_index]
1089                    .get(id.name)
1090                    .or_else(|| self.package_items.get(id.name));
1091                match item {
1092                    Some(item) => Ok((*item, id.name.into(), id.span)),
1093                    None => {
1094                        bail!(Error::new(
1095                            id.span,
1096                            format!("interface or world `{}` does not exist", id.name),
1097                        ))
1098                    }
1099                }
1100            }
1101            ast::UsePath::Package { id, name } => Ok((
1102                self.foreign_deps[&id.package_name()][name.name],
1103                name.name.into(),
1104                name.span,
1105            )),
1106        }
1107    }
1108
1109    fn extract_iface_from_item(
1110        &self,
1111        item: &AstItem,
1112        name: &str,
1113        span: Span,
1114    ) -> Result<InterfaceId> {
1115        match item {
1116            AstItem::Interface(id) => Ok(*id),
1117            AstItem::World(_) => {
1118                bail!(Error::new(
1119                    span,
1120                    format!("name `{name}` is defined as a world, not an interface"),
1121                ))
1122            }
1123        }
1124    }
1125
1126    fn extract_world_from_item(&self, item: &AstItem, name: &str, span: Span) -> Result<WorldId> {
1127        match item {
1128            AstItem::World(id) => Ok(*id),
1129            AstItem::Interface(_) => {
1130                bail!(Error::new(
1131                    span,
1132                    format!("name `{name}` is defined as an interface, not a world"),
1133                ))
1134            }
1135        }
1136    }
1137
1138    fn define_interface_name(&mut self, name: &ast::Id<'a>, item: TypeOrItem) -> Result<()> {
1139        let prev = self.type_lookup.insert(name.name, (item, name.span));
1140        if prev.is_some() {
1141            bail!(Error::new(
1142                name.span,
1143                format!("name `{}` is defined more than once", name.name),
1144            ))
1145        } else {
1146            Ok(())
1147        }
1148    }
1149
1150    fn resolve_type_def(
1151        &mut self,
1152        ty: &ast::Type<'_>,
1153        stability: &Stability,
1154    ) -> Result<TypeDefKind> {
1155        Ok(match ty {
1156            ast::Type::Bool(_) => TypeDefKind::Type(Type::Bool),
1157            ast::Type::U8(_) => TypeDefKind::Type(Type::U8),
1158            ast::Type::U16(_) => TypeDefKind::Type(Type::U16),
1159            ast::Type::U32(_) => TypeDefKind::Type(Type::U32),
1160            ast::Type::U64(_) => TypeDefKind::Type(Type::U64),
1161            ast::Type::S8(_) => TypeDefKind::Type(Type::S8),
1162            ast::Type::S16(_) => TypeDefKind::Type(Type::S16),
1163            ast::Type::S32(_) => TypeDefKind::Type(Type::S32),
1164            ast::Type::S64(_) => TypeDefKind::Type(Type::S64),
1165            ast::Type::F32(_) => TypeDefKind::Type(Type::F32),
1166            ast::Type::F64(_) => TypeDefKind::Type(Type::F64),
1167            ast::Type::Char(_) => TypeDefKind::Type(Type::Char),
1168            ast::Type::String(_) => TypeDefKind::Type(Type::String),
1169            ast::Type::ErrorContext(_) => TypeDefKind::Type(Type::ErrorContext),
1170            ast::Type::Name(name) => {
1171                let id = self.resolve_type_name(name)?;
1172                TypeDefKind::Type(Type::Id(id))
1173            }
1174            ast::Type::List(list) => {
1175                let ty = self.resolve_type(&list.ty, stability)?;
1176                TypeDefKind::List(ty)
1177            }
1178            ast::Type::FixedSizeList(list) => {
1179                let ty = self.resolve_type(&list.ty, stability)?;
1180                TypeDefKind::FixedSizeList(ty, list.size)
1181            }
1182            ast::Type::Handle(handle) => TypeDefKind::Handle(match handle {
1183                ast::Handle::Own { resource } => Handle::Own(self.validate_resource(resource)?),
1184                ast::Handle::Borrow { resource } => {
1185                    Handle::Borrow(self.validate_resource(resource)?)
1186                }
1187            }),
1188            ast::Type::Resource(resource) => {
1189                // Validate here that the resource doesn't have any duplicate-ly
1190                // named methods and that there's at most one constructor.
1191                let mut ctors = 0;
1192                let mut names = HashSet::new();
1193                for func in resource.funcs.iter() {
1194                    match func {
1195                        ast::ResourceFunc::Method(f) | ast::ResourceFunc::Static(f) => {
1196                            if !names.insert(&f.name.name) {
1197                                bail!(Error::new(
1198                                    f.name.span,
1199                                    format!("duplicate function name `{}`", f.name.name),
1200                                ))
1201                            }
1202                        }
1203                        ast::ResourceFunc::Constructor(f) => {
1204                            ctors += 1;
1205                            if ctors > 1 {
1206                                bail!(Error::new(f.name.span, "duplicate constructors"))
1207                            }
1208                        }
1209                    }
1210                }
1211
1212                TypeDefKind::Resource
1213            }
1214            ast::Type::Record(record) => {
1215                let fields = record
1216                    .fields
1217                    .iter()
1218                    .map(|field| {
1219                        Ok(Field {
1220                            docs: self.docs(&field.docs),
1221                            name: field.name.name.to_string(),
1222                            ty: self.resolve_type(&field.ty, stability)?,
1223                        })
1224                    })
1225                    .collect::<Result<Vec<_>>>()?;
1226                TypeDefKind::Record(Record { fields })
1227            }
1228            ast::Type::Flags(flags) => {
1229                let flags = flags
1230                    .flags
1231                    .iter()
1232                    .map(|flag| Flag {
1233                        docs: self.docs(&flag.docs),
1234                        name: flag.name.name.to_string(),
1235                    })
1236                    .collect::<Vec<_>>();
1237                TypeDefKind::Flags(Flags { flags })
1238            }
1239            ast::Type::Tuple(t) => {
1240                let types = t
1241                    .types
1242                    .iter()
1243                    .map(|ty| self.resolve_type(ty, stability))
1244                    .collect::<Result<Vec<_>>>()?;
1245                TypeDefKind::Tuple(Tuple { types })
1246            }
1247            ast::Type::Variant(variant) => {
1248                if variant.cases.is_empty() {
1249                    bail!(Error::new(variant.span, "empty variant"))
1250                }
1251                let cases = variant
1252                    .cases
1253                    .iter()
1254                    .map(|case| {
1255                        Ok(Case {
1256                            docs: self.docs(&case.docs),
1257                            name: case.name.name.to_string(),
1258                            ty: self.resolve_optional_type(case.ty.as_ref(), stability)?,
1259                        })
1260                    })
1261                    .collect::<Result<Vec<_>>>()?;
1262                TypeDefKind::Variant(Variant { cases })
1263            }
1264            ast::Type::Enum(e) => {
1265                if e.cases.is_empty() {
1266                    bail!(Error::new(e.span, "empty enum"))
1267                }
1268                let cases = e
1269                    .cases
1270                    .iter()
1271                    .map(|case| {
1272                        Ok(EnumCase {
1273                            docs: self.docs(&case.docs),
1274                            name: case.name.name.to_string(),
1275                        })
1276                    })
1277                    .collect::<Result<Vec<_>>>()?;
1278                TypeDefKind::Enum(Enum { cases })
1279            }
1280            ast::Type::Option(ty) => TypeDefKind::Option(self.resolve_type(&ty.ty, stability)?),
1281            ast::Type::Result(r) => TypeDefKind::Result(Result_ {
1282                ok: self.resolve_optional_type(r.ok.as_deref(), stability)?,
1283                err: self.resolve_optional_type(r.err.as_deref(), stability)?,
1284            }),
1285            ast::Type::Future(t) => {
1286                TypeDefKind::Future(self.resolve_optional_type(t.ty.as_deref(), stability)?)
1287            }
1288            ast::Type::Stream(s) => {
1289                TypeDefKind::Stream(self.resolve_optional_type(s.ty.as_deref(), stability)?)
1290            }
1291        })
1292    }
1293
1294    fn resolve_type_name(&mut self, name: &ast::Id<'_>) -> Result<TypeId> {
1295        match self.type_lookup.get(name.name) {
1296            Some((TypeOrItem::Type(id), _)) => Ok(*id),
1297            Some((TypeOrItem::Item(s), _)) => bail!(Error::new(
1298                name.span,
1299                format!("cannot use {s} `{name}` as a type", name = name.name),
1300            )),
1301            None => bail!(Error::new(
1302                name.span,
1303                format!("name `{name}` is not defined", name = name.name),
1304            )),
1305        }
1306    }
1307
1308    fn validate_resource(&mut self, name: &ast::Id<'_>) -> Result<TypeId> {
1309        let id = self.resolve_type_name(name)?;
1310        let mut cur = id;
1311        loop {
1312            match self.types[cur].kind {
1313                TypeDefKind::Resource => break Ok(id),
1314                TypeDefKind::Type(Type::Id(ty)) => cur = ty,
1315                TypeDefKind::Unknown => {
1316                    self.required_resource_types.push((cur, name.span));
1317                    break Ok(id);
1318                }
1319                _ => bail!(Error::new(
1320                    name.span,
1321                    format!("type `{}` used in a handle must be a resource", name.name),
1322                )),
1323            }
1324        }
1325    }
1326
1327    /// If `stability` is `Stability::Unknown`, recursively inspect the
1328    /// specified `kind` until we either bottom out or find a type which has a
1329    /// stability that's _not_ unknown.  If we find such a type, return a clone
1330    /// of its stability; otherwise return `Stability::Unknown`.
1331    ///
1332    /// The idea here is that e.g. `option<T>` should inherit `T`'s stability.
1333    /// This gets a little ambiguous in the case of e.g. `tuple<T, U, V>`; for
1334    /// now, we just pick the first one has a known stability, if any.
1335    fn find_stability(&self, kind: &TypeDefKind, stability: &Stability) -> Stability {
1336        fn find_in_type(types: &Arena<TypeDef>, ty: Type) -> Option<&Stability> {
1337            if let Type::Id(id) = ty {
1338                let ty = &types[id];
1339                if !matches!(&ty.stability, Stability::Unknown) {
1340                    Some(&ty.stability)
1341                } else {
1342                    // Note that this type isn't searched recursively since the
1343                    // creation of `id` should already have searched its
1344                    // recursive edges, so there's no need to search again.
1345                    None
1346                }
1347            } else {
1348                None
1349            }
1350        }
1351
1352        fn find_in_kind<'a>(
1353            types: &'a Arena<TypeDef>,
1354            kind: &TypeDefKind,
1355        ) -> Option<&'a Stability> {
1356            match kind {
1357                TypeDefKind::Type(ty) => find_in_type(types, *ty),
1358                TypeDefKind::Handle(Handle::Borrow(id) | Handle::Own(id)) => {
1359                    find_in_type(types, Type::Id(*id))
1360                }
1361                TypeDefKind::Tuple(t) => t.types.iter().find_map(|ty| find_in_type(types, *ty)),
1362                TypeDefKind::List(ty)
1363                | TypeDefKind::FixedSizeList(ty, _)
1364                | TypeDefKind::Option(ty) => find_in_type(types, *ty),
1365                TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
1366                    ty.as_ref().and_then(|ty| find_in_type(types, *ty))
1367                }
1368                TypeDefKind::Result(r) => {
1369                    r.ok.as_ref()
1370                        .and_then(|ty| find_in_type(types, *ty))
1371                        .or_else(|| r.err.as_ref().and_then(|ty| find_in_type(types, *ty)))
1372                }
1373                // Assume these are named types which will be annotated with an
1374                // explicit stability if applicable:
1375                TypeDefKind::Resource
1376                | TypeDefKind::Variant(_)
1377                | TypeDefKind::Record(_)
1378                | TypeDefKind::Flags(_)
1379                | TypeDefKind::Enum(_)
1380                | TypeDefKind::Unknown => None,
1381            }
1382        }
1383
1384        if let Stability::Unknown = stability {
1385            find_in_kind(&self.types, kind)
1386                .cloned()
1387                .unwrap_or(Stability::Unknown)
1388        } else {
1389            stability.clone()
1390        }
1391    }
1392
1393    fn resolve_type(&mut self, ty: &super::Type<'_>, stability: &Stability) -> Result<Type> {
1394        // Resources must be declared at the top level to have their methods
1395        // processed appropriately, but resources also shouldn't show up
1396        // recursively so assert that's not happening here.
1397        match ty {
1398            ast::Type::Resource(_) => unreachable!(),
1399            _ => {}
1400        }
1401        let kind = self.resolve_type_def(ty, stability)?;
1402        let stability = self.find_stability(&kind, stability);
1403        Ok(self.anon_type_def(
1404            TypeDef {
1405                kind,
1406                name: None,
1407                docs: Docs::default(),
1408                stability,
1409                owner: TypeOwner::None,
1410            },
1411            ty.span(),
1412        ))
1413    }
1414
1415    fn resolve_optional_type(
1416        &mut self,
1417        ty: Option<&super::Type<'_>>,
1418        stability: &Stability,
1419    ) -> Result<Option<Type>> {
1420        match ty {
1421            Some(ty) => Ok(Some(self.resolve_type(ty, stability)?)),
1422            None => Ok(None),
1423        }
1424    }
1425
1426    fn anon_type_def(&mut self, ty: TypeDef, span: Span) -> Type {
1427        let key = match &ty.kind {
1428            TypeDefKind::Type(t) => return *t,
1429            TypeDefKind::Variant(v) => Key::Variant(
1430                v.cases
1431                    .iter()
1432                    .map(|case| (case.name.clone(), case.ty))
1433                    .collect::<Vec<_>>(),
1434            ),
1435            TypeDefKind::Handle(Handle::Borrow(h)) => Key::BorrowHandle(*h),
1436            // An anonymous `own<T>` type is the same as a reference to the type
1437            // `T`, so avoid creating anonymous type and return that here
1438            // directly. Note that this additionally avoids creating distinct
1439            // anonymous types for `list<T>` and `list<own<T>>` for example.
1440            TypeDefKind::Handle(Handle::Own(id)) => return Type::Id(*id),
1441            TypeDefKind::Resource => unreachable!("anonymous resources aren't supported"),
1442            TypeDefKind::Record(r) => Key::Record(
1443                r.fields
1444                    .iter()
1445                    .map(|case| (case.name.clone(), case.ty))
1446                    .collect::<Vec<_>>(),
1447            ),
1448            TypeDefKind::Flags(r) => {
1449                Key::Flags(r.flags.iter().map(|f| f.name.clone()).collect::<Vec<_>>())
1450            }
1451            TypeDefKind::Tuple(t) => Key::Tuple(t.types.clone()),
1452            TypeDefKind::Enum(r) => {
1453                Key::Enum(r.cases.iter().map(|f| f.name.clone()).collect::<Vec<_>>())
1454            }
1455            TypeDefKind::List(ty) => Key::List(*ty),
1456            TypeDefKind::FixedSizeList(ty, size) => Key::FixedSizeList(*ty, *size),
1457            TypeDefKind::Option(t) => Key::Option(*t),
1458            TypeDefKind::Result(r) => Key::Result(r.ok, r.err),
1459            TypeDefKind::Future(ty) => Key::Future(*ty),
1460            TypeDefKind::Stream(ty) => Key::Stream(*ty),
1461            TypeDefKind::Unknown => unreachable!(),
1462        };
1463        let id = self.anon_types.entry(key).or_insert_with(|| {
1464            self.type_spans.push(span);
1465            self.types.alloc(ty)
1466        });
1467        Type::Id(*id)
1468    }
1469
1470    fn docs(&mut self, doc: &super::Docs<'_>) -> Docs {
1471        let mut docs = vec![];
1472
1473        for doc in doc.docs.iter() {
1474            let contents = match doc.strip_prefix("/**") {
1475                Some(doc) => doc.strip_suffix("*/").unwrap(),
1476                None => doc.trim_start_matches('/'),
1477            };
1478
1479            docs.push(contents.trim_end());
1480        }
1481
1482        // Scan the (non-empty) doc lines to find the minimum amount of leading whitespace.
1483        // This amount of whitespace will be removed from the start of all doc lines,
1484        // normalizing the output while retaining intentional spacing added by the original authors.
1485        let min_leading_ws = docs
1486            .iter()
1487            .filter(|doc| !doc.is_empty())
1488            .map(|doc| doc.bytes().take_while(|c| c.is_ascii_whitespace()).count())
1489            .min()
1490            .unwrap_or(0);
1491
1492        if min_leading_ws > 0 {
1493            let leading_ws_pattern = " ".repeat(min_leading_ws);
1494            docs = docs
1495                .iter()
1496                .map(|doc| doc.strip_prefix(&leading_ws_pattern).unwrap_or(doc))
1497                .collect();
1498        }
1499
1500        let contents = if docs.is_empty() {
1501            None
1502        } else {
1503            // NB: this notably, through the use of `lines`, normalizes `\r\n`
1504            // to `\n`.
1505            let mut contents = String::new();
1506            for doc in docs {
1507                if doc.is_empty() {
1508                    contents.push_str("\n");
1509                } else {
1510                    for line in doc.lines() {
1511                        contents.push_str(line);
1512                        contents.push_str("\n");
1513                    }
1514                }
1515            }
1516            while contents.ends_with("\n") {
1517                contents.pop();
1518            }
1519            Some(contents)
1520        };
1521        Docs { contents }
1522    }
1523
1524    fn stability(&mut self, attrs: &[ast::Attribute<'_>]) -> Result<Stability> {
1525        match attrs {
1526            [] => Ok(Stability::Unknown),
1527
1528            [ast::Attribute::Since { version, .. }] => Ok(Stability::Stable {
1529                since: version.clone(),
1530                deprecated: None,
1531            }),
1532
1533            [ast::Attribute::Since { version, .. }, ast::Attribute::Deprecated {
1534                version: deprecated,
1535                ..
1536            }]
1537            | [ast::Attribute::Deprecated {
1538                version: deprecated,
1539                ..
1540            }, ast::Attribute::Since { version, .. }] => Ok(Stability::Stable {
1541                since: version.clone(),
1542                deprecated: Some(deprecated.clone()),
1543            }),
1544
1545            [ast::Attribute::Unstable { feature, .. }] => Ok(Stability::Unstable {
1546                feature: feature.name.to_string(),
1547                deprecated: None,
1548            }),
1549
1550            [ast::Attribute::Unstable { feature, .. }, ast::Attribute::Deprecated { version, .. }]
1551            | [ast::Attribute::Deprecated { version, .. }, ast::Attribute::Unstable { feature, .. }] => {
1552                Ok(Stability::Unstable {
1553                    feature: feature.name.to_string(),
1554                    deprecated: Some(version.clone()),
1555                })
1556            }
1557            [ast::Attribute::Deprecated { span, .. }] => {
1558                bail!(Error::new(
1559                    *span,
1560                    "must pair @deprecated with either @since or @unstable",
1561                ))
1562            }
1563            [_, b, ..] => {
1564                bail!(Error::new(
1565                    b.span(),
1566                    "unsupported combination of attributes",
1567                ))
1568            }
1569        }
1570    }
1571
1572    fn resolve_params(
1573        &mut self,
1574        params: &ParamList<'_>,
1575        kind: &FunctionKind,
1576        span: Span,
1577    ) -> Result<Vec<(String, Type)>> {
1578        let mut ret = IndexMap::new();
1579        match *kind {
1580            // These kinds of methods don't have any adjustments to the
1581            // parameters, so do nothing here.
1582            FunctionKind::Freestanding
1583            | FunctionKind::AsyncFreestanding
1584            | FunctionKind::Constructor(_)
1585            | FunctionKind::Static(_)
1586            | FunctionKind::AsyncStatic(_) => {}
1587
1588            // Methods automatically get a `self` initial argument so insert
1589            // that here before processing the normal parameters.
1590            FunctionKind::Method(id) | FunctionKind::AsyncMethod(id) => {
1591                let kind = TypeDefKind::Handle(Handle::Borrow(id));
1592                let stability = self.find_stability(&kind, &Stability::Unknown);
1593                let shared = self.anon_type_def(
1594                    TypeDef {
1595                        docs: Docs::default(),
1596                        stability,
1597                        kind,
1598                        name: None,
1599                        owner: TypeOwner::None,
1600                    },
1601                    span,
1602                );
1603                ret.insert("self".to_string(), shared);
1604            }
1605        }
1606        for (name, ty) in params {
1607            let prev = ret.insert(
1608                name.name.to_string(),
1609                self.resolve_type(ty, &Stability::Unknown)?,
1610            );
1611            if prev.is_some() {
1612                bail!(Error::new(
1613                    name.span,
1614                    format!("param `{}` is defined more than once", name.name),
1615                ))
1616            }
1617        }
1618        Ok(ret.into_iter().collect())
1619    }
1620
1621    fn resolve_result(
1622        &mut self,
1623        result: &Option<ast::Type<'_>>,
1624        kind: &FunctionKind,
1625        _span: Span,
1626    ) -> Result<Option<Type>> {
1627        match *kind {
1628            // These kinds of methods don't have any adjustments to the return
1629            // values, so plumb them through as-is.
1630            FunctionKind::Freestanding
1631            | FunctionKind::AsyncFreestanding
1632            | FunctionKind::Method(_)
1633            | FunctionKind::AsyncMethod(_)
1634            | FunctionKind::Static(_)
1635            | FunctionKind::AsyncStatic(_) => match result {
1636                Some(ty) => Ok(Some(self.resolve_type(ty, &Stability::Unknown)?)),
1637                None => Ok(None),
1638            },
1639
1640            // Constructors are alwys parsed as 0 returned types but they're
1641            // automatically translated as a single return type of the type that
1642            // it's a constructor for.
1643            FunctionKind::Constructor(id) => {
1644                assert!(result.is_none());
1645                Ok(Some(Type::Id(id)))
1646            }
1647        }
1648    }
1649}
1650
1651fn collect_deps<'a>(ty: &ast::Type<'a>, deps: &mut Vec<ast::Id<'a>>) {
1652    match ty {
1653        ast::Type::Bool(_)
1654        | ast::Type::U8(_)
1655        | ast::Type::U16(_)
1656        | ast::Type::U32(_)
1657        | ast::Type::U64(_)
1658        | ast::Type::S8(_)
1659        | ast::Type::S16(_)
1660        | ast::Type::S32(_)
1661        | ast::Type::S64(_)
1662        | ast::Type::F32(_)
1663        | ast::Type::F64(_)
1664        | ast::Type::Char(_)
1665        | ast::Type::String(_)
1666        | ast::Type::Flags(_)
1667        | ast::Type::Enum(_)
1668        | ast::Type::ErrorContext(_) => {}
1669        ast::Type::Name(name) => deps.push(name.clone()),
1670        ast::Type::Handle(handle) => match handle {
1671            ast::Handle::Own { resource } => deps.push(resource.clone()),
1672            ast::Handle::Borrow { resource } => deps.push(resource.clone()),
1673        },
1674        ast::Type::Resource(_) => {}
1675        ast::Type::Record(record) => {
1676            for field in record.fields.iter() {
1677                collect_deps(&field.ty, deps);
1678            }
1679        }
1680        ast::Type::Tuple(t) => {
1681            for ty in t.types.iter() {
1682                collect_deps(ty, deps);
1683            }
1684        }
1685        ast::Type::Variant(variant) => {
1686            for case in variant.cases.iter() {
1687                if let Some(ty) = &case.ty {
1688                    collect_deps(ty, deps);
1689                }
1690            }
1691        }
1692        ast::Type::Option(ast::Option_ { ty, .. })
1693        | ast::Type::List(ast::List { ty, .. })
1694        | ast::Type::FixedSizeList(ast::FixedSizeList { ty, .. }) => collect_deps(ty, deps),
1695        ast::Type::Result(r) => {
1696            if let Some(ty) = &r.ok {
1697                collect_deps(ty, deps);
1698            }
1699            if let Some(ty) = &r.err {
1700                collect_deps(ty, deps);
1701            }
1702        }
1703        ast::Type::Future(t) => {
1704            if let Some(t) = &t.ty {
1705                collect_deps(t, deps)
1706            }
1707        }
1708        ast::Type::Stream(s) => {
1709            if let Some(t) = &s.ty {
1710                collect_deps(t, deps)
1711            }
1712        }
1713    }
1714}