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