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        for (name, (item, span)) in self.type_lookup.iter() {
634            match *item {
635                TypeOrItem::Type(id) => {
636                    let prev = self.worlds[world_id]
637                        .imports
638                        .insert(WorldKey::Name(name.to_string()), WorldItem::Type(id));
639                    if prev.is_some() {
640                        bail!(Error::new(
641                            *span,
642                            format!("import `{name}` conflicts with prior import of same name"),
643                        ))
644                    }
645                    import_spans.push(*span);
646                }
647                TypeOrItem::Item(_) => unreachable!(),
648            }
649        }
650
651        let mut imported_interfaces = HashSet::new();
652        let mut exported_interfaces = HashSet::new();
653        for item in world.items.iter() {
654            let (docs, attrs, kind, desc, spans, interfaces) = match item {
655                ast::WorldItem::Import(import) => (
656                    &import.docs,
657                    &import.attributes,
658                    &import.kind,
659                    "import",
660                    &mut import_spans,
661                    &mut imported_interfaces,
662                ),
663                ast::WorldItem::Export(export) => (
664                    &export.docs,
665                    &export.attributes,
666                    &export.kind,
667                    "export",
668                    &mut export_spans,
669                    &mut exported_interfaces,
670                ),
671
672                ast::WorldItem::Type(ast::TypeDef {
673                    name,
674                    ty: ast::Type::Resource(r),
675                    ..
676                }) => {
677                    for func in r.funcs.iter() {
678                        import_spans.push(func.named_func().name.span);
679                        let func = self.resolve_resource_func(func, name)?;
680                        let prev = self.worlds[world_id]
681                            .imports
682                            .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                        assert!(prev.is_none());
687                    }
688                    continue;
689                }
690
691                // handled in `resolve_types`
692                ast::WorldItem::Use(_) | ast::WorldItem::Type(_) | ast::WorldItem::Include(_) => {
693                    continue;
694                }
695            };
696
697            let world_item = self.resolve_world_item(docs, attrs, kind)?;
698            let key = match kind {
699                // Interfaces are always named exactly as they are in the WIT.
700                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                    let func = match &world_item {
707                        WorldItem::Function(f) => f,
708                        _ => unreachable!(),
709                    };
710                    WorldKey::Name(func.name.clone())
711                }
712
713                ast::ExternKind::Path(path) => {
714                    let (item, name, span) = self.resolve_ast_item_path(path)?;
715                    let id = self.extract_iface_from_item(&item, &name, span)?;
716                    WorldKey::Interface(id)
717                }
718            };
719            if let WorldItem::Interface { id, .. } = world_item {
720                if !interfaces.insert(id) {
721                    bail!(Error::new(
722                        kind.span(),
723                        format!("interface cannot be {desc}ed more than once"),
724                    ))
725                }
726            }
727            let dst = if desc == "import" {
728                &mut self.worlds[world_id].imports
729            } else {
730                &mut self.worlds[world_id].exports
731            };
732            let prev = dst.insert(key.clone(), world_item);
733            if let Some(prev) = prev {
734                let prev = match prev {
735                    WorldItem::Interface { .. } => "interface",
736                    WorldItem::Function(..) => "func",
737                    WorldItem::Type(..) => "type",
738                };
739                let name = match key {
740                    WorldKey::Name(name) => name,
741                    WorldKey::Interface(..) => unreachable!(),
742                };
743                bail!(Error::new(
744                    kind.span(),
745                    format!("{desc} `{name}` conflicts with prior {prev} of same name",),
746                ))
747            }
748            spans.push(kind.span());
749        }
750        self.world_spans[world_id.index()].imports = import_spans;
751        self.world_spans[world_id.index()].exports = export_spans;
752        self.type_lookup.clear();
753
754        Ok(world_id)
755    }
756
757    fn resolve_world_item(
758        &mut self,
759        docs: &ast::Docs<'a>,
760        attrs: &[ast::Attribute<'a>],
761        kind: &ast::ExternKind<'a>,
762    ) -> Result<WorldItem> {
763        match kind {
764            ast::ExternKind::Interface(name, items) => {
765                let prev = mem::take(&mut self.type_lookup);
766                let id = self.alloc_interface(name.span);
767                self.resolve_interface(id, items, docs, attrs)?;
768                self.type_lookup = prev;
769                let stability = self.interfaces[id].stability.clone();
770                Ok(WorldItem::Interface { id, stability })
771            }
772            ast::ExternKind::Path(path) => {
773                let stability = self.stability(attrs)?;
774                let (item, name, span) = self.resolve_ast_item_path(path)?;
775                let id = self.extract_iface_from_item(&item, &name, span)?;
776                Ok(WorldItem::Interface { id, stability })
777            }
778            ast::ExternKind::Func(name, func) => {
779                let prefix = if func.async_ { "[async]" } else { "" };
780                let name = format!("{prefix}{}", name.name);
781                let func = self.resolve_function(
782                    docs,
783                    attrs,
784                    &name,
785                    func,
786                    if func.async_ {
787                        FunctionKind::AsyncFreestanding
788                    } else {
789                        FunctionKind::Freestanding
790                    },
791                )?;
792                Ok(WorldItem::Function(func))
793            }
794        }
795    }
796
797    fn resolve_interface(
798        &mut self,
799        interface_id: InterfaceId,
800        fields: &[ast::InterfaceItem<'a>],
801        docs: &ast::Docs<'a>,
802        attrs: &[ast::Attribute<'a>],
803    ) -> Result<()> {
804        let docs = self.docs(docs);
805        self.interfaces[interface_id].docs = docs;
806        let stability = self.stability(attrs)?;
807        self.interfaces[interface_id].stability = stability;
808
809        self.resolve_types(
810            TypeOwner::Interface(interface_id),
811            fields.iter().filter_map(|i| match i {
812                ast::InterfaceItem::Use(u) => Some(TypeItem::Use(u)),
813                ast::InterfaceItem::TypeDef(t) => Some(TypeItem::Def(t)),
814                ast::InterfaceItem::Func(_) => None,
815            }),
816        )?;
817
818        for (name, (ty, _)) in self.type_lookup.iter() {
819            match *ty {
820                TypeOrItem::Type(id) => {
821                    self.interfaces[interface_id]
822                        .types
823                        .insert(name.to_string(), id);
824                }
825                TypeOrItem::Item(_) => unreachable!(),
826            }
827        }
828
829        // Finally process all function definitions now that all types are
830        // defined.
831        let mut funcs = Vec::new();
832        for field in fields {
833            match field {
834                ast::InterfaceItem::Func(f) => {
835                    self.define_interface_name(&f.name, TypeOrItem::Item("function"))?;
836                    let prefix = if f.func.async_ { "[async]" } else { "" };
837                    let name = format!("{prefix}{}", f.name.name);
838                    funcs.push(self.resolve_function(
839                        &f.docs,
840                        &f.attributes,
841                        &name,
842                        &f.func,
843                        if f.func.async_ {
844                            FunctionKind::AsyncFreestanding
845                        } else {
846                            FunctionKind::Freestanding
847                        },
848                    )?);
849                    self.interface_spans[interface_id.index()]
850                        .funcs
851                        .push(f.name.span);
852                }
853                ast::InterfaceItem::Use(_) => {}
854                ast::InterfaceItem::TypeDef(ast::TypeDef {
855                    name,
856                    ty: ast::Type::Resource(r),
857                    ..
858                }) => {
859                    for func in r.funcs.iter() {
860                        funcs.push(self.resolve_resource_func(func, name)?);
861                        self.interface_spans[interface_id.index()]
862                            .funcs
863                            .push(func.named_func().name.span);
864                    }
865                }
866                ast::InterfaceItem::TypeDef(_) => {}
867            }
868        }
869        for func in funcs {
870            let prev = self.interfaces[interface_id]
871                .functions
872                .insert(func.name.clone(), func);
873            assert!(prev.is_none());
874        }
875
876        let lookup = mem::take(&mut self.type_lookup);
877        self.interface_types[interface_id.index()] = lookup;
878
879        Ok(())
880    }
881
882    fn resolve_types<'b>(
883        &mut self,
884        owner: TypeOwner,
885        fields: impl Iterator<Item = TypeItem<'a, 'b>> + Clone,
886    ) -> Result<()>
887    where
888        'a: 'b,
889    {
890        assert!(self.type_lookup.is_empty());
891
892        // First, populate our namespace with `use` statements
893        for field in fields.clone() {
894            match field {
895                TypeItem::Use(u) => {
896                    self.resolve_use(owner, u)?;
897                }
898                TypeItem::Def(_) => {}
899            }
900        }
901
902        // Next determine dependencies between types, perform a topological
903        // sort, and then define all types. This will define types in a
904        // topological fashion, forbid cycles, and weed out references to
905        // undefined types all in one go.
906        let mut type_deps = IndexMap::new();
907        let mut type_defs = IndexMap::new();
908        for field in fields {
909            match field {
910                TypeItem::Def(t) => {
911                    let prev = type_defs.insert(t.name.name, Some(t));
912                    if prev.is_some() {
913                        bail!(Error::new(
914                            t.name.span,
915                            format!("name `{}` is defined more than once", t.name.name),
916                        ))
917                    }
918                    let mut deps = Vec::new();
919                    collect_deps(&t.ty, &mut deps);
920                    type_deps.insert(t.name.name, deps);
921                }
922                TypeItem::Use(u) => {
923                    for name in u.names.iter() {
924                        let name = name.as_.as_ref().unwrap_or(&name.name);
925                        type_deps.insert(name.name, Vec::new());
926                        type_defs.insert(name.name, None);
927                    }
928                }
929            }
930        }
931        let order = toposort("type", &type_deps).map_err(attach_old_float_type_context)?;
932        for ty in order {
933            let def = match type_defs.swap_remove(&ty).unwrap() {
934                Some(def) => def,
935                None => continue,
936            };
937            let docs = self.docs(&def.docs);
938            let stability = self.stability(&def.attributes)?;
939            let kind = self.resolve_type_def(&def.ty, &stability)?;
940            let id = self.types.alloc(TypeDef {
941                docs,
942                stability,
943                kind,
944                name: Some(def.name.name.to_string()),
945                owner,
946            });
947            self.type_spans.push(def.name.span);
948            self.define_interface_name(&def.name, TypeOrItem::Type(id))?;
949        }
950        return Ok(());
951
952        fn attach_old_float_type_context(err: ast::toposort::Error) -> anyhow::Error {
953            let name = match &err {
954                ast::toposort::Error::NonexistentDep { name, .. } => name,
955                _ => return err.into(),
956            };
957            let new = match name.as_str() {
958                "float32" => "f32",
959                "float64" => "f64",
960                _ => return err.into(),
961            };
962
963            let context = format!(
964                "the `{name}` type has been renamed to `{new}` and is \
965                 no longer accepted, but the `WIT_REQUIRE_F32_F64=0` \
966                 environment variable can be used to temporarily \
967                 disable this error"
968            );
969            anyhow::Error::from(err).context(context)
970        }
971    }
972
973    fn resolve_use(&mut self, owner: TypeOwner, u: &ast::Use<'a>) -> Result<()> {
974        let (item, name, span) = self.resolve_ast_item_path(&u.from)?;
975        let use_from = self.extract_iface_from_item(&item, &name, span)?;
976        let stability = self.stability(&u.attributes)?;
977
978        for name in u.names.iter() {
979            let lookup = &self.interface_types[use_from.index()];
980            let id = match lookup.get(name.name.name) {
981                Some((TypeOrItem::Type(id), _)) => *id,
982                Some((TypeOrItem::Item(s), _)) => {
983                    bail!(Error::new(
984                        name.name.span,
985                        format!("cannot import {s} `{}`", name.name.name),
986                    ))
987                }
988                None => bail!(Error::new(
989                    name.name.span,
990                    format!("name `{}` is not defined", name.name.name),
991                )),
992            };
993            self.type_spans.push(name.name.span);
994            let name = name.as_.as_ref().unwrap_or(&name.name);
995            let id = self.types.alloc(TypeDef {
996                docs: Docs::default(),
997                stability: stability.clone(),
998                kind: TypeDefKind::Type(Type::Id(id)),
999                name: Some(name.name.to_string()),
1000                owner,
1001            });
1002            self.define_interface_name(name, TypeOrItem::Type(id))?;
1003        }
1004        Ok(())
1005    }
1006
1007    /// For each name in the `include`, resolve the path of the include, add it to the self.includes
1008    fn resolve_include(&mut self, world_id: WorldId, i: &ast::Include<'a>) -> Result<()> {
1009        let stability = self.stability(&i.attributes)?;
1010        let (item, name, span) = self.resolve_ast_item_path(&i.from)?;
1011        let include_from = self.extract_world_from_item(&item, &name, span)?;
1012        self.worlds[world_id]
1013            .includes
1014            .push((stability, include_from));
1015        self.worlds[world_id].include_names.push(
1016            i.names
1017                .iter()
1018                .map(|n| IncludeName {
1019                    name: n.name.name.to_string(),
1020                    as_: n.as_.name.to_string(),
1021                })
1022                .collect(),
1023        );
1024        self.world_spans[world_id.index()].includes.push(span);
1025        Ok(())
1026    }
1027
1028    fn resolve_resource_func(
1029        &mut self,
1030        func: &ast::ResourceFunc<'_>,
1031        resource: &ast::Id<'_>,
1032    ) -> Result<Function> {
1033        let resource_id = match self.type_lookup.get(resource.name) {
1034            Some((TypeOrItem::Type(id), _)) => *id,
1035            _ => panic!("type lookup for resource failed"),
1036        };
1037        let (name, kind);
1038        let named_func = func.named_func();
1039        let async_ = named_func.func.async_;
1040        match func {
1041            ast::ResourceFunc::Method(f) => {
1042                let prefix = if async_ { "[async method]" } else { "[method]" };
1043                name = format!("{prefix}{}.{}", resource.name, f.name.name);
1044                kind = if async_ {
1045                    FunctionKind::AsyncMethod(resource_id)
1046                } else {
1047                    FunctionKind::Method(resource_id)
1048                };
1049            }
1050            ast::ResourceFunc::Static(f) => {
1051                let prefix = if async_ { "[async static]" } else { "[static]" };
1052                name = format!("{prefix}{}.{}", resource.name, f.name.name);
1053                kind = if async_ {
1054                    FunctionKind::AsyncStatic(resource_id)
1055                } else {
1056                    FunctionKind::Static(resource_id)
1057                };
1058            }
1059            ast::ResourceFunc::Constructor(_) => {
1060                assert!(!async_); // should not be possible to parse
1061                name = format!("[constructor]{}", resource.name);
1062                kind = FunctionKind::Constructor(resource_id);
1063            }
1064        }
1065        self.resolve_function(
1066            &named_func.docs,
1067            &named_func.attributes,
1068            &name,
1069            &named_func.func,
1070            kind,
1071        )
1072    }
1073
1074    fn resolve_function(
1075        &mut self,
1076        docs: &ast::Docs<'_>,
1077        attrs: &[ast::Attribute<'_>],
1078        name: &str,
1079        func: &ast::Func,
1080        kind: FunctionKind,
1081    ) -> Result<Function> {
1082        let docs = self.docs(docs);
1083        let stability = self.stability(attrs)?;
1084        let params = self.resolve_params(&func.params, &kind, func.span)?;
1085        let result = self.resolve_result(&func.result, &kind, func.span)?;
1086        Ok(Function {
1087            docs,
1088            stability,
1089            name: name.to_string(),
1090            kind,
1091            params,
1092            result,
1093        })
1094    }
1095
1096    fn resolve_ast_item_path(&self, path: &ast::UsePath<'a>) -> Result<(AstItem, String, Span)> {
1097        match path {
1098            ast::UsePath::Id(id) => {
1099                let item = self.ast_items[self.cur_ast_index]
1100                    .get(id.name)
1101                    .or_else(|| self.package_items.get(id.name));
1102                match item {
1103                    Some(item) => Ok((*item, id.name.into(), id.span)),
1104                    None => {
1105                        bail!(Error::new(
1106                            id.span,
1107                            format!("interface or world `{}` does not exist", id.name),
1108                        ))
1109                    }
1110                }
1111            }
1112            ast::UsePath::Package { id, name } => Ok((
1113                self.foreign_deps[&id.package_name()][name.name],
1114                name.name.into(),
1115                name.span,
1116            )),
1117        }
1118    }
1119
1120    fn extract_iface_from_item(
1121        &self,
1122        item: &AstItem,
1123        name: &str,
1124        span: Span,
1125    ) -> Result<InterfaceId> {
1126        match item {
1127            AstItem::Interface(id) => Ok(*id),
1128            AstItem::World(_) => {
1129                bail!(Error::new(
1130                    span,
1131                    format!("name `{name}` is defined as a world, not an interface"),
1132                ))
1133            }
1134        }
1135    }
1136
1137    fn extract_world_from_item(&self, item: &AstItem, name: &str, span: Span) -> Result<WorldId> {
1138        match item {
1139            AstItem::World(id) => Ok(*id),
1140            AstItem::Interface(_) => {
1141                bail!(Error::new(
1142                    span,
1143                    format!("name `{name}` is defined as an interface, not a world"),
1144                ))
1145            }
1146        }
1147    }
1148
1149    fn define_interface_name(&mut self, name: &ast::Id<'a>, item: TypeOrItem) -> Result<()> {
1150        let prev = self.type_lookup.insert(name.name, (item, name.span));
1151        if prev.is_some() {
1152            bail!(Error::new(
1153                name.span,
1154                format!("name `{}` is defined more than once", name.name),
1155            ))
1156        } else {
1157            Ok(())
1158        }
1159    }
1160
1161    fn resolve_type_def(
1162        &mut self,
1163        ty: &ast::Type<'_>,
1164        stability: &Stability,
1165    ) -> Result<TypeDefKind> {
1166        Ok(match ty {
1167            ast::Type::Bool(_) => TypeDefKind::Type(Type::Bool),
1168            ast::Type::U8(_) => TypeDefKind::Type(Type::U8),
1169            ast::Type::U16(_) => TypeDefKind::Type(Type::U16),
1170            ast::Type::U32(_) => TypeDefKind::Type(Type::U32),
1171            ast::Type::U64(_) => TypeDefKind::Type(Type::U64),
1172            ast::Type::S8(_) => TypeDefKind::Type(Type::S8),
1173            ast::Type::S16(_) => TypeDefKind::Type(Type::S16),
1174            ast::Type::S32(_) => TypeDefKind::Type(Type::S32),
1175            ast::Type::S64(_) => TypeDefKind::Type(Type::S64),
1176            ast::Type::F32(_) => TypeDefKind::Type(Type::F32),
1177            ast::Type::F64(_) => TypeDefKind::Type(Type::F64),
1178            ast::Type::Char(_) => TypeDefKind::Type(Type::Char),
1179            ast::Type::String(_) => TypeDefKind::Type(Type::String),
1180            ast::Type::ErrorContext(_) => TypeDefKind::Type(Type::ErrorContext),
1181            ast::Type::Name(name) => {
1182                let id = self.resolve_type_name(name)?;
1183                TypeDefKind::Type(Type::Id(id))
1184            }
1185            ast::Type::List(list) => {
1186                let ty = self.resolve_type(&list.ty, stability)?;
1187                TypeDefKind::List(ty)
1188            }
1189            ast::Type::FixedSizeList(list) => {
1190                let ty = self.resolve_type(&list.ty, stability)?;
1191                TypeDefKind::FixedSizeList(ty, list.size)
1192            }
1193            ast::Type::Handle(handle) => TypeDefKind::Handle(match handle {
1194                ast::Handle::Own { resource } => Handle::Own(self.validate_resource(resource)?),
1195                ast::Handle::Borrow { resource } => {
1196                    Handle::Borrow(self.validate_resource(resource)?)
1197                }
1198            }),
1199            ast::Type::Resource(resource) => {
1200                // Validate here that the resource doesn't have any duplicate-ly
1201                // named methods and that there's at most one constructor.
1202                let mut ctors = 0;
1203                let mut names = HashSet::new();
1204                for func in resource.funcs.iter() {
1205                    match func {
1206                        ast::ResourceFunc::Method(f) | ast::ResourceFunc::Static(f) => {
1207                            if !names.insert(&f.name.name) {
1208                                bail!(Error::new(
1209                                    f.name.span,
1210                                    format!("duplicate function name `{}`", f.name.name),
1211                                ))
1212                            }
1213                        }
1214                        ast::ResourceFunc::Constructor(f) => {
1215                            ctors += 1;
1216                            if ctors > 1 {
1217                                bail!(Error::new(f.name.span, "duplicate constructors"))
1218                            }
1219                        }
1220                    }
1221                }
1222
1223                TypeDefKind::Resource
1224            }
1225            ast::Type::Record(record) => {
1226                let fields = record
1227                    .fields
1228                    .iter()
1229                    .map(|field| {
1230                        Ok(Field {
1231                            docs: self.docs(&field.docs),
1232                            name: field.name.name.to_string(),
1233                            ty: self.resolve_type(&field.ty, stability)?,
1234                        })
1235                    })
1236                    .collect::<Result<Vec<_>>>()?;
1237                TypeDefKind::Record(Record { fields })
1238            }
1239            ast::Type::Flags(flags) => {
1240                let flags = flags
1241                    .flags
1242                    .iter()
1243                    .map(|flag| Flag {
1244                        docs: self.docs(&flag.docs),
1245                        name: flag.name.name.to_string(),
1246                    })
1247                    .collect::<Vec<_>>();
1248                TypeDefKind::Flags(Flags { flags })
1249            }
1250            ast::Type::Tuple(t) => {
1251                let types = t
1252                    .types
1253                    .iter()
1254                    .map(|ty| self.resolve_type(ty, stability))
1255                    .collect::<Result<Vec<_>>>()?;
1256                TypeDefKind::Tuple(Tuple { types })
1257            }
1258            ast::Type::Variant(variant) => {
1259                if variant.cases.is_empty() {
1260                    bail!(Error::new(variant.span, "empty variant"))
1261                }
1262                let cases = variant
1263                    .cases
1264                    .iter()
1265                    .map(|case| {
1266                        Ok(Case {
1267                            docs: self.docs(&case.docs),
1268                            name: case.name.name.to_string(),
1269                            ty: self.resolve_optional_type(case.ty.as_ref(), stability)?,
1270                        })
1271                    })
1272                    .collect::<Result<Vec<_>>>()?;
1273                TypeDefKind::Variant(Variant { cases })
1274            }
1275            ast::Type::Enum(e) => {
1276                if e.cases.is_empty() {
1277                    bail!(Error::new(e.span, "empty enum"))
1278                }
1279                let cases = e
1280                    .cases
1281                    .iter()
1282                    .map(|case| {
1283                        Ok(EnumCase {
1284                            docs: self.docs(&case.docs),
1285                            name: case.name.name.to_string(),
1286                        })
1287                    })
1288                    .collect::<Result<Vec<_>>>()?;
1289                TypeDefKind::Enum(Enum { cases })
1290            }
1291            ast::Type::Option(ty) => TypeDefKind::Option(self.resolve_type(&ty.ty, stability)?),
1292            ast::Type::Result(r) => TypeDefKind::Result(Result_ {
1293                ok: self.resolve_optional_type(r.ok.as_deref(), stability)?,
1294                err: self.resolve_optional_type(r.err.as_deref(), stability)?,
1295            }),
1296            ast::Type::Future(t) => {
1297                TypeDefKind::Future(self.resolve_optional_type(t.ty.as_deref(), stability)?)
1298            }
1299            ast::Type::Stream(s) => {
1300                TypeDefKind::Stream(self.resolve_optional_type(s.ty.as_deref(), stability)?)
1301            }
1302        })
1303    }
1304
1305    fn resolve_type_name(&mut self, name: &ast::Id<'_>) -> Result<TypeId> {
1306        match self.type_lookup.get(name.name) {
1307            Some((TypeOrItem::Type(id), _)) => Ok(*id),
1308            Some((TypeOrItem::Item(s), _)) => bail!(Error::new(
1309                name.span,
1310                format!("cannot use {s} `{name}` as a type", name = name.name),
1311            )),
1312            None => bail!(Error::new(
1313                name.span,
1314                format!("name `{name}` is not defined", name = name.name),
1315            )),
1316        }
1317    }
1318
1319    fn validate_resource(&mut self, name: &ast::Id<'_>) -> Result<TypeId> {
1320        let id = self.resolve_type_name(name)?;
1321        let mut cur = id;
1322        loop {
1323            match self.types[cur].kind {
1324                TypeDefKind::Resource => break Ok(id),
1325                TypeDefKind::Type(Type::Id(ty)) => cur = ty,
1326                TypeDefKind::Unknown => {
1327                    self.required_resource_types.push((cur, name.span));
1328                    break Ok(id);
1329                }
1330                _ => bail!(Error::new(
1331                    name.span,
1332                    format!("type `{}` used in a handle must be a resource", name.name),
1333                )),
1334            }
1335        }
1336    }
1337
1338    /// If `stability` is `Stability::Unknown`, recursively inspect the
1339    /// specified `kind` until we either bottom out or find a type which has a
1340    /// stability that's _not_ unknown.  If we find such a type, return a clone
1341    /// of its stability; otherwise return `Stability::Unknown`.
1342    ///
1343    /// The idea here is that e.g. `option<T>` should inherit `T`'s stability.
1344    /// This gets a little ambiguous in the case of e.g. `tuple<T, U, V>`; for
1345    /// now, we just pick the first one has a known stability, if any.
1346    fn find_stability(&self, kind: &TypeDefKind, stability: &Stability) -> Stability {
1347        fn find_in_type(types: &Arena<TypeDef>, ty: Type) -> Option<&Stability> {
1348            if let Type::Id(id) = ty {
1349                let ty = &types[id];
1350                if !matches!(&ty.stability, Stability::Unknown) {
1351                    Some(&ty.stability)
1352                } else {
1353                    // Note that this type isn't searched recursively since the
1354                    // creation of `id` should already have searched its
1355                    // recursive edges, so there's no need to search again.
1356                    None
1357                }
1358            } else {
1359                None
1360            }
1361        }
1362
1363        fn find_in_kind<'a>(
1364            types: &'a Arena<TypeDef>,
1365            kind: &TypeDefKind,
1366        ) -> Option<&'a Stability> {
1367            match kind {
1368                TypeDefKind::Type(ty) => find_in_type(types, *ty),
1369                TypeDefKind::Handle(Handle::Borrow(id) | Handle::Own(id)) => {
1370                    find_in_type(types, Type::Id(*id))
1371                }
1372                TypeDefKind::Tuple(t) => t.types.iter().find_map(|ty| find_in_type(types, *ty)),
1373                TypeDefKind::List(ty)
1374                | TypeDefKind::FixedSizeList(ty, _)
1375                | TypeDefKind::Option(ty) => find_in_type(types, *ty),
1376                TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
1377                    ty.as_ref().and_then(|ty| find_in_type(types, *ty))
1378                }
1379                TypeDefKind::Result(r) => {
1380                    r.ok.as_ref()
1381                        .and_then(|ty| find_in_type(types, *ty))
1382                        .or_else(|| r.err.as_ref().and_then(|ty| find_in_type(types, *ty)))
1383                }
1384                // Assume these are named types which will be annotated with an
1385                // explicit stability if applicable:
1386                TypeDefKind::Resource
1387                | TypeDefKind::Variant(_)
1388                | TypeDefKind::Record(_)
1389                | TypeDefKind::Flags(_)
1390                | TypeDefKind::Enum(_)
1391                | TypeDefKind::Unknown => None,
1392            }
1393        }
1394
1395        if let Stability::Unknown = stability {
1396            find_in_kind(&self.types, kind)
1397                .cloned()
1398                .unwrap_or(Stability::Unknown)
1399        } else {
1400            stability.clone()
1401        }
1402    }
1403
1404    fn resolve_type(&mut self, ty: &super::Type<'_>, stability: &Stability) -> Result<Type> {
1405        // Resources must be declared at the top level to have their methods
1406        // processed appropriately, but resources also shouldn't show up
1407        // recursively so assert that's not happening here.
1408        match ty {
1409            ast::Type::Resource(_) => unreachable!(),
1410            _ => {}
1411        }
1412        let kind = self.resolve_type_def(ty, stability)?;
1413        let stability = self.find_stability(&kind, stability);
1414        Ok(self.anon_type_def(
1415            TypeDef {
1416                kind,
1417                name: None,
1418                docs: Docs::default(),
1419                stability,
1420                owner: TypeOwner::None,
1421            },
1422            ty.span(),
1423        ))
1424    }
1425
1426    fn resolve_optional_type(
1427        &mut self,
1428        ty: Option<&super::Type<'_>>,
1429        stability: &Stability,
1430    ) -> Result<Option<Type>> {
1431        match ty {
1432            Some(ty) => Ok(Some(self.resolve_type(ty, stability)?)),
1433            None => Ok(None),
1434        }
1435    }
1436
1437    fn anon_type_def(&mut self, ty: TypeDef, span: Span) -> Type {
1438        let key = match &ty.kind {
1439            TypeDefKind::Type(t) => return *t,
1440            TypeDefKind::Variant(v) => Key::Variant(
1441                v.cases
1442                    .iter()
1443                    .map(|case| (case.name.clone(), case.ty))
1444                    .collect::<Vec<_>>(),
1445            ),
1446            TypeDefKind::Handle(Handle::Borrow(h)) => Key::BorrowHandle(*h),
1447            // An anonymous `own<T>` type is the same as a reference to the type
1448            // `T`, so avoid creating anonymous type and return that here
1449            // directly. Note that this additionally avoids creating distinct
1450            // anonymous types for `list<T>` and `list<own<T>>` for example.
1451            TypeDefKind::Handle(Handle::Own(id)) => return Type::Id(*id),
1452            TypeDefKind::Resource => unreachable!("anonymous resources aren't supported"),
1453            TypeDefKind::Record(r) => Key::Record(
1454                r.fields
1455                    .iter()
1456                    .map(|case| (case.name.clone(), case.ty))
1457                    .collect::<Vec<_>>(),
1458            ),
1459            TypeDefKind::Flags(r) => {
1460                Key::Flags(r.flags.iter().map(|f| f.name.clone()).collect::<Vec<_>>())
1461            }
1462            TypeDefKind::Tuple(t) => Key::Tuple(t.types.clone()),
1463            TypeDefKind::Enum(r) => {
1464                Key::Enum(r.cases.iter().map(|f| f.name.clone()).collect::<Vec<_>>())
1465            }
1466            TypeDefKind::List(ty) => Key::List(*ty),
1467            TypeDefKind::FixedSizeList(ty, size) => Key::FixedSizeList(*ty, *size),
1468            TypeDefKind::Option(t) => Key::Option(*t),
1469            TypeDefKind::Result(r) => Key::Result(r.ok, r.err),
1470            TypeDefKind::Future(ty) => Key::Future(*ty),
1471            TypeDefKind::Stream(ty) => Key::Stream(*ty),
1472            TypeDefKind::Unknown => unreachable!(),
1473        };
1474        let id = self.anon_types.entry(key).or_insert_with(|| {
1475            self.type_spans.push(span);
1476            self.types.alloc(ty)
1477        });
1478        Type::Id(*id)
1479    }
1480
1481    fn docs(&mut self, doc: &super::Docs<'_>) -> Docs {
1482        let mut docs = vec![];
1483
1484        for doc in doc.docs.iter() {
1485            let contents = match doc.strip_prefix("/**") {
1486                Some(doc) => doc.strip_suffix("*/").unwrap(),
1487                None => doc.trim_start_matches('/'),
1488            };
1489
1490            docs.push(contents.trim_end());
1491        }
1492
1493        // Scan the (non-empty) doc lines to find the minimum amount of leading whitespace.
1494        // This amount of whitespace will be removed from the start of all doc lines,
1495        // normalizing the output while retaining intentional spacing added by the original authors.
1496        let min_leading_ws = docs
1497            .iter()
1498            .filter(|doc| !doc.is_empty())
1499            .map(|doc| doc.bytes().take_while(|c| c.is_ascii_whitespace()).count())
1500            .min()
1501            .unwrap_or(0);
1502
1503        if min_leading_ws > 0 {
1504            let leading_ws_pattern = " ".repeat(min_leading_ws);
1505            docs = docs
1506                .iter()
1507                .map(|doc| doc.strip_prefix(&leading_ws_pattern).unwrap_or(doc))
1508                .collect();
1509        }
1510
1511        let contents = if docs.is_empty() {
1512            None
1513        } else {
1514            // NB: this notably, through the use of `lines`, normalizes `\r\n`
1515            // to `\n`.
1516            let mut contents = String::new();
1517            for doc in docs {
1518                if doc.is_empty() {
1519                    contents.push_str("\n");
1520                } else {
1521                    for line in doc.lines() {
1522                        contents.push_str(line);
1523                        contents.push_str("\n");
1524                    }
1525                }
1526            }
1527            while contents.ends_with("\n") {
1528                contents.pop();
1529            }
1530            Some(contents)
1531        };
1532        Docs { contents }
1533    }
1534
1535    fn stability(&mut self, attrs: &[ast::Attribute<'_>]) -> Result<Stability> {
1536        match attrs {
1537            [] => Ok(Stability::Unknown),
1538
1539            [ast::Attribute::Since { version, .. }] => Ok(Stability::Stable {
1540                since: version.clone(),
1541                deprecated: None,
1542            }),
1543
1544            [
1545                ast::Attribute::Since { version, .. },
1546                ast::Attribute::Deprecated {
1547                    version: deprecated,
1548                    ..
1549                },
1550            ]
1551            | [
1552                ast::Attribute::Deprecated {
1553                    version: deprecated,
1554                    ..
1555                },
1556                ast::Attribute::Since { version, .. },
1557            ] => Ok(Stability::Stable {
1558                since: version.clone(),
1559                deprecated: Some(deprecated.clone()),
1560            }),
1561
1562            [ast::Attribute::Unstable { feature, .. }] => Ok(Stability::Unstable {
1563                feature: feature.name.to_string(),
1564                deprecated: None,
1565            }),
1566
1567            [
1568                ast::Attribute::Unstable { feature, .. },
1569                ast::Attribute::Deprecated { version, .. },
1570            ]
1571            | [
1572                ast::Attribute::Deprecated { version, .. },
1573                ast::Attribute::Unstable { feature, .. },
1574            ] => Ok(Stability::Unstable {
1575                feature: feature.name.to_string(),
1576                deprecated: Some(version.clone()),
1577            }),
1578            [ast::Attribute::Deprecated { span, .. }] => {
1579                bail!(Error::new(
1580                    *span,
1581                    "must pair @deprecated with either @since or @unstable",
1582                ))
1583            }
1584            [_, b, ..] => {
1585                bail!(Error::new(
1586                    b.span(),
1587                    "unsupported combination of attributes",
1588                ))
1589            }
1590        }
1591    }
1592
1593    fn resolve_params(
1594        &mut self,
1595        params: &ParamList<'_>,
1596        kind: &FunctionKind,
1597        span: Span,
1598    ) -> Result<Vec<(String, Type)>> {
1599        let mut ret = IndexMap::new();
1600        match *kind {
1601            // These kinds of methods don't have any adjustments to the
1602            // parameters, so do nothing here.
1603            FunctionKind::Freestanding
1604            | FunctionKind::AsyncFreestanding
1605            | FunctionKind::Constructor(_)
1606            | FunctionKind::Static(_)
1607            | FunctionKind::AsyncStatic(_) => {}
1608
1609            // Methods automatically get a `self` initial argument so insert
1610            // that here before processing the normal parameters.
1611            FunctionKind::Method(id) | FunctionKind::AsyncMethod(id) => {
1612                let kind = TypeDefKind::Handle(Handle::Borrow(id));
1613                let stability = self.find_stability(&kind, &Stability::Unknown);
1614                let shared = self.anon_type_def(
1615                    TypeDef {
1616                        docs: Docs::default(),
1617                        stability,
1618                        kind,
1619                        name: None,
1620                        owner: TypeOwner::None,
1621                    },
1622                    span,
1623                );
1624                ret.insert("self".to_string(), shared);
1625            }
1626        }
1627        for (name, ty) in params {
1628            let prev = ret.insert(
1629                name.name.to_string(),
1630                self.resolve_type(ty, &Stability::Unknown)?,
1631            );
1632            if prev.is_some() {
1633                bail!(Error::new(
1634                    name.span,
1635                    format!("param `{}` is defined more than once", name.name),
1636                ))
1637            }
1638        }
1639        Ok(ret.into_iter().collect())
1640    }
1641
1642    fn resolve_result(
1643        &mut self,
1644        result: &Option<ast::Type<'_>>,
1645        kind: &FunctionKind,
1646        _span: Span,
1647    ) -> Result<Option<Type>> {
1648        match *kind {
1649            // These kinds of methods don't have any adjustments to the return
1650            // values, so plumb them through as-is.
1651            FunctionKind::Freestanding
1652            | FunctionKind::AsyncFreestanding
1653            | FunctionKind::Method(_)
1654            | FunctionKind::AsyncMethod(_)
1655            | FunctionKind::Static(_)
1656            | FunctionKind::AsyncStatic(_) => match result {
1657                Some(ty) => Ok(Some(self.resolve_type(ty, &Stability::Unknown)?)),
1658                None => Ok(None),
1659            },
1660
1661            // Constructors are alwys parsed as 0 returned types but they're
1662            // automatically translated as a single return type of the type that
1663            // it's a constructor for.
1664            FunctionKind::Constructor(id) => {
1665                assert!(result.is_none());
1666                Ok(Some(Type::Id(id)))
1667            }
1668        }
1669    }
1670}
1671
1672fn collect_deps<'a>(ty: &ast::Type<'a>, deps: &mut Vec<ast::Id<'a>>) {
1673    match ty {
1674        ast::Type::Bool(_)
1675        | ast::Type::U8(_)
1676        | ast::Type::U16(_)
1677        | ast::Type::U32(_)
1678        | ast::Type::U64(_)
1679        | ast::Type::S8(_)
1680        | ast::Type::S16(_)
1681        | ast::Type::S32(_)
1682        | ast::Type::S64(_)
1683        | ast::Type::F32(_)
1684        | ast::Type::F64(_)
1685        | ast::Type::Char(_)
1686        | ast::Type::String(_)
1687        | ast::Type::Flags(_)
1688        | ast::Type::Enum(_)
1689        | ast::Type::ErrorContext(_) => {}
1690        ast::Type::Name(name) => deps.push(name.clone()),
1691        ast::Type::Handle(handle) => match handle {
1692            ast::Handle::Own { resource } => deps.push(resource.clone()),
1693            ast::Handle::Borrow { resource } => deps.push(resource.clone()),
1694        },
1695        ast::Type::Resource(_) => {}
1696        ast::Type::Record(record) => {
1697            for field in record.fields.iter() {
1698                collect_deps(&field.ty, deps);
1699            }
1700        }
1701        ast::Type::Tuple(t) => {
1702            for ty in t.types.iter() {
1703                collect_deps(ty, deps);
1704            }
1705        }
1706        ast::Type::Variant(variant) => {
1707            for case in variant.cases.iter() {
1708                if let Some(ty) = &case.ty {
1709                    collect_deps(ty, deps);
1710                }
1711            }
1712        }
1713        ast::Type::Option(ast::Option_ { ty, .. })
1714        | ast::Type::List(ast::List { ty, .. })
1715        | ast::Type::FixedSizeList(ast::FixedSizeList { ty, .. }) => collect_deps(ty, deps),
1716        ast::Type::Result(r) => {
1717            if let Some(ty) = &r.ok {
1718                collect_deps(ty, deps);
1719            }
1720            if let Some(ty) = &r.err {
1721                collect_deps(ty, deps);
1722            }
1723        }
1724        ast::Type::Future(t) => {
1725            if let Some(t) = &t.ty {
1726                collect_deps(t, deps)
1727            }
1728        }
1729        ast::Type::Stream(s) => {
1730            if let Some(t) = &s.ty {
1731                collect_deps(t, deps)
1732            }
1733        }
1734    }
1735}