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