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