/src/wasm-tools/crates/wit-parser/src/ast/resolve.rs
Line | Count | Source |
1 | | use super::{ParamList, WorldOrInterface}; |
2 | | use crate::alloc::borrow::ToOwned; |
3 | | use crate::ast::error::{ParseError, ParseErrorKind}; |
4 | | use crate::ast::toposort::toposort; |
5 | | use crate::*; |
6 | | use alloc::string::{String, ToString}; |
7 | | use alloc::vec::Vec; |
8 | | use alloc::{format, vec}; |
9 | | use core::mem; |
10 | | use wasmparser::names::{ComponentName, ComponentNameKind, KebabStr}; |
11 | | |
12 | | #[derive(Default)] |
13 | | pub struct Resolver<'a> { |
14 | | /// Current package name learned through the ASTs pushed onto this resolver. |
15 | | package_name: Option<(PackageName, Span)>, |
16 | | |
17 | | /// Package docs. |
18 | | package_docs: Docs, |
19 | | |
20 | | /// All non-`package` WIT decls are going to be resolved together. |
21 | | decl_lists: Vec<ast::DeclList<'a>>, |
22 | | |
23 | | // Arenas that get plumbed to the final `UnresolvedPackage` |
24 | | types: Arena<TypeDef>, |
25 | | interfaces: Arena<Interface>, |
26 | | worlds: Arena<World>, |
27 | | |
28 | | // Interning structure for types which-need-not-be-named such as |
29 | | // `list<string>` and such. |
30 | | anon_types: HashMap<Key, TypeId>, |
31 | | |
32 | | /// The index within `self.ast_items` that lookups should go through. This |
33 | | /// is updated as the ASTs are walked. |
34 | | cur_ast_index: usize, |
35 | | |
36 | | /// A map per `ast::DeclList` which keeps track of the file's top level |
37 | | /// names in scope. This maps each name onto either a world or an interface, |
38 | | /// handling things like `use` at the top level. |
39 | | ast_items: Vec<IndexMap<&'a str, AstItem>>, |
40 | | |
41 | | /// A map for the entire package being created of all names defined within, |
42 | | /// along with the ID they're mapping to. |
43 | | package_items: IndexMap<&'a str, AstItem>, |
44 | | |
45 | | /// A per-interface map of name to item-in-the-interface. This is the same |
46 | | /// length as `self.types` and is pushed to whenever `self.types` is pushed |
47 | | /// to. |
48 | | interface_types: Vec<IndexMap<&'a str, (TypeOrItem, Span)>>, |
49 | | |
50 | | /// Metadata about foreign dependencies which are not defined in this |
51 | | /// package. This map is keyed by the name of the package being imported |
52 | | /// from. The next level of key is the name of the interface being imported |
53 | | /// from, and the final value is a tuple containing the assigned ID of the |
54 | | /// dependency, and a Vector of the Stability attributes associated with each |
55 | | /// of its imports. |
56 | | foreign_deps: IndexMap<PackageName, IndexMap<&'a str, (AstItem, Vec<Stability>)>>, |
57 | | |
58 | | /// All interfaces that are present within `self.foreign_deps`. |
59 | | foreign_interfaces: HashSet<InterfaceId>, |
60 | | |
61 | | foreign_worlds: HashSet<WorldId>, |
62 | | |
63 | | /// The current type lookup scope which will eventually make its way into |
64 | | /// `self.interface_types`. |
65 | | type_lookup: IndexMap<&'a str, (TypeOrItem, Span)>, |
66 | | |
67 | | /// An assigned span for where all types inserted into `self.types` as |
68 | | /// imported from foreign interfaces. These types all show up first in the |
69 | | /// `self.types` arena and this span is used to generate an error message |
70 | | /// pointing to it if the item isn't actually defined. |
71 | | unknown_type_spans: Vec<Span>, |
72 | | |
73 | | /// Spans per entry in `self.foreign_deps` for where the dependency was |
74 | | /// introduced to print an error message if necessary. |
75 | | foreign_dep_spans: Vec<Span>, |
76 | | |
77 | | /// A list of `TypeDefKind::Unknown` types which are required to be |
78 | | /// resources when this package is resolved against its dependencies. |
79 | | required_resource_types: Vec<(TypeId, Span)>, |
80 | | } |
81 | | |
82 | | #[derive(PartialEq, Eq, Hash)] |
83 | | enum Key { |
84 | | Variant(Vec<(String, Option<Type>)>), |
85 | | BorrowHandle(TypeId), |
86 | | Record(Vec<(String, Type)>), |
87 | | Flags(Vec<String>), |
88 | | Tuple(Vec<Type>), |
89 | | Enum(Vec<String>), |
90 | | List(Type), |
91 | | Map(Type, Type), |
92 | | FixedLengthList(Type, u32), |
93 | | Option(Type), |
94 | | Result(Option<Type>, Option<Type>), |
95 | | Future(Option<Type>), |
96 | | Stream(Option<Type>), |
97 | | } |
98 | | |
99 | | enum TypeItem<'a, 'b> { |
100 | | Use(&'b ast::Use<'a>), |
101 | | Def(&'b ast::TypeDef<'a>), |
102 | | } |
103 | | |
104 | | enum TypeOrItem { |
105 | | Type(TypeId), |
106 | | Item(&'static str), |
107 | | } |
108 | | |
109 | | impl<'a> Resolver<'a> { |
110 | 20.9k | pub(super) fn push(&mut self, file: ast::PackageFile<'a>) -> ParseResult<()> { |
111 | | // As each WIT file is pushed into this resolver keep track of the |
112 | | // current package name assigned. Only one file needs to mention it, but |
113 | | // if multiple mention it then they must all match. |
114 | 20.9k | if let Some(cur) = &file.package_id { |
115 | 15.7k | let cur_name = cur.package_name(); |
116 | 15.7k | if let Some((prev, _)) = &self.package_name { |
117 | 3.95k | if cur_name != *prev { |
118 | 0 | return Err(ParseError::new_syntax( |
119 | 0 | cur.span, |
120 | 0 | format!( |
121 | 0 | "package identifier `{cur_name}` does not match \ |
122 | 0 | previous package name of `{prev}`" |
123 | 0 | ), |
124 | 0 | )); |
125 | 3.95k | } |
126 | 11.8k | } |
127 | 15.7k | self.package_name = Some((cur_name, cur.span)); |
128 | | |
129 | | // At most one 'package' item can have doc comments. |
130 | 15.7k | let docs = self.docs(&cur.docs); |
131 | 15.7k | if docs.contents.is_some() { |
132 | 0 | if self.package_docs.contents.is_some() { |
133 | 0 | return Err(ParseError::new_syntax( |
134 | 0 | cur.docs.span, |
135 | 0 | "found doc comments on multiple 'package' items".to_owned(), |
136 | 0 | )); |
137 | 0 | } |
138 | 0 | self.package_docs = docs; |
139 | 15.7k | } |
140 | 5.17k | } |
141 | | |
142 | | // Ensure that there are no nested packages in `file`. Note that for |
143 | | // top level files nested packages are handled separately in `ast.rs` |
144 | | // with their own resolver. |
145 | 62.0k | for item in file.decl_list.items.iter() { |
146 | 62.0k | let span = match item { |
147 | 0 | ast::AstItem::Package(pkg) => pkg.package_id.as_ref().unwrap().span, |
148 | 62.0k | _ => continue, |
149 | | }; |
150 | 0 | return Err(ParseError::new_syntax( |
151 | 0 | span, |
152 | 0 | "nested packages must be placed at the top-level".to_owned(), |
153 | 0 | )); |
154 | | } |
155 | | |
156 | 20.9k | self.decl_lists.push(file.decl_list); |
157 | 20.9k | Ok(()) |
158 | 20.9k | } |
159 | | |
160 | 11.8k | pub(crate) fn resolve(&mut self) -> ParseResult<UnresolvedPackage> { |
161 | | // At least one of the WIT files must have a `package` annotation. |
162 | 11.8k | let (name, package_name_span) = match &self.package_name { |
163 | 11.8k | Some(name) => name.clone(), |
164 | | None => { |
165 | 0 | return Err(ParseError::new_syntax( |
166 | 0 | Span::default(), |
167 | 0 | "no `package` header was found in any WIT file for this package".to_owned(), |
168 | 0 | )); |
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 | 11.8k | let decl_lists = mem::take(&mut self.decl_lists); |
177 | 11.8k | self.populate_foreign_deps(&decl_lists); |
178 | 11.8k | let (iface_order, world_order) = self.populate_ast_items(&decl_lists)?; |
179 | 11.8k | 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 | 11.8k | let mut iface_id_to_ast = IndexMap::default(); |
185 | 11.8k | let mut world_id_to_ast = IndexMap::default(); |
186 | 20.9k | for (i, decl_list) in decl_lists.iter().enumerate() { |
187 | 62.0k | for item in decl_list.items.iter() { |
188 | 62.0k | match item { |
189 | 42.3k | ast::AstItem::Interface(iface) => { |
190 | 42.3k | let id = match self.ast_items[i][iface.name.name] { |
191 | 42.3k | AstItem::Interface(id) => id, |
192 | 0 | AstItem::World(_) => unreachable!(), |
193 | | }; |
194 | 42.3k | iface_id_to_ast.insert(id, (iface, i)); |
195 | | } |
196 | 16.3k | ast::AstItem::World(world) => { |
197 | 16.3k | let id = match self.ast_items[i][world.name.name] { |
198 | 16.3k | AstItem::World(id) => id, |
199 | 0 | AstItem::Interface(_) => unreachable!(), |
200 | | }; |
201 | 16.3k | world_id_to_ast.insert(id, (world, i)); |
202 | | } |
203 | 3.38k | ast::AstItem::Use(_) => {} |
204 | 0 | ast::AstItem::Package(_) => unreachable!(), |
205 | | } |
206 | | } |
207 | | } |
208 | | |
209 | 42.3k | for id in iface_order { |
210 | 42.3k | let (interface, i) = &iface_id_to_ast[&id]; |
211 | 42.3k | self.cur_ast_index = *i; |
212 | 42.3k | self.resolve_interface(id, &interface.items, &interface.docs, &interface.attributes)?; |
213 | | } |
214 | | |
215 | 16.3k | for id in world_order { |
216 | 16.3k | let (world, i) = &world_id_to_ast[&id]; |
217 | 16.3k | self.cur_ast_index = *i; |
218 | 16.3k | self.resolve_world(id, world)?; |
219 | | } |
220 | | |
221 | 11.8k | self.decl_lists = decl_lists; |
222 | | Ok(UnresolvedPackage { |
223 | 11.8k | package_name_span, |
224 | 11.8k | name, |
225 | 11.8k | docs: mem::take(&mut self.package_docs), |
226 | 11.8k | worlds: mem::take(&mut self.worlds), |
227 | 11.8k | types: mem::take(&mut self.types), |
228 | 11.8k | interfaces: mem::take(&mut self.interfaces), |
229 | 11.8k | foreign_deps: self |
230 | 11.8k | .foreign_deps |
231 | 11.8k | .iter() |
232 | 11.8k | .map(|(name, deps)| { |
233 | | ( |
234 | 3.05k | name.clone(), |
235 | 3.05k | deps.iter() |
236 | 3.53k | .map(|(name, (id, stabilities))| { |
237 | 3.53k | (name.to_string(), (*id, stabilities.clone())) |
238 | 3.53k | }) |
239 | 3.05k | .collect(), |
240 | | ) |
241 | 3.05k | }) |
242 | 11.8k | .collect(), |
243 | 11.8k | unknown_type_spans: mem::take(&mut self.unknown_type_spans), |
244 | 11.8k | foreign_dep_spans: mem::take(&mut self.foreign_dep_spans), |
245 | 11.8k | required_resource_types: mem::take(&mut self.required_resource_types), |
246 | | }) |
247 | 11.8k | } |
248 | | |
249 | | /// Registers all foreign dependencies made within the ASTs provided. |
250 | | /// |
251 | | /// This will populate the `self.foreign_{deps,interfaces,worlds}` maps with all |
252 | | /// `UsePath::Package` entries. |
253 | 11.8k | fn populate_foreign_deps(&mut self, decl_lists: &[ast::DeclList<'a>]) { |
254 | 11.8k | let mut foreign_deps = mem::take(&mut self.foreign_deps); |
255 | 11.8k | let mut foreign_interfaces = mem::take(&mut self.foreign_interfaces); |
256 | 11.8k | let mut foreign_worlds = mem::take(&mut self.foreign_worlds); |
257 | 20.9k | for decl_list in decl_lists { |
258 | 20.9k | decl_list |
259 | 48.5k | .for_each_path(&mut |_, attrs, path, _names, world_or_iface| { |
260 | 48.5k | let (id, name) = match path { |
261 | 32.7k | ast::UsePath::Package { id, name } => (id, name), |
262 | 15.7k | _ => return Ok(()), |
263 | | }; |
264 | | |
265 | 32.7k | let stability = self.stability(attrs)?; |
266 | | |
267 | 32.7k | let deps = foreign_deps.entry(id.package_name()).or_insert_with(|| { |
268 | 3.05k | self.foreign_dep_spans.push(id.span); |
269 | 3.05k | IndexMap::default() |
270 | 3.05k | }); |
271 | 32.7k | let (id, stabilities) = deps.entry(name.name).or_insert_with(|| { |
272 | 3.53k | let id = match world_or_iface { |
273 | | WorldOrInterface::World => { |
274 | 0 | log::trace!( |
275 | | "creating a world for foreign dep: {}/{}", |
276 | 0 | id.package_name(), |
277 | | name.name |
278 | | ); |
279 | 0 | AstItem::World(self.alloc_world(name.span)) |
280 | | } |
281 | | WorldOrInterface::Interface | WorldOrInterface::Unknown => { |
282 | | // Currently top-level `use` always assumes an interface, so the |
283 | | // `Unknown` case is the same as `Interface`. |
284 | 3.53k | log::trace!( |
285 | | "creating an interface for foreign dep: {}/{}", |
286 | 0 | id.package_name(), |
287 | | name.name |
288 | | ); |
289 | 3.53k | AstItem::Interface(self.alloc_interface(name.span)) |
290 | | } |
291 | | }; |
292 | 3.53k | (id, Vec::new()) |
293 | 3.53k | }); |
294 | | |
295 | 32.7k | stabilities.push(stability); |
296 | | |
297 | 32.7k | let _ = match *id { |
298 | 32.7k | AstItem::Interface(id) => foreign_interfaces.insert(id), |
299 | 0 | AstItem::World(id) => foreign_worlds.insert(id), |
300 | | }; |
301 | | |
302 | 32.7k | Ok(()) |
303 | 48.5k | }) |
304 | 20.9k | .unwrap(); |
305 | | } |
306 | 11.8k | self.foreign_deps = foreign_deps; |
307 | 11.8k | self.foreign_interfaces = foreign_interfaces; |
308 | 11.8k | self.foreign_worlds = foreign_worlds; |
309 | 11.8k | } |
310 | | |
311 | 47.6k | fn alloc_interface(&mut self, span: Span) -> InterfaceId { |
312 | 47.6k | self.interface_types.push(IndexMap::default()); |
313 | 47.6k | self.interfaces.alloc(Interface { |
314 | 47.6k | name: None, |
315 | 47.6k | types: IndexMap::default(), |
316 | 47.6k | docs: Docs::default(), |
317 | 47.6k | stability: Default::default(), |
318 | 47.6k | functions: IndexMap::default(), |
319 | 47.6k | package: None, |
320 | 47.6k | span, |
321 | 47.6k | clone_of: None, |
322 | 47.6k | }) |
323 | 47.6k | } |
324 | | |
325 | 16.3k | fn alloc_world(&mut self, span: Span) -> WorldId { |
326 | 16.3k | self.worlds.alloc(World { |
327 | 16.3k | name: String::new(), |
328 | 16.3k | docs: Docs::default(), |
329 | 16.3k | exports: IndexMap::default(), |
330 | 16.3k | imports: IndexMap::default(), |
331 | 16.3k | package: None, |
332 | 16.3k | includes: Default::default(), |
333 | 16.3k | stability: Default::default(), |
334 | 16.3k | span, |
335 | 16.3k | }) |
336 | 16.3k | } |
337 | | |
338 | | /// This method will create a `World` and an `Interface` for all items |
339 | | /// present in the specified set of ASTs. Additionally maps for each AST are |
340 | | /// generated for resolving use-paths later on. |
341 | 11.8k | fn populate_ast_items( |
342 | 11.8k | &mut self, |
343 | 11.8k | decl_lists: &[ast::DeclList<'a>], |
344 | 11.8k | ) -> ParseResult<(Vec<InterfaceId>, Vec<WorldId>)> { |
345 | 11.8k | let mut package_items = IndexMap::default(); |
346 | | |
347 | | // Validate that all worlds and interfaces have unique names within this |
348 | | // package across all ASTs which make up the package. |
349 | 11.8k | let mut names = HashMap::new(); |
350 | 11.8k | let mut decl_list_namespaces = Vec::new(); |
351 | 11.8k | let mut order = IndexMap::default(); |
352 | 20.9k | for decl_list in decl_lists { |
353 | 20.9k | let mut decl_list_ns = IndexMap::default(); |
354 | 62.0k | for item in decl_list.items.iter() { |
355 | 62.0k | match item { |
356 | 42.3k | ast::AstItem::Interface(i) => { |
357 | 42.3k | if package_items.insert(i.name.name, i.name.span).is_some() { |
358 | 0 | return Err(ParseError::new_syntax( |
359 | 0 | i.name.span, |
360 | 0 | format!("duplicate item named `{}`", i.name.name), |
361 | 0 | )); |
362 | 42.3k | } |
363 | 42.3k | let prev = decl_list_ns.insert(i.name.name, ()); |
364 | 42.3k | assert!(prev.is_none()); |
365 | 42.3k | let prev = order.insert(i.name.name, Vec::new()); |
366 | 42.3k | assert!(prev.is_none()); |
367 | 42.3k | let prev = names.insert(i.name.name, item); |
368 | 42.3k | assert!(prev.is_none()); |
369 | | } |
370 | 16.3k | ast::AstItem::World(w) => { |
371 | 16.3k | if package_items.insert(w.name.name, w.name.span).is_some() { |
372 | 0 | return Err(ParseError::new_syntax( |
373 | 0 | w.name.span, |
374 | 0 | format!("duplicate item named `{}`", w.name.name), |
375 | 0 | )); |
376 | 16.3k | } |
377 | 16.3k | let prev = decl_list_ns.insert(w.name.name, ()); |
378 | 16.3k | assert!(prev.is_none()); |
379 | 16.3k | let prev = order.insert(w.name.name, Vec::new()); |
380 | 16.3k | assert!(prev.is_none()); |
381 | 16.3k | let prev = names.insert(w.name.name, item); |
382 | 16.3k | assert!(prev.is_none()); |
383 | | } |
384 | | // These are processed down below. |
385 | 3.38k | ast::AstItem::Use(_) => {} |
386 | | |
387 | 0 | ast::AstItem::Package(_) => unreachable!(), |
388 | | } |
389 | | } |
390 | 20.9k | decl_list_namespaces.push(decl_list_ns); |
391 | | } |
392 | | |
393 | | // Next record dependencies between interfaces as induced via `use` |
394 | | // paths. This step is used to perform a topological sort of all |
395 | | // interfaces to ensure there are no cycles and to generate an ordering |
396 | | // which we can resolve in. |
397 | | enum ItemSource<'a> { |
398 | | Foreign, |
399 | | Local(ast::Id<'a>), |
400 | | } |
401 | | |
402 | 20.9k | for decl_list in decl_lists { |
403 | | // Record, in the context of this file, what all names are defined |
404 | | // at the top level and whether they point to other items in this |
405 | | // package or foreign items. Foreign deps are ignored for |
406 | | // topological ordering. |
407 | 20.9k | let mut decl_list_ns = IndexMap::default(); |
408 | 62.0k | for item in decl_list.items.iter() { |
409 | 62.0k | let (name, src) = match item { |
410 | 3.38k | ast::AstItem::Use(u) => { |
411 | 3.38k | let name = u.as_.as_ref().unwrap_or(u.item.name()); |
412 | 3.38k | let src = match &u.item { |
413 | 1.36k | ast::UsePath::Id(id) => ItemSource::Local(id.clone()), |
414 | 2.01k | ast::UsePath::Package { .. } => ItemSource::Foreign, |
415 | | }; |
416 | 3.38k | (name, src) |
417 | | } |
418 | 42.3k | ast::AstItem::Interface(i) => (&i.name, ItemSource::Local(i.name.clone())), |
419 | 16.3k | ast::AstItem::World(w) => (&w.name, ItemSource::Local(w.name.clone())), |
420 | 0 | ast::AstItem::Package(_) => unreachable!(), |
421 | | }; |
422 | 62.0k | if decl_list_ns.insert(name.name, (name.span, src)).is_some() { |
423 | 0 | return Err(ParseError::new_syntax( |
424 | 0 | name.span, |
425 | 0 | format!("duplicate name `{}` in this file", name.name), |
426 | 0 | )); |
427 | 62.0k | } |
428 | | } |
429 | | |
430 | | // With this file's namespace information look at all `use` paths |
431 | | // and record dependencies between interfaces. |
432 | 48.5k | decl_list.for_each_path(&mut |iface, _attrs, path, _names, _| { |
433 | | // If this import isn't contained within an interface then it's |
434 | | // in a world and it doesn't need to participate in our |
435 | | // topo-sort. |
436 | 48.5k | let iface = match iface { |
437 | 13.3k | Some(name) => name, |
438 | 35.2k | None => return Ok(()), |
439 | | }; |
440 | 13.3k | let used_name = match path { |
441 | 3.27k | ast::UsePath::Id(id) => id, |
442 | 10.0k | ast::UsePath::Package { .. } => return Ok(()), |
443 | | }; |
444 | 3.27k | match decl_list_ns.get(used_name.name) { |
445 | 39 | Some((_, ItemSource::Foreign)) => return Ok(()), |
446 | 1.57k | Some((_, ItemSource::Local(id))) => { |
447 | 1.57k | order[iface.name].push(id.clone()); |
448 | 1.57k | } |
449 | 1.66k | None => match package_items.get(used_name.name) { |
450 | 1.66k | Some(_) => { |
451 | 1.66k | order[iface.name].push(used_name.clone()); |
452 | 1.66k | } |
453 | | None => { |
454 | 0 | return Err(ParseError::from(ParseErrorKind::ItemNotFound { |
455 | 0 | span: used_name.span, |
456 | 0 | name: used_name.name.to_string(), |
457 | 0 | kind: "interface or world".to_string(), |
458 | 0 | hint: None, |
459 | 0 | })); |
460 | | } |
461 | | }, |
462 | | } |
463 | 3.23k | Ok(()) |
464 | 48.5k | })?; |
465 | | } |
466 | | |
467 | 11.8k | let order = toposort("interface or world", &order)?; |
468 | 11.8k | log::debug!("toposort for interfaces and worlds in order: {order:?}"); |
469 | | |
470 | | // Allocate interfaces in-order now that the ordering is defined. This |
471 | | // is then used to build up internal maps for each AST which are stored |
472 | | // in `self.ast_items`. |
473 | 11.8k | let mut ids = IndexMap::default(); |
474 | 11.8k | let mut iface_id_order = Vec::new(); |
475 | 11.8k | let mut world_id_order = Vec::new(); |
476 | 58.6k | for name in order { |
477 | 58.6k | match names.get(name).unwrap() { |
478 | | ast::AstItem::Interface(_) => { |
479 | 42.3k | let id = self.alloc_interface(package_items[name]); |
480 | 42.3k | self.interfaces[id].name = Some(name.to_string()); |
481 | 42.3k | let prev = ids.insert(name, AstItem::Interface(id)); |
482 | 42.3k | assert!(prev.is_none()); |
483 | 42.3k | iface_id_order.push(id); |
484 | | } |
485 | | ast::AstItem::World(_) => { |
486 | 16.3k | let id = self.alloc_world(package_items[name]); |
487 | 16.3k | self.worlds[id].name = name.to_string(); |
488 | 16.3k | let prev = ids.insert(name, AstItem::World(id)); |
489 | 16.3k | assert!(prev.is_none()); |
490 | 16.3k | world_id_order.push(id); |
491 | | } |
492 | 0 | ast::AstItem::Use(_) | ast::AstItem::Package(_) => unreachable!(), |
493 | | }; |
494 | | } |
495 | 20.9k | for decl_list in decl_lists { |
496 | 20.9k | let mut items = IndexMap::default(); |
497 | 62.0k | for item in decl_list.items.iter() { |
498 | 62.0k | let (name, ast_item) = match item { |
499 | 3.38k | ast::AstItem::Use(u) => { |
500 | 3.38k | if !u.attributes.is_empty() { |
501 | 0 | return Err(ParseError::new_syntax( |
502 | 0 | u.span, |
503 | 0 | format!("attributes not allowed on top-level use"), |
504 | 0 | )); |
505 | 3.38k | } |
506 | 3.38k | let name = u.as_.as_ref().unwrap_or(u.item.name()); |
507 | 3.38k | let item = match &u.item { |
508 | 1.36k | ast::UsePath::Id(name) => *ids.get(name.name).ok_or_else(|| { |
509 | 0 | ParseError::from(ParseErrorKind::ItemNotFound { |
510 | 0 | span: name.span, |
511 | 0 | name: name.name.to_string(), |
512 | 0 | kind: "interface or world".to_owned(), |
513 | 0 | hint: None, |
514 | 0 | }) |
515 | 0 | })?, |
516 | 2.01k | ast::UsePath::Package { id, name } => { |
517 | 2.01k | self.foreign_deps[&id.package_name()][name.name].0 |
518 | | } |
519 | | }; |
520 | 3.38k | (name.name, item) |
521 | | } |
522 | 42.3k | ast::AstItem::Interface(i) => { |
523 | 42.3k | let iface_item = ids[i.name.name]; |
524 | 42.3k | assert!(matches!(iface_item, AstItem::Interface(_))); |
525 | 42.3k | (i.name.name, iface_item) |
526 | | } |
527 | 16.3k | ast::AstItem::World(w) => { |
528 | 16.3k | let world_item = ids[w.name.name]; |
529 | 16.3k | assert!(matches!(world_item, AstItem::World(_))); |
530 | 16.3k | (w.name.name, world_item) |
531 | | } |
532 | 0 | ast::AstItem::Package(_) => unreachable!(), |
533 | | }; |
534 | 62.0k | let prev = items.insert(name, ast_item); |
535 | 62.0k | assert!(prev.is_none()); |
536 | | |
537 | | // Items defined via `use` don't go into the package namespace, |
538 | | // only the file namespace. |
539 | 62.0k | if !matches!(item, ast::AstItem::Use(_)) { |
540 | 58.6k | let prev = self.package_items.insert(name, ast_item); |
541 | 58.6k | assert!(prev.is_none()); |
542 | 3.38k | } |
543 | | } |
544 | 20.9k | self.ast_items.push(items); |
545 | | } |
546 | 11.8k | Ok((iface_id_order, world_id_order)) |
547 | 11.8k | } |
548 | | |
549 | | /// Generate a `Type::Unknown` entry for all types imported from foreign |
550 | | /// packages. |
551 | | /// |
552 | | /// This is done after all interfaces are generated so `self.resolve_path` |
553 | | /// can be used to determine if what's being imported from is a foreign |
554 | | /// interface or not. |
555 | 11.8k | fn populate_foreign_types(&mut self, decl_lists: &[ast::DeclList<'a>]) -> ParseResult<()> { |
556 | 20.9k | for (i, decl_list) in decl_lists.iter().enumerate() { |
557 | 20.9k | self.cur_ast_index = i; |
558 | 48.5k | decl_list.for_each_path(&mut |_, attrs, path, names, _| { |
559 | 48.5k | let names = match names { |
560 | 14.5k | Some(names) => names, |
561 | 34.0k | None => return Ok(()), |
562 | | }; |
563 | 14.5k | let stability = self.stability(attrs)?; |
564 | 14.5k | let external_id = self.external_id(attrs)?; |
565 | 14.5k | let (item, name, span) = self.resolve_ast_item_path(path)?; |
566 | 14.5k | let iface = self.extract_iface_from_item(&item, &name, span)?; |
567 | 14.5k | if !self.foreign_interfaces.contains(&iface) { |
568 | 3.91k | return Ok(()); |
569 | 10.5k | } |
570 | | |
571 | 10.5k | let lookup = &mut self.interface_types[iface.index()]; |
572 | 11.5k | for name in names { |
573 | | // If this name has already been defined then use that prior |
574 | | // definition, otherwise create a new type with an unknown |
575 | | // representation and insert it into the various maps. |
576 | 11.5k | if lookup.contains_key(name.name.name) { |
577 | 9.10k | continue; |
578 | 2.49k | } |
579 | 2.49k | let id = self.types.alloc(TypeDef { |
580 | 2.49k | docs: Docs::default(), |
581 | 2.49k | stability: stability.clone(), |
582 | 2.49k | kind: TypeDefKind::Unknown, |
583 | 2.49k | name: Some(name.name.name.to_string()), |
584 | 2.49k | owner: TypeOwner::Interface(iface), |
585 | 2.49k | span: name.name.span, |
586 | 2.49k | external_id: external_id.clone(), |
587 | 2.49k | }); |
588 | 2.49k | self.unknown_type_spans.push(name.name.span); |
589 | 2.49k | lookup.insert(name.name.name, (TypeOrItem::Type(id), name.name.span)); |
590 | 2.49k | self.interfaces[iface] |
591 | 2.49k | .types |
592 | 2.49k | .insert(name.name.name.to_string(), id); |
593 | | } |
594 | | |
595 | 10.5k | Ok(()) |
596 | 48.5k | })?; |
597 | | } |
598 | 11.8k | Ok(()) |
599 | 11.8k | } |
600 | | |
601 | 16.3k | fn resolve_world(&mut self, world_id: WorldId, world: &ast::World<'a>) -> ParseResult<WorldId> { |
602 | 16.3k | let docs = self.docs(&world.docs); |
603 | 16.3k | self.worlds[world_id].docs = docs; |
604 | 16.3k | let stability = self.stability(&world.attributes)?; |
605 | 16.3k | self.worlds[world_id].stability = stability; |
606 | | |
607 | 16.3k | self.resolve_types( |
608 | 16.3k | TypeOwner::World(world_id), |
609 | 84.5k | world.items.iter().filter_map(|i| match i { |
610 | 1.49k | ast::WorldItem::Use(u) => Some(TypeItem::Use(u)), |
611 | 10.2k | ast::WorldItem::Type(t) => Some(TypeItem::Def(t)), |
612 | 72.8k | ast::WorldItem::Import(_) | ast::WorldItem::Export(_) => None, |
613 | | // should be handled in `wit-parser::resolve` |
614 | 0 | ast::WorldItem::Include(_) => None, |
615 | 84.5k | }), |
616 | 0 | )?; |
617 | | |
618 | | // resolve include items |
619 | 42.2k | let items = world.items.iter().filter_map(|i| match i { |
620 | 0 | ast::WorldItem::Include(i) => Some(i), |
621 | 42.2k | _ => None, |
622 | 42.2k | }); |
623 | 16.3k | for include in items { |
624 | 0 | self.resolve_include(world_id, include)?; |
625 | | } |
626 | | |
627 | | // The imports and exports of a world must each be strongly unique. |
628 | 16.3k | let mut import_names = NameScope::default(); |
629 | 16.3k | let mut export_names = NameScope::default(); |
630 | | |
631 | 16.3k | for (name, (item, span)) in self.type_lookup.iter() { |
632 | 5.97k | match *item { |
633 | 5.97k | TypeOrItem::Type(id) => { |
634 | 5.97k | import_names.define(name, *span)?; |
635 | 5.97k | let prev = self.worlds[world_id].imports.insert( |
636 | 5.97k | WorldKey::Name(name.to_string()), |
637 | 5.97k | WorldItem::Type { id, span: *span }, |
638 | | ); |
639 | 5.97k | if prev.is_some() { |
640 | 0 | return Err(ParseError::new_syntax( |
641 | 0 | *span, |
642 | 0 | format!("import `{name}` conflicts with prior import of same name"), |
643 | 0 | )); |
644 | 5.97k | } |
645 | | } |
646 | 0 | TypeOrItem::Item(_) => unreachable!(), |
647 | | } |
648 | | } |
649 | | |
650 | 16.3k | let mut imported_interfaces = HashSet::new(); |
651 | 16.3k | let mut exported_interfaces = HashSet::new(); |
652 | 42.2k | for item in world.items.iter() { |
653 | 36.4k | let (docs, attrs, kind, desc, interfaces) = match item { |
654 | 6.07k | ast::WorldItem::Import(import) => ( |
655 | 6.07k | &import.docs, |
656 | 6.07k | &import.attributes, |
657 | 6.07k | &import.kind, |
658 | 6.07k | "import", |
659 | 6.07k | &mut imported_interfaces, |
660 | 6.07k | ), |
661 | 30.3k | ast::WorldItem::Export(export) => ( |
662 | 30.3k | &export.docs, |
663 | 30.3k | &export.attributes, |
664 | 30.3k | &export.kind, |
665 | 30.3k | "export", |
666 | 30.3k | &mut exported_interfaces, |
667 | 30.3k | ), |
668 | | |
669 | | ast::WorldItem::Type(ast::TypeDef { |
670 | 407 | name, |
671 | 407 | ty: ast::Type::Resource(r), |
672 | | .. |
673 | | }) => { |
674 | 797 | for func in r.funcs.iter() { |
675 | 797 | let span = func.named_func().name.span; |
676 | 797 | let func = self.resolve_resource_func(func, name)?; |
677 | 797 | import_names.define(&func.name, span)?; |
678 | 797 | let prev = self.worlds[world_id] |
679 | 797 | .imports |
680 | 797 | .insert(WorldKey::Name(func.name.clone()), WorldItem::Function(func)); |
681 | | // Resource names themselves are unique, and methods are |
682 | | // uniquely named, so this should be possible to assert |
683 | | // at this point and never trip. |
684 | 797 | assert!(prev.is_none()); |
685 | | } |
686 | 407 | continue; |
687 | | } |
688 | | |
689 | | // handled in `resolve_types` |
690 | | ast::WorldItem::Use(_) | ast::WorldItem::Type(_) | ast::WorldItem::Include(_) => { |
691 | 5.44k | continue; |
692 | | } |
693 | | }; |
694 | | |
695 | 36.4k | let world_item = self.resolve_world_item(docs, attrs, kind)?; |
696 | 36.4k | let key = match kind { |
697 | | // Interfaces are always named exactly as they are in the WIT. |
698 | 1.79k | ast::ExternKind::Interface(name, _) => WorldKey::Name(name.name.to_string()), |
699 | | |
700 | | // Functions, however, might get mangled (e.g. with async) |
701 | | // meaning that the item's name comes from the function, not |
702 | | // from the in-WIT name. |
703 | | ast::ExternKind::Func(..) => { |
704 | 3.97k | let func = match &world_item { |
705 | 3.97k | WorldItem::Function(f) => f, |
706 | 0 | _ => unreachable!(), |
707 | | }; |
708 | 3.97k | WorldKey::Name(func.name.clone()) |
709 | | } |
710 | | |
711 | 1.23k | ast::ExternKind::Path(path) => { |
712 | 1.23k | let (item, name, span) = self.resolve_ast_item_path(path)?; |
713 | 1.23k | let id = self.extract_iface_from_item(&item, &name, span)?; |
714 | 1.23k | WorldKey::Interface(id) |
715 | | } |
716 | | |
717 | | // Named paths use the label as the key. |
718 | 29.4k | ast::ExternKind::NamedPath(name, _) => WorldKey::Name(name.name.to_string()), |
719 | | }; |
720 | 36.4k | if let WorldKey::Interface(id) = key { |
721 | 1.23k | if !interfaces.insert(id) { |
722 | 0 | return Err(ParseError::new_syntax( |
723 | 0 | kind.span(), |
724 | 0 | format!("interface cannot be {desc}ed more than once"), |
725 | 0 | )); |
726 | 1.23k | } |
727 | 35.1k | } |
728 | 36.4k | let dst = if desc == "import" { |
729 | 6.07k | &mut self.worlds[world_id].imports |
730 | | } else { |
731 | 30.3k | &mut self.worlds[world_id].exports |
732 | | }; |
733 | 36.4k | let prev = dst.insert(key.clone(), world_item); |
734 | 36.4k | if let Some(prev) = prev { |
735 | 0 | let prev = match prev { |
736 | 0 | WorldItem::Interface { .. } => "interface", |
737 | 0 | WorldItem::Function(..) => "func", |
738 | 0 | WorldItem::Type { .. } => "type", |
739 | | }; |
740 | 0 | let name = match key { |
741 | 0 | WorldKey::Name(name) => name, |
742 | 0 | WorldKey::Interface(..) => unreachable!(), |
743 | | }; |
744 | 0 | return Err(ParseError::new_syntax( |
745 | 0 | kind.span(), |
746 | 0 | format!("{desc} `{name}` conflicts with prior {prev} of same name",), |
747 | 0 | )); |
748 | 36.4k | } |
749 | | |
750 | | // Check that names are strongly unique. This is somewhat redundant |
751 | | // with the checks above, which are exact instead of using strong |
752 | | // uniqueness, but it's nice to have WIT-oriented error messages |
753 | | // for the most common kinds of name collisions. |
754 | 36.4k | if let WorldKey::Name(name) = &key { |
755 | 35.1k | let names = if desc == "import" { |
756 | 5.07k | &mut import_names |
757 | | } else { |
758 | 30.0k | &mut export_names |
759 | | }; |
760 | 35.1k | names.define(name, kind.span())?; |
761 | 1.23k | } |
762 | | } |
763 | 16.3k | self.type_lookup.clear(); |
764 | | |
765 | 16.3k | Ok(world_id) |
766 | 16.3k | } |
767 | | |
768 | 36.4k | fn resolve_world_item( |
769 | 36.4k | &mut self, |
770 | 36.4k | docs: &ast::Docs<'a>, |
771 | 36.4k | attrs: &[ast::Attribute<'a>], |
772 | 36.4k | kind: &ast::ExternKind<'a>, |
773 | 36.4k | ) -> ParseResult<WorldItem> { |
774 | 36.4k | match kind { |
775 | 1.79k | ast::ExternKind::Interface(name, items) => { |
776 | 1.79k | let prev = mem::take(&mut self.type_lookup); |
777 | 1.79k | let id = self.alloc_interface(name.span); |
778 | 1.79k | self.resolve_interface(id, items, docs, attrs)?; |
779 | 1.79k | self.type_lookup = prev; |
780 | 1.79k | let stability = self.interfaces[id].stability.clone(); |
781 | 1.79k | let external_id = self.external_id(attrs)?; |
782 | 1.79k | Ok(WorldItem::Interface { |
783 | 1.79k | id, |
784 | 1.79k | stability, |
785 | 1.79k | docs: Default::default(), |
786 | 1.79k | span: name.span, |
787 | 1.79k | external_id, |
788 | 1.79k | }) |
789 | | } |
790 | 1.23k | ast::ExternKind::Path(path) => { |
791 | 1.23k | let stability = self.stability(attrs)?; |
792 | 1.23k | let external_id = self.external_id(attrs)?; |
793 | 1.23k | let docs = self.docs(docs); |
794 | 1.23k | let (item, name, item_span) = self.resolve_ast_item_path(path)?; |
795 | 1.23k | let id = self.extract_iface_from_item(&item, &name, item_span)?; |
796 | 1.23k | Ok(WorldItem::Interface { |
797 | 1.23k | id, |
798 | 1.23k | stability, |
799 | 1.23k | external_id, |
800 | 1.23k | docs, |
801 | 1.23k | span: item_span, |
802 | 1.23k | }) |
803 | | } |
804 | 29.4k | ast::ExternKind::NamedPath(name, path) => { |
805 | 29.4k | let stability = self.stability(attrs)?; |
806 | 29.4k | let external_id = self.external_id(attrs)?; |
807 | 29.4k | let docs = self.docs(docs); |
808 | 29.4k | let (item, iface_name, item_span) = self.resolve_ast_item_path(path)?; |
809 | 29.4k | let id = self.extract_iface_from_item(&item, &iface_name, item_span)?; |
810 | 29.4k | Ok(WorldItem::Interface { |
811 | 29.4k | id, |
812 | 29.4k | stability, |
813 | 29.4k | external_id, |
814 | 29.4k | docs, |
815 | 29.4k | span: name.span, |
816 | 29.4k | }) |
817 | | } |
818 | 3.97k | ast::ExternKind::Func(name, func) => { |
819 | 3.97k | let (mangled_name, kind) = freestanding_func(name.name, func); |
820 | 3.97k | let func = |
821 | 3.97k | self.resolve_function(docs, attrs, &mangled_name, name.span, func, kind)?; |
822 | 3.97k | Ok(WorldItem::Function(func)) |
823 | | } |
824 | | } |
825 | 36.4k | } |
826 | | |
827 | 44.1k | fn resolve_interface( |
828 | 44.1k | &mut self, |
829 | 44.1k | interface_id: InterfaceId, |
830 | 44.1k | fields: &[ast::InterfaceItem<'a>], |
831 | 44.1k | docs: &ast::Docs<'a>, |
832 | 44.1k | attrs: &[ast::Attribute<'a>], |
833 | 44.1k | ) -> ParseResult<()> { |
834 | 44.1k | let docs = self.docs(docs); |
835 | 44.1k | self.interfaces[interface_id].docs = docs; |
836 | 44.1k | let stability = self.stability(attrs)?; |
837 | 44.1k | self.interfaces[interface_id].stability = stability; |
838 | | |
839 | 44.1k | self.resolve_types( |
840 | 44.1k | TypeOwner::Interface(interface_id), |
841 | 98.6k | fields.iter().filter_map(|i| match i { |
842 | 27.5k | ast::InterfaceItem::Use(u) => Some(TypeItem::Use(u)), |
843 | 45.3k | ast::InterfaceItem::TypeDef(t) => Some(TypeItem::Def(t)), |
844 | 25.8k | ast::InterfaceItem::Func(_) => None, |
845 | 98.6k | }), |
846 | 0 | )?; |
847 | | |
848 | | // All names in an interface must be strongly unique. |
849 | 44.1k | let mut names = NameScope::default(); |
850 | | |
851 | 44.1k | for (name, (ty, span)) in self.type_lookup.iter() { |
852 | 37.8k | match *ty { |
853 | 37.8k | TypeOrItem::Type(id) => { |
854 | 37.8k | names.define(name, *span)?; |
855 | 37.8k | self.interfaces[interface_id] |
856 | 37.8k | .types |
857 | 37.8k | .insert(name.to_string(), id); |
858 | | } |
859 | 0 | TypeOrItem::Item(_) => unreachable!(), |
860 | | } |
861 | | } |
862 | | |
863 | | // Finally process all function definitions now that all types are |
864 | | // defined. |
865 | 44.1k | let mut funcs = Vec::new(); |
866 | 49.3k | for field in fields { |
867 | 22.6k | match field { |
868 | 12.9k | ast::InterfaceItem::Func(f) => { |
869 | | // Record that this name is a function so that attempts to |
870 | | // reference it as a type produce a helpful error. |
871 | 12.9k | self.type_lookup |
872 | 12.9k | .entry(f.name.name) |
873 | 12.9k | .or_insert((TypeOrItem::Item("function"), f.name.span)); |
874 | 12.9k | let (name, kind) = freestanding_func(f.name.name, &f.func); |
875 | 12.9k | let func = self.resolve_function( |
876 | 12.9k | &f.docs, |
877 | 12.9k | &f.attributes, |
878 | 12.9k | &name, |
879 | 12.9k | f.name.span, |
880 | 12.9k | &f.func, |
881 | 12.9k | kind, |
882 | 0 | )?; |
883 | 12.9k | names.define(&func.name, f.name.span)?; |
884 | 12.9k | funcs.push(func); |
885 | | } |
886 | 13.7k | ast::InterfaceItem::Use(_) => {} |
887 | | ast::InterfaceItem::TypeDef(ast::TypeDef { |
888 | 1.73k | name, |
889 | 1.73k | ty: ast::Type::Resource(r), |
890 | | .. |
891 | | }) => { |
892 | 2.82k | for func in r.funcs.iter() { |
893 | 2.82k | let span = func.named_func().name.span; |
894 | 2.82k | let func = self.resolve_resource_func(func, name)?; |
895 | 2.82k | names.define(&func.name, span)?; |
896 | 2.82k | funcs.push(func); |
897 | | } |
898 | | } |
899 | 20.9k | ast::InterfaceItem::TypeDef(_) => {} |
900 | | } |
901 | | } |
902 | 44.1k | names.check_setters()?; |
903 | 44.1k | for func in funcs { |
904 | 15.7k | let prev = self.interfaces[interface_id] |
905 | 15.7k | .functions |
906 | 15.7k | .insert(func.name.clone(), func); |
907 | 15.7k | assert!(prev.is_none()); |
908 | | } |
909 | 44.1k | place_setters_after_getters(&mut self.interfaces[interface_id].functions, |f| Some(f)); |
910 | | |
911 | 44.1k | let lookup = mem::take(&mut self.type_lookup); |
912 | 44.1k | self.interface_types[interface_id.index()] = lookup; |
913 | | |
914 | 44.1k | Ok(()) |
915 | 44.1k | } |
916 | | |
917 | 60.4k | fn resolve_types<'b>( |
918 | 60.4k | &mut self, |
919 | 60.4k | owner: TypeOwner, |
920 | 60.4k | fields: impl Iterator<Item = TypeItem<'a, 'b>> + Clone, |
921 | 60.4k | ) -> ParseResult<()> |
922 | 60.4k | where |
923 | 60.4k | 'a: 'b, |
924 | | { |
925 | 60.4k | assert!(self.type_lookup.is_empty()); |
926 | | |
927 | | // First, populate our namespace with `use` statements |
928 | 60.4k | for field in fields.clone() { |
929 | 42.2k | match field { |
930 | 14.5k | TypeItem::Use(u) => { |
931 | 14.5k | self.resolve_use(owner, u)?; |
932 | | } |
933 | 27.7k | TypeItem::Def(_) => {} |
934 | | } |
935 | | } |
936 | | |
937 | | // Next determine dependencies between types, perform a topological |
938 | | // sort, and then define all types. This will define types in a |
939 | | // topological fashion, forbid cycles, and weed out references to |
940 | | // undefined types all in one go. |
941 | 60.4k | let mut type_deps = IndexMap::default(); |
942 | 60.4k | let mut type_defs = IndexMap::default(); |
943 | 60.4k | for field in fields { |
944 | 42.2k | match field { |
945 | 27.7k | TypeItem::Def(t) => { |
946 | 27.7k | let prev = type_defs.insert(t.name.name, Some(t)); |
947 | 27.7k | if prev.is_some() { |
948 | 0 | return Err(ParseError::new_syntax( |
949 | 0 | t.name.span, |
950 | 0 | format!("name `{}` is defined more than once", t.name.name), |
951 | 0 | )); |
952 | 27.7k | } |
953 | 27.7k | let mut deps = Vec::new(); |
954 | 27.7k | collect_deps(&t.ty, &mut deps); |
955 | 27.7k | type_deps.insert(t.name.name, deps); |
956 | | } |
957 | 14.5k | TypeItem::Use(u) => { |
958 | 16.1k | for name in u.names.iter() { |
959 | 16.1k | let name = name.as_.as_ref().unwrap_or(&name.name); |
960 | 16.1k | type_deps.insert(name.name, Vec::new()); |
961 | 16.1k | type_defs.insert(name.name, None); |
962 | 16.1k | } |
963 | | } |
964 | | } |
965 | | } |
966 | 60.4k | let order = toposort("type", &type_deps).map_err(attach_old_float_type_context)?; |
967 | 60.4k | for ty in order { |
968 | 43.8k | let def = match type_defs.swap_remove(&ty).unwrap() { |
969 | 27.7k | Some(def) => def, |
970 | 16.1k | None => continue, |
971 | | }; |
972 | 27.7k | let docs = self.docs(&def.docs); |
973 | 27.7k | let stability = self.stability(&def.attributes)?; |
974 | 27.7k | let external_id = self.external_id(&def.attributes)?; |
975 | 27.7k | let kind = self.resolve_type_def(&def.ty, &stability)?; |
976 | 27.7k | let id = self.types.alloc(TypeDef { |
977 | 27.7k | docs, |
978 | 27.7k | stability, |
979 | 27.7k | kind, |
980 | 27.7k | name: Some(def.name.name.to_string()), |
981 | 27.7k | owner, |
982 | 27.7k | span: def.name.span, |
983 | 27.7k | external_id, |
984 | 27.7k | }); |
985 | 27.7k | self.define_interface_name(&def.name, TypeOrItem::Type(id))?; |
986 | | } |
987 | 60.4k | return Ok(()); |
988 | | |
989 | 0 | fn attach_old_float_type_context(mut err: ParseError) -> ParseError { |
990 | 0 | if let ParseErrorKind::ItemNotFound { name, hint, .. } = err.kind_mut() { |
991 | 0 | let new = match name.as_str() { |
992 | 0 | "float32" => "f32", |
993 | 0 | "float64" => "f64", |
994 | 0 | _ => return err, |
995 | | }; |
996 | 0 | *hint = Some(format!( |
997 | 0 | "the `{name}` type has been renamed to `{new}` and is \ |
998 | 0 | no longer accepted, but the `WIT_REQUIRE_F32_F64=0` \ |
999 | 0 | environment variable can be used to temporarily \ |
1000 | 0 | disable this error" |
1001 | 0 | )); |
1002 | 0 | } |
1003 | 0 | err |
1004 | 0 | } |
1005 | 60.4k | } <wit_parser::ast::resolve::Resolver>::resolve_types::<core::iter::adapters::filter_map::FilterMap<core::slice::iter::Iter<wit_parser::ast::InterfaceItem>, <wit_parser::ast::resolve::Resolver>::resolve_interface::{closure#0}>>Line | Count | Source | 917 | 44.1k | fn resolve_types<'b>( | 918 | 44.1k | &mut self, | 919 | 44.1k | owner: TypeOwner, | 920 | 44.1k | fields: impl Iterator<Item = TypeItem<'a, 'b>> + Clone, | 921 | 44.1k | ) -> ParseResult<()> | 922 | 44.1k | where | 923 | 44.1k | 'a: 'b, | 924 | | { | 925 | 44.1k | assert!(self.type_lookup.is_empty()); | 926 | | | 927 | | // First, populate our namespace with `use` statements | 928 | 44.1k | for field in fields.clone() { | 929 | 36.4k | match field { | 930 | 13.7k | TypeItem::Use(u) => { | 931 | 13.7k | self.resolve_use(owner, u)?; | 932 | | } | 933 | 22.6k | TypeItem::Def(_) => {} | 934 | | } | 935 | | } | 936 | | | 937 | | // Next determine dependencies between types, perform a topological | 938 | | // sort, and then define all types. This will define types in a | 939 | | // topological fashion, forbid cycles, and weed out references to | 940 | | // undefined types all in one go. | 941 | 44.1k | let mut type_deps = IndexMap::default(); | 942 | 44.1k | let mut type_defs = IndexMap::default(); | 943 | 44.1k | for field in fields { | 944 | 36.4k | match field { | 945 | 22.6k | TypeItem::Def(t) => { | 946 | 22.6k | let prev = type_defs.insert(t.name.name, Some(t)); | 947 | 22.6k | if prev.is_some() { | 948 | 0 | return Err(ParseError::new_syntax( | 949 | 0 | t.name.span, | 950 | 0 | format!("name `{}` is defined more than once", t.name.name), | 951 | 0 | )); | 952 | 22.6k | } | 953 | 22.6k | let mut deps = Vec::new(); | 954 | 22.6k | collect_deps(&t.ty, &mut deps); | 955 | 22.6k | type_deps.insert(t.name.name, deps); | 956 | | } | 957 | 13.7k | TypeItem::Use(u) => { | 958 | 15.2k | for name in u.names.iter() { | 959 | 15.2k | let name = name.as_.as_ref().unwrap_or(&name.name); | 960 | 15.2k | type_deps.insert(name.name, Vec::new()); | 961 | 15.2k | type_defs.insert(name.name, None); | 962 | 15.2k | } | 963 | | } | 964 | | } | 965 | | } | 966 | 44.1k | let order = toposort("type", &type_deps).map_err(attach_old_float_type_context)?; | 967 | 44.1k | for ty in order { | 968 | 37.8k | let def = match type_defs.swap_remove(&ty).unwrap() { | 969 | 22.6k | Some(def) => def, | 970 | 15.2k | None => continue, | 971 | | }; | 972 | 22.6k | let docs = self.docs(&def.docs); | 973 | 22.6k | let stability = self.stability(&def.attributes)?; | 974 | 22.6k | let external_id = self.external_id(&def.attributes)?; | 975 | 22.6k | let kind = self.resolve_type_def(&def.ty, &stability)?; | 976 | 22.6k | let id = self.types.alloc(TypeDef { | 977 | 22.6k | docs, | 978 | 22.6k | stability, | 979 | 22.6k | kind, | 980 | 22.6k | name: Some(def.name.name.to_string()), | 981 | 22.6k | owner, | 982 | 22.6k | span: def.name.span, | 983 | 22.6k | external_id, | 984 | 22.6k | }); | 985 | 22.6k | self.define_interface_name(&def.name, TypeOrItem::Type(id))?; | 986 | | } | 987 | 44.1k | return Ok(()); | 988 | | | 989 | | fn attach_old_float_type_context(mut err: ParseError) -> ParseError { | 990 | | if let ParseErrorKind::ItemNotFound { name, hint, .. } = err.kind_mut() { | 991 | | let new = match name.as_str() { | 992 | | "float32" => "f32", | 993 | | "float64" => "f64", | 994 | | _ => return err, | 995 | | }; | 996 | | *hint = Some(format!( | 997 | | "the `{name}` type has been renamed to `{new}` and is \ | 998 | | no longer accepted, but the `WIT_REQUIRE_F32_F64=0` \ | 999 | | environment variable can be used to temporarily \ | 1000 | | disable this error" | 1001 | | )); | 1002 | | } | 1003 | | err | 1004 | | } | 1005 | 44.1k | } |
<wit_parser::ast::resolve::Resolver>::resolve_types::<core::iter::adapters::filter_map::FilterMap<core::slice::iter::Iter<wit_parser::ast::WorldItem>, <wit_parser::ast::resolve::Resolver>::resolve_world::{closure#0}>>Line | Count | Source | 917 | 16.3k | fn resolve_types<'b>( | 918 | 16.3k | &mut self, | 919 | 16.3k | owner: TypeOwner, | 920 | 16.3k | fields: impl Iterator<Item = TypeItem<'a, 'b>> + Clone, | 921 | 16.3k | ) -> ParseResult<()> | 922 | 16.3k | where | 923 | 16.3k | 'a: 'b, | 924 | | { | 925 | 16.3k | assert!(self.type_lookup.is_empty()); | 926 | | | 927 | | // First, populate our namespace with `use` statements | 928 | 16.3k | for field in fields.clone() { | 929 | 5.85k | match field { | 930 | 746 | TypeItem::Use(u) => { | 931 | 746 | self.resolve_use(owner, u)?; | 932 | | } | 933 | 5.10k | TypeItem::Def(_) => {} | 934 | | } | 935 | | } | 936 | | | 937 | | // Next determine dependencies between types, perform a topological | 938 | | // sort, and then define all types. This will define types in a | 939 | | // topological fashion, forbid cycles, and weed out references to | 940 | | // undefined types all in one go. | 941 | 16.3k | let mut type_deps = IndexMap::default(); | 942 | 16.3k | let mut type_defs = IndexMap::default(); | 943 | 16.3k | for field in fields { | 944 | 5.85k | match field { | 945 | 5.10k | TypeItem::Def(t) => { | 946 | 5.10k | let prev = type_defs.insert(t.name.name, Some(t)); | 947 | 5.10k | if prev.is_some() { | 948 | 0 | return Err(ParseError::new_syntax( | 949 | 0 | t.name.span, | 950 | 0 | format!("name `{}` is defined more than once", t.name.name), | 951 | 0 | )); | 952 | 5.10k | } | 953 | 5.10k | let mut deps = Vec::new(); | 954 | 5.10k | collect_deps(&t.ty, &mut deps); | 955 | 5.10k | type_deps.insert(t.name.name, deps); | 956 | | } | 957 | 746 | TypeItem::Use(u) => { | 958 | 872 | for name in u.names.iter() { | 959 | 872 | let name = name.as_.as_ref().unwrap_or(&name.name); | 960 | 872 | type_deps.insert(name.name, Vec::new()); | 961 | 872 | type_defs.insert(name.name, None); | 962 | 872 | } | 963 | | } | 964 | | } | 965 | | } | 966 | 16.3k | let order = toposort("type", &type_deps).map_err(attach_old_float_type_context)?; | 967 | 16.3k | for ty in order { | 968 | 5.97k | let def = match type_defs.swap_remove(&ty).unwrap() { | 969 | 5.10k | Some(def) => def, | 970 | 872 | None => continue, | 971 | | }; | 972 | 5.10k | let docs = self.docs(&def.docs); | 973 | 5.10k | let stability = self.stability(&def.attributes)?; | 974 | 5.10k | let external_id = self.external_id(&def.attributes)?; | 975 | 5.10k | let kind = self.resolve_type_def(&def.ty, &stability)?; | 976 | 5.10k | let id = self.types.alloc(TypeDef { | 977 | 5.10k | docs, | 978 | 5.10k | stability, | 979 | 5.10k | kind, | 980 | 5.10k | name: Some(def.name.name.to_string()), | 981 | 5.10k | owner, | 982 | 5.10k | span: def.name.span, | 983 | 5.10k | external_id, | 984 | 5.10k | }); | 985 | 5.10k | self.define_interface_name(&def.name, TypeOrItem::Type(id))?; | 986 | | } | 987 | 16.3k | return Ok(()); | 988 | | | 989 | | fn attach_old_float_type_context(mut err: ParseError) -> ParseError { | 990 | | if let ParseErrorKind::ItemNotFound { name, hint, .. } = err.kind_mut() { | 991 | | let new = match name.as_str() { | 992 | | "float32" => "f32", | 993 | | "float64" => "f64", | 994 | | _ => return err, | 995 | | }; | 996 | | *hint = Some(format!( | 997 | | "the `{name}` type has been renamed to `{new}` and is \ | 998 | | no longer accepted, but the `WIT_REQUIRE_F32_F64=0` \ | 999 | | environment variable can be used to temporarily \ | 1000 | | disable this error" | 1001 | | )); | 1002 | | } | 1003 | | err | 1004 | | } | 1005 | 16.3k | } |
|
1006 | | |
1007 | 14.5k | fn resolve_use(&mut self, owner: TypeOwner, u: &ast::Use<'a>) -> ParseResult<()> { |
1008 | 14.5k | let (item, name, span) = self.resolve_ast_item_path(&u.from)?; |
1009 | 14.5k | let use_from = self.extract_iface_from_item(&item, &name, span)?; |
1010 | 14.5k | let stability = self.stability(&u.attributes)?; |
1011 | 14.5k | let external_id = self.external_id(&u.attributes)?; |
1012 | | |
1013 | 16.1k | for name in u.names.iter() { |
1014 | 16.1k | let lookup = &self.interface_types[use_from.index()]; |
1015 | 16.1k | let id = match lookup.get(name.name.name) { |
1016 | 16.1k | Some((TypeOrItem::Type(id), _)) => *id, |
1017 | 0 | Some((TypeOrItem::Item(s), _)) => { |
1018 | 0 | return Err(ParseError::new_syntax( |
1019 | 0 | name.name.span, |
1020 | 0 | format!("cannot import {s} `{}`", name.name.name), |
1021 | 0 | )); |
1022 | | } |
1023 | | None => { |
1024 | 0 | return Err(ParseError::from(ParseErrorKind::ItemNotFound { |
1025 | 0 | span: name.name.span, |
1026 | 0 | name: name.name.name.to_string(), |
1027 | 0 | kind: "name".to_string(), |
1028 | 0 | hint: None, |
1029 | 0 | })); |
1030 | | } |
1031 | | }; |
1032 | 16.1k | let span = name.name.span; |
1033 | 16.1k | let name = name.as_.as_ref().unwrap_or(&name.name); |
1034 | 16.1k | let id = self.types.alloc(TypeDef { |
1035 | 16.1k | docs: Docs::default(), |
1036 | 16.1k | stability: stability.clone(), |
1037 | 16.1k | kind: TypeDefKind::Type(Type::Id(id)), |
1038 | 16.1k | name: Some(name.name.to_string()), |
1039 | 16.1k | owner, |
1040 | 16.1k | span, |
1041 | 16.1k | external_id: external_id.clone(), |
1042 | 16.1k | }); |
1043 | 16.1k | self.define_interface_name(name, TypeOrItem::Type(id))?; |
1044 | | } |
1045 | 14.5k | Ok(()) |
1046 | 14.5k | } |
1047 | | |
1048 | | /// For each name in the `include`, resolve the path of the include, add it to the self.includes |
1049 | 0 | fn resolve_include(&mut self, world_id: WorldId, i: &ast::Include<'a>) -> ParseResult<()> { |
1050 | 0 | let stability = self.stability(&i.attributes)?; |
1051 | 0 | let (item, name, span) = self.resolve_ast_item_path(&i.from)?; |
1052 | 0 | let include_from = self.extract_world_from_item(&item, &name, span)?; |
1053 | 0 | self.worlds[world_id].includes.push(WorldInclude { |
1054 | 0 | stability, |
1055 | 0 | id: include_from, |
1056 | 0 | names: i |
1057 | 0 | .names |
1058 | 0 | .iter() |
1059 | 0 | .map(|n| IncludeName { |
1060 | 0 | name: n.name.name.to_string(), |
1061 | 0 | as_: n.as_.name.to_string(), |
1062 | 0 | }) |
1063 | 0 | .collect(), |
1064 | 0 | span, |
1065 | | }); |
1066 | 0 | Ok(()) |
1067 | 0 | } |
1068 | | |
1069 | 3.62k | fn resolve_resource_func( |
1070 | 3.62k | &mut self, |
1071 | 3.62k | func: &ast::ResourceFunc<'_>, |
1072 | 3.62k | resource: &ast::Id<'_>, |
1073 | 3.62k | ) -> ParseResult<Function> { |
1074 | 3.62k | let resource_id = match self.type_lookup.get(resource.name) { |
1075 | 3.62k | Some((TypeOrItem::Type(id), _)) => *id, |
1076 | 0 | _ => panic!("type lookup for resource failed"), |
1077 | | }; |
1078 | | let (name, kind); |
1079 | 3.62k | let named_func = func.named_func(); |
1080 | 3.62k | let async_ = named_func.func.async_; |
1081 | 3.62k | match func { |
1082 | 1.92k | ast::ResourceFunc::Method(f) => match f.func.accessor { |
1083 | | None => { |
1084 | 1.92k | name = format!("[method]{}.{}", resource.name, f.name.name); |
1085 | 1.92k | kind = if async_ { |
1086 | 1.51k | FunctionKind::AsyncMethod(resource_id) |
1087 | | } else { |
1088 | 407 | FunctionKind::Method(resource_id) |
1089 | | }; |
1090 | | } |
1091 | | Some(AccessorKind::Getter) => { |
1092 | 0 | assert!(!async_); |
1093 | 0 | name = format!("[method][get]{}.{}", resource.name, f.name.name); |
1094 | 0 | kind = FunctionKind::MethodGetter(resource_id); |
1095 | | } |
1096 | | Some(AccessorKind::Setter) => { |
1097 | 0 | assert!(!async_); |
1098 | 0 | name = format!("[method][set]{}.{}", resource.name, f.name.name); |
1099 | 0 | kind = FunctionKind::MethodSetter(resource_id); |
1100 | | } |
1101 | | }, |
1102 | 1.22k | ast::ResourceFunc::Static(f) => match f.func.accessor { |
1103 | | None => { |
1104 | 1.22k | name = format!("[static]{}.{}", resource.name, f.name.name); |
1105 | 1.22k | kind = if async_ { |
1106 | 1.04k | FunctionKind::AsyncStatic(resource_id) |
1107 | | } else { |
1108 | 181 | FunctionKind::Static(resource_id) |
1109 | | }; |
1110 | | } |
1111 | | Some(AccessorKind::Getter) => { |
1112 | 0 | assert!(!async_); |
1113 | 0 | name = format!("[static][get]{}.{}", resource.name, f.name.name); |
1114 | 0 | kind = FunctionKind::StaticGetter(resource_id); |
1115 | | } |
1116 | | Some(AccessorKind::Setter) => { |
1117 | 0 | assert!(!async_); |
1118 | 0 | name = format!("[static][set]{}.{}", resource.name, f.name.name); |
1119 | 0 | kind = FunctionKind::StaticSetter(resource_id); |
1120 | | } |
1121 | | }, |
1122 | | ast::ResourceFunc::Constructor(_) => { |
1123 | 478 | assert!(!async_); // should not be possible to parse |
1124 | 478 | name = format!("[constructor]{}", resource.name); |
1125 | 478 | kind = FunctionKind::Constructor(resource_id); |
1126 | | } |
1127 | | } |
1128 | 3.62k | self.resolve_function( |
1129 | 3.62k | &named_func.docs, |
1130 | 3.62k | &named_func.attributes, |
1131 | 3.62k | &name, |
1132 | 3.62k | named_func.name.span, |
1133 | 3.62k | &named_func.func, |
1134 | 3.62k | kind, |
1135 | | ) |
1136 | 3.62k | } |
1137 | | |
1138 | 20.4k | fn resolve_function( |
1139 | 20.4k | &mut self, |
1140 | 20.4k | docs: &ast::Docs<'_>, |
1141 | 20.4k | attrs: &[ast::Attribute<'_>], |
1142 | 20.4k | name: &str, |
1143 | 20.4k | name_span: Span, |
1144 | 20.4k | func: &ast::Func, |
1145 | 20.4k | kind: FunctionKind, |
1146 | 20.4k | ) -> ParseResult<Function> { |
1147 | 20.4k | let docs = self.docs(docs); |
1148 | 20.4k | let stability = self.stability(attrs)?; |
1149 | 20.4k | let external_id = self.external_id(attrs)?; |
1150 | 20.4k | let params = self.resolve_params(&func.params, &kind, func.span)?; |
1151 | 20.4k | let result = self.resolve_result(&func.result, &kind, func.span)?; |
1152 | 20.4k | Ok(Function { |
1153 | 20.4k | docs, |
1154 | 20.4k | stability, |
1155 | 20.4k | name: name.to_string(), |
1156 | 20.4k | kind, |
1157 | 20.4k | params, |
1158 | 20.4k | result, |
1159 | 20.4k | span: name_span, |
1160 | 20.4k | external_id, |
1161 | 20.4k | }) |
1162 | 20.4k | } |
1163 | | |
1164 | 60.9k | fn resolve_ast_item_path( |
1165 | 60.9k | &self, |
1166 | 60.9k | path: &ast::UsePath<'a>, |
1167 | 60.9k | ) -> ParseResult<(AstItem, String, Span)> { |
1168 | 60.9k | match path { |
1169 | 18.9k | ast::UsePath::Id(id) => { |
1170 | 18.9k | let item = self.ast_items[self.cur_ast_index] |
1171 | 18.9k | .get(id.name) |
1172 | 18.9k | .or_else(|| self.package_items.get(id.name)); |
1173 | 18.9k | match item { |
1174 | 18.9k | Some(item) => Ok((*item, id.name.into(), id.span)), |
1175 | | None => { |
1176 | 0 | return Err(ParseError::from(ParseErrorKind::ItemNotFound { |
1177 | 0 | span: id.span, |
1178 | 0 | name: id.name.to_string(), |
1179 | 0 | kind: "interface or world".to_owned(), |
1180 | 0 | hint: None, |
1181 | 0 | })); |
1182 | | } |
1183 | | } |
1184 | | } |
1185 | 41.9k | ast::UsePath::Package { id, name } => Ok(( |
1186 | 41.9k | self.foreign_deps[&id.package_name()][name.name].0, |
1187 | 41.9k | name.name.into(), |
1188 | 41.9k | name.span, |
1189 | 41.9k | )), |
1190 | | } |
1191 | 60.9k | } |
1192 | | |
1193 | 60.9k | fn extract_iface_from_item( |
1194 | 60.9k | &self, |
1195 | 60.9k | item: &AstItem, |
1196 | 60.9k | name: &str, |
1197 | 60.9k | span: Span, |
1198 | 60.9k | ) -> ParseResult<InterfaceId> { |
1199 | 60.9k | match item { |
1200 | 60.9k | AstItem::Interface(id) => Ok(*id), |
1201 | | AstItem::World(_) => { |
1202 | 0 | return Err(ParseError::new_syntax( |
1203 | 0 | span, |
1204 | 0 | format!("name `{name}` is defined as a world, not an interface"), |
1205 | 0 | )); |
1206 | | } |
1207 | | } |
1208 | 60.9k | } |
1209 | | |
1210 | 0 | fn extract_world_from_item( |
1211 | 0 | &self, |
1212 | 0 | item: &AstItem, |
1213 | 0 | name: &str, |
1214 | 0 | span: Span, |
1215 | 0 | ) -> ParseResult<WorldId> { |
1216 | 0 | match item { |
1217 | 0 | AstItem::World(id) => Ok(*id), |
1218 | | AstItem::Interface(_) => { |
1219 | 0 | return Err(ParseError::new_syntax( |
1220 | 0 | span, |
1221 | 0 | format!("name `{name}` is defined as an interface, not a world"), |
1222 | 0 | )); |
1223 | | } |
1224 | | } |
1225 | 0 | } |
1226 | | |
1227 | 43.8k | fn define_interface_name(&mut self, name: &ast::Id<'a>, item: TypeOrItem) -> ParseResult<()> { |
1228 | 43.8k | let prev = self.type_lookup.insert(name.name, (item, name.span)); |
1229 | 43.8k | if prev.is_some() { |
1230 | 0 | return Err(ParseError::new_syntax( |
1231 | 0 | name.span, |
1232 | 0 | format!("name `{}` is defined more than once", name.name), |
1233 | 0 | )); |
1234 | | } else { |
1235 | 43.8k | Ok(()) |
1236 | | } |
1237 | 43.8k | } |
1238 | | |
1239 | 409k | fn resolve_type_def( |
1240 | 409k | &mut self, |
1241 | 409k | ty: &ast::Type<'_>, |
1242 | 409k | stability: &Stability, |
1243 | 409k | ) -> ParseResult<TypeDefKind> { |
1244 | 409k | Ok(match ty { |
1245 | 60.4k | ast::Type::Bool(_) => TypeDefKind::Type(Type::Bool), |
1246 | 9.65k | ast::Type::U8(_) => TypeDefKind::Type(Type::U8), |
1247 | 3.50k | ast::Type::U16(_) => TypeDefKind::Type(Type::U16), |
1248 | 3.47k | ast::Type::U32(_) => TypeDefKind::Type(Type::U32), |
1249 | 3.07k | ast::Type::U64(_) => TypeDefKind::Type(Type::U64), |
1250 | 4.90k | ast::Type::S8(_) => TypeDefKind::Type(Type::S8), |
1251 | 3.49k | ast::Type::S16(_) => TypeDefKind::Type(Type::S16), |
1252 | 6.56k | ast::Type::S32(_) => TypeDefKind::Type(Type::S32), |
1253 | 9.99k | ast::Type::S64(_) => TypeDefKind::Type(Type::S64), |
1254 | 7.39k | ast::Type::F32(_) => TypeDefKind::Type(Type::F32), |
1255 | 5.69k | ast::Type::F64(_) => TypeDefKind::Type(Type::F64), |
1256 | 28.0k | ast::Type::Char(_) => TypeDefKind::Type(Type::Char), |
1257 | 4.31k | ast::Type::String(_) => TypeDefKind::Type(Type::String), |
1258 | 30.1k | ast::Type::ErrorContext(_) => TypeDefKind::Type(Type::ErrorContext), |
1259 | 2.07k | ast::Type::Name(name) => { |
1260 | 2.07k | let id = self.resolve_type_name(name)?; |
1261 | 2.07k | TypeDefKind::Type(Type::Id(id)) |
1262 | | } |
1263 | 10.4k | ast::Type::List(list) => { |
1264 | 10.4k | let ty = self.resolve_type(&list.ty, stability)?; |
1265 | 10.4k | TypeDefKind::List(ty) |
1266 | | } |
1267 | 0 | ast::Type::Map(map) => { |
1268 | 0 | let key_ty = self.resolve_type(&map.key, stability)?; |
1269 | 0 | let value_ty = self.resolve_type(&map.value, stability)?; |
1270 | | |
1271 | 0 | match key_ty { |
1272 | | Type::Bool |
1273 | | | Type::U8 |
1274 | | | Type::U16 |
1275 | | | Type::U32 |
1276 | | | Type::U64 |
1277 | | | Type::S8 |
1278 | | | Type::S16 |
1279 | | | Type::S32 |
1280 | | | Type::S64 |
1281 | | | Type::Char |
1282 | 0 | | Type::String => {} |
1283 | | _ => { |
1284 | 0 | return Err(ParseError::new_syntax(map.span, "invalid map key type: map keys must be bool, u8, u16, u32, u64, s8, s16, s32, s64, char, or string".to_owned())); |
1285 | | } |
1286 | | } |
1287 | | |
1288 | 0 | TypeDefKind::Map(key_ty, value_ty) |
1289 | | } |
1290 | 95.7k | ast::Type::FixedLengthList(list) => { |
1291 | 95.7k | let ty = self.resolve_type(&list.ty, stability)?; |
1292 | 95.7k | TypeDefKind::FixedLengthList(ty, list.size) |
1293 | | } |
1294 | 368 | ast::Type::Handle(handle) => TypeDefKind::Handle(match handle { |
1295 | 368 | ast::Handle::Own { resource } => Handle::Own(self.validate_resource(resource)?), |
1296 | 0 | ast::Handle::Borrow { resource } => { |
1297 | 0 | Handle::Borrow(self.validate_resource(resource)?) |
1298 | | } |
1299 | | }), |
1300 | 2.14k | ast::Type::Resource(_) => TypeDefKind::Resource, |
1301 | 2.91k | ast::Type::Record(record) => { |
1302 | 2.91k | if record.fields.is_empty() { |
1303 | 0 | return Err(ParseError::new_syntax( |
1304 | 0 | record.span, |
1305 | 0 | "empty record".to_owned(), |
1306 | 0 | )); |
1307 | 2.91k | } |
1308 | 2.91k | check_unique_names("field", record.fields.iter().map(|f| &f.name))?; |
1309 | 2.91k | let fields = record |
1310 | 2.91k | .fields |
1311 | 2.91k | .iter() |
1312 | 9.21k | .map(|field| { |
1313 | | Ok(Field { |
1314 | 9.21k | docs: self.docs(&field.docs), |
1315 | 9.21k | name: field.name.name.to_string(), |
1316 | 9.21k | ty: self.resolve_type(&field.ty, stability)?, |
1317 | 9.21k | span: field.name.span, |
1318 | | }) |
1319 | 9.21k | }) |
1320 | 2.91k | .collect::<ParseResult<Vec<_>>>()?; |
1321 | 2.91k | TypeDefKind::Record(Record { fields }) |
1322 | | } |
1323 | 1.31k | ast::Type::Flags(flags) => { |
1324 | 1.31k | if flags.flags.is_empty() { |
1325 | 0 | return Err(ParseError::new_syntax(flags.span, "empty flags".to_owned())); |
1326 | 1.31k | } |
1327 | 1.31k | if let Some(flag) = flags.flags.get(32) { |
1328 | 0 | return Err(ParseError::new_syntax( |
1329 | 0 | flag.name.span, |
1330 | 0 | "cannot have more than 32 flags".to_owned(), |
1331 | 0 | )); |
1332 | 1.31k | } |
1333 | 1.31k | check_unique_names("flag", flags.flags.iter().map(|f| &f.name))?; |
1334 | 1.31k | let flags = flags |
1335 | 1.31k | .flags |
1336 | 1.31k | .iter() |
1337 | 1.31k | .map(|flag| Flag { |
1338 | 5.31k | docs: self.docs(&flag.docs), |
1339 | 5.31k | name: flag.name.name.to_string(), |
1340 | 5.31k | span: flag.name.span, |
1341 | 5.31k | }) |
1342 | 1.31k | .collect::<Vec<_>>(); |
1343 | 1.31k | TypeDefKind::Flags(Flags { flags }) |
1344 | | } |
1345 | 38.4k | ast::Type::Tuple(t) => { |
1346 | 38.4k | if t.types.is_empty() { |
1347 | 0 | return Err(ParseError::new_syntax(t.span, "empty tuple".to_owned())); |
1348 | 38.4k | } |
1349 | 38.4k | let types = t |
1350 | 38.4k | .types |
1351 | 38.4k | .iter() |
1352 | 116k | .map(|ty| self.resolve_type(ty, stability)) |
1353 | 38.4k | .collect::<ParseResult<Vec<_>>>()?; |
1354 | 38.4k | TypeDefKind::Tuple(Tuple { types }) |
1355 | | } |
1356 | 4.62k | ast::Type::Variant(variant) => { |
1357 | 4.62k | if variant.cases.is_empty() { |
1358 | 0 | return Err(ParseError::new_syntax( |
1359 | 0 | variant.span, |
1360 | 0 | "empty variant".to_owned(), |
1361 | 0 | )); |
1362 | 4.62k | } |
1363 | 4.62k | check_unique_names("case", variant.cases.iter().map(|c| &c.name))?; |
1364 | 4.62k | let cases = variant |
1365 | 4.62k | .cases |
1366 | 4.62k | .iter() |
1367 | 15.2k | .map(|case| { |
1368 | | Ok(Case { |
1369 | 15.2k | docs: self.docs(&case.docs), |
1370 | 15.2k | name: case.name.name.to_string(), |
1371 | 15.2k | ty: self.resolve_optional_type(case.ty.as_ref(), stability)?, |
1372 | 15.2k | span: case.name.span, |
1373 | | }) |
1374 | 15.2k | }) |
1375 | 4.62k | .collect::<ParseResult<Vec<_>>>()?; |
1376 | 4.62k | TypeDefKind::Variant(Variant { cases }) |
1377 | | } |
1378 | 14.3k | ast::Type::Enum(e) => { |
1379 | 14.3k | if e.cases.is_empty() { |
1380 | 0 | return Err(ParseError::new_syntax(e.span, "empty enum".to_owned())); |
1381 | 14.3k | } |
1382 | 14.3k | check_unique_names("case", e.cases.iter().map(|c| &c.name))?; |
1383 | 14.3k | let cases = e |
1384 | 14.3k | .cases |
1385 | 14.3k | .iter() |
1386 | 89.7k | .map(|case| { |
1387 | 89.7k | Ok(EnumCase { |
1388 | 89.7k | docs: self.docs(&case.docs), |
1389 | 89.7k | name: case.name.name.to_string(), |
1390 | 89.7k | span: case.name.span, |
1391 | 89.7k | }) |
1392 | 89.7k | }) |
1393 | 14.3k | .collect::<ParseResult<Vec<_>>>()?; |
1394 | 14.3k | TypeDefKind::Enum(Enum { cases }) |
1395 | | } |
1396 | 21.6k | ast::Type::Option(ty) => TypeDefKind::Option(self.resolve_type(&ty.ty, stability)?), |
1397 | 19.3k | ast::Type::Result(r) => TypeDefKind::Result(Result_ { |
1398 | 19.3k | ok: self.resolve_optional_type(r.ok.as_deref(), stability)?, |
1399 | 19.3k | err: self.resolve_optional_type(r.err.as_deref(), stability)?, |
1400 | | }), |
1401 | 8.60k | ast::Type::Future(t) => { |
1402 | 8.60k | TypeDefKind::Future(self.resolve_optional_type(t.ty.as_deref(), stability)?) |
1403 | | } |
1404 | 6.74k | ast::Type::Stream(s) => { |
1405 | 6.74k | TypeDefKind::Stream(self.resolve_optional_type(s.ty.as_deref(), stability)?) |
1406 | | } |
1407 | | }) |
1408 | 409k | } |
1409 | | |
1410 | 2.44k | fn resolve_type_name(&mut self, name: &ast::Id<'_>) -> ParseResult<TypeId> { |
1411 | 2.44k | match self.type_lookup.get(name.name) { |
1412 | 2.44k | Some((TypeOrItem::Type(id), _)) => Ok(*id), |
1413 | 0 | Some((TypeOrItem::Item(s), _)) => { |
1414 | 0 | return Err(ParseError::new_syntax( |
1415 | 0 | name.span, |
1416 | 0 | format!("cannot use {s} `{name}` as a type", name = name.name), |
1417 | 0 | )); |
1418 | | } |
1419 | | None => { |
1420 | 0 | return Err(ParseError::from(ParseErrorKind::ItemNotFound { |
1421 | 0 | span: name.span, |
1422 | 0 | name: name.name.to_string(), |
1423 | 0 | kind: "name".to_owned(), |
1424 | 0 | hint: None, |
1425 | 0 | })); |
1426 | | } |
1427 | | } |
1428 | 2.44k | } |
1429 | | |
1430 | 368 | fn validate_resource(&mut self, name: &ast::Id<'_>) -> ParseResult<TypeId> { |
1431 | 368 | let id = self.resolve_type_name(name)?; |
1432 | 368 | let mut cur = id; |
1433 | | loop { |
1434 | 389 | match self.types[cur].kind { |
1435 | 351 | TypeDefKind::Resource => break Ok(id), |
1436 | 21 | TypeDefKind::Type(Type::Id(ty)) => cur = ty, |
1437 | | TypeDefKind::Unknown => { |
1438 | 17 | self.required_resource_types.push((cur, name.span)); |
1439 | 17 | break Ok(id); |
1440 | | } |
1441 | | _ => { |
1442 | 0 | return Err(ParseError::new_syntax( |
1443 | 0 | name.span, |
1444 | 0 | format!("type `{}` used in a handle must be a resource", name.name), |
1445 | 0 | )); |
1446 | | } |
1447 | | } |
1448 | | } |
1449 | 368 | } |
1450 | | |
1451 | | /// If `stability` is `Stability::Unknown`, recursively inspect the |
1452 | | /// specified `kind` until we either bottom out or find a type which has a |
1453 | | /// stability that's _not_ unknown. If we find such a type, return a clone |
1454 | | /// of its stability; otherwise return `Stability::Unknown`. |
1455 | | /// |
1456 | | /// The idea here is that e.g. `option<T>` should inherit `T`'s stability. |
1457 | | /// This gets a little ambiguous in the case of e.g. `tuple<T, U, V>`; for |
1458 | | /// now, we just pick the first one has a known stability, if any. |
1459 | 383k | fn find_stability(&self, kind: &TypeDefKind, stability: &Stability) -> Stability { |
1460 | 470k | fn find_in_type(types: &Arena<TypeDef>, ty: Type) -> Option<&Stability> { |
1461 | 470k | if let Type::Id(id) = ty { |
1462 | 190k | let ty = &types[id]; |
1463 | 190k | if !matches!(&ty.stability, Stability::Unknown) { |
1464 | 390 | Some(&ty.stability) |
1465 | | } else { |
1466 | | // Note that this type isn't searched recursively since the |
1467 | | // creation of `id` should already have searched its |
1468 | | // recursive edges, so there's no need to search again. |
1469 | 190k | None |
1470 | | } |
1471 | | } else { |
1472 | 280k | None |
1473 | | } |
1474 | 470k | } |
1475 | | |
1476 | 381k | fn find_in_kind<'a>( |
1477 | 381k | types: &'a Arena<TypeDef>, |
1478 | 381k | kind: &TypeDefKind, |
1479 | 381k | ) -> Option<&'a Stability> { |
1480 | 2.28k | match kind { |
1481 | 180k | TypeDefKind::Type(ty) => find_in_type(types, *ty), |
1482 | 1.92k | TypeDefKind::Handle(Handle::Borrow(id) | Handle::Own(id)) => { |
1483 | 2.28k | find_in_type(types, Type::Id(*id)) |
1484 | | } |
1485 | 115k | TypeDefKind::Tuple(t) => t.types.iter().find_map(|ty| find_in_type(types, *ty)), |
1486 | 10.4k | TypeDefKind::List(ty) |
1487 | 95.6k | | TypeDefKind::FixedLengthList(ty, _) |
1488 | 126k | | TypeDefKind::Option(ty) => find_in_type(types, *ty), |
1489 | 0 | TypeDefKind::Map(k, v) => { |
1490 | 0 | find_in_type(types, *k).or_else(|| find_in_type(types, *v)) |
1491 | | } |
1492 | 8.58k | TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => { |
1493 | 15.2k | ty.as_ref().and_then(|ty| find_in_type(types, *ty)) |
1494 | | } |
1495 | 19.1k | TypeDefKind::Result(r) => { |
1496 | 19.1k | r.ok.as_ref() |
1497 | 19.1k | .and_then(|ty| find_in_type(types, *ty)) |
1498 | 19.1k | .or_else(|| r.err.as_ref().and_then(|ty| find_in_type(types, *ty))) |
1499 | | } |
1500 | | // Assume these are named types which will be annotated with an |
1501 | | // explicit stability if applicable: |
1502 | | TypeDefKind::Resource |
1503 | | | TypeDefKind::Variant(_) |
1504 | | | TypeDefKind::Record(_) |
1505 | | | TypeDefKind::Flags(_) |
1506 | | | TypeDefKind::Enum(_) |
1507 | 0 | | TypeDefKind::Unknown => None, |
1508 | | } |
1509 | 381k | } |
1510 | | |
1511 | 383k | if let Stability::Unknown = stability { |
1512 | 381k | find_in_kind(&self.types, kind) |
1513 | 381k | .cloned() |
1514 | 381k | .unwrap_or(Stability::Unknown) |
1515 | | } else { |
1516 | 2.18k | stability.clone() |
1517 | | } |
1518 | 383k | } |
1519 | | |
1520 | 381k | fn resolve_type(&mut self, ty: &super::Type<'_>, stability: &Stability) -> ParseResult<Type> { |
1521 | | // Resources must be declared at the top level to have their methods |
1522 | | // processed appropriately, but resources also shouldn't show up |
1523 | | // recursively so assert that's not happening here. |
1524 | 381k | match ty { |
1525 | 0 | ast::Type::Resource(_) => unreachable!(), |
1526 | 381k | _ => {} |
1527 | | } |
1528 | 381k | let kind = self.resolve_type_def(ty, stability)?; |
1529 | 381k | let stability = self.find_stability(&kind, stability); |
1530 | 381k | Ok(self.anon_type_def(TypeDef { |
1531 | 381k | kind, |
1532 | 381k | name: None, |
1533 | 381k | docs: Docs::default(), |
1534 | 381k | stability, |
1535 | 381k | owner: TypeOwner::None, |
1536 | 381k | span: ty.span(), |
1537 | 381k | external_id: None, |
1538 | 381k | })) |
1539 | 381k | } |
1540 | | |
1541 | 69.3k | fn resolve_optional_type( |
1542 | 69.3k | &mut self, |
1543 | 69.3k | ty: Option<&super::Type<'_>>, |
1544 | 69.3k | stability: &Stability, |
1545 | 69.3k | ) -> ParseResult<Option<Type>> { |
1546 | 69.3k | match ty { |
1547 | 59.6k | Some(ty) => Ok(Some(self.resolve_type(ty, stability)?)), |
1548 | 9.68k | None => Ok(None), |
1549 | | } |
1550 | 69.3k | } |
1551 | | |
1552 | 383k | fn anon_type_def(&mut self, ty: TypeDef) -> Type { |
1553 | 201k | let key = match &ty.kind { |
1554 | 181k | TypeDefKind::Type(t) => return *t, |
1555 | 0 | TypeDefKind::Variant(v) => Key::Variant( |
1556 | 0 | v.cases |
1557 | 0 | .iter() |
1558 | 0 | .map(|case| (case.name.clone(), case.ty)) |
1559 | 0 | .collect::<Vec<_>>(), |
1560 | | ), |
1561 | 1.92k | TypeDefKind::Handle(Handle::Borrow(h)) => Key::BorrowHandle(*h), |
1562 | | // An anonymous `own<T>` type is the same as a reference to the type |
1563 | | // `T`, so avoid creating anonymous type and return that here |
1564 | | // directly. Note that this additionally avoids creating distinct |
1565 | | // anonymous types for `list<T>` and `list<own<T>>` for example. |
1566 | 365 | TypeDefKind::Handle(Handle::Own(id)) => return Type::Id(*id), |
1567 | 0 | TypeDefKind::Resource => unreachable!("anonymous resources aren't supported"), |
1568 | 0 | TypeDefKind::Record(r) => Key::Record( |
1569 | 0 | r.fields |
1570 | 0 | .iter() |
1571 | 0 | .map(|case| (case.name.clone(), case.ty)) |
1572 | 0 | .collect::<Vec<_>>(), |
1573 | | ), |
1574 | 0 | TypeDefKind::Flags(r) => { |
1575 | 0 | Key::Flags(r.flags.iter().map(|f| f.name.clone()).collect::<Vec<_>>()) |
1576 | | } |
1577 | 37.9k | TypeDefKind::Tuple(t) => Key::Tuple(t.types.clone()), |
1578 | 0 | TypeDefKind::Enum(r) => { |
1579 | 0 | Key::Enum(r.cases.iter().map(|f| f.name.clone()).collect::<Vec<_>>()) |
1580 | | } |
1581 | 10.4k | TypeDefKind::List(ty) => Key::List(*ty), |
1582 | 0 | TypeDefKind::Map(k, v) => Key::Map(*k, *v), |
1583 | 95.7k | TypeDefKind::FixedLengthList(ty, size) => Key::FixedLengthList(*ty, *size), |
1584 | 21.3k | TypeDefKind::Option(t) => Key::Option(*t), |
1585 | 19.1k | TypeDefKind::Result(r) => Key::Result(r.ok, r.err), |
1586 | 8.58k | TypeDefKind::Future(ty) => Key::Future(*ty), |
1587 | 6.71k | TypeDefKind::Stream(ty) => Key::Stream(*ty), |
1588 | 0 | TypeDefKind::Unknown => unreachable!(), |
1589 | | }; |
1590 | 201k | let id = self |
1591 | 201k | .anon_types |
1592 | 201k | .entry(key) |
1593 | 201k | .or_insert_with(|| self.types.alloc(ty)); |
1594 | 201k | Type::Id(*id) |
1595 | 383k | } |
1596 | | |
1597 | 274k | fn docs(&mut self, doc: &super::Docs<'_>) -> Docs { |
1598 | 274k | let mut docs = vec![]; |
1599 | | |
1600 | 274k | for doc in doc.docs.iter() { |
1601 | 0 | let contents = match doc.strip_prefix("/**") { |
1602 | 0 | Some(doc) => doc.strip_suffix("*/").unwrap(), |
1603 | 0 | None => doc.trim_start_matches('/'), |
1604 | | }; |
1605 | | |
1606 | 0 | docs.push(contents.trim_end()); |
1607 | | } |
1608 | | |
1609 | | // Scan the (non-empty) doc lines to find the minimum amount of leading whitespace. |
1610 | | // This amount of whitespace will be removed from the start of all doc lines, |
1611 | | // normalizing the output while retaining intentional spacing added by the original authors. |
1612 | 274k | let min_leading_ws = docs |
1613 | 274k | .iter() |
1614 | 274k | .filter(|doc| !doc.is_empty()) |
1615 | 274k | .map(|doc| doc.bytes().take_while(|c| c.is_ascii_whitespace()).count()) |
1616 | 274k | .min() |
1617 | 274k | .unwrap_or(0); |
1618 | | |
1619 | 274k | if min_leading_ws > 0 { |
1620 | 0 | let leading_ws_pattern = " ".repeat(min_leading_ws); |
1621 | 0 | docs = docs |
1622 | 0 | .iter() |
1623 | 0 | .map(|doc| doc.strip_prefix(&leading_ws_pattern).unwrap_or(doc)) |
1624 | 0 | .collect(); |
1625 | 274k | } |
1626 | | |
1627 | 274k | let contents = if docs.is_empty() { |
1628 | 274k | None |
1629 | | } else { |
1630 | | // NB: this notably, through the use of `lines`, normalizes `\r\n` |
1631 | | // to `\n`. |
1632 | 0 | let mut contents = String::new(); |
1633 | 0 | for doc in docs { |
1634 | 0 | if doc.is_empty() { |
1635 | 0 | contents.push_str("\n"); |
1636 | 0 | } else { |
1637 | 0 | for line in doc.lines() { |
1638 | 0 | contents.push_str(line); |
1639 | 0 | contents.push_str("\n"); |
1640 | 0 | } |
1641 | | } |
1642 | | } |
1643 | 0 | while contents.ends_with("\n") { |
1644 | 0 | contents.pop(); |
1645 | 0 | } |
1646 | 0 | Some(contents) |
1647 | | }; |
1648 | 274k | Docs { contents } |
1649 | 274k | } |
1650 | | |
1651 | 201k | fn stability(&mut self, attrs: &[ast::Attribute<'_>]) -> ParseResult<Stability> { |
1652 | 201k | let mut since = None; |
1653 | 201k | let mut since_span = Span::default(); |
1654 | 201k | let mut deprecated = None; |
1655 | 201k | let mut deprecated_span = Span::default(); |
1656 | 201k | let mut unstable = None; |
1657 | 201k | for attr in attrs { |
1658 | 129k | match attr { |
1659 | 3.51k | ast::Attribute::Since { version, span } => { |
1660 | 3.51k | if since.is_some() { |
1661 | 0 | return Err(ParseError::new_syntax( |
1662 | 0 | *span, |
1663 | 0 | "cannot specify @since twice".to_owned(), |
1664 | 0 | )); |
1665 | 3.51k | } |
1666 | 3.51k | since = Some(version.clone()); |
1667 | 3.51k | since_span = *span; |
1668 | | } |
1669 | 1.24k | ast::Attribute::Deprecated { version, span } => { |
1670 | 1.24k | if deprecated.is_some() { |
1671 | 0 | return Err(ParseError::new_syntax( |
1672 | 0 | *span, |
1673 | 0 | "cannot specify @deprecated twice".to_owned(), |
1674 | 0 | )); |
1675 | 1.24k | } |
1676 | 1.24k | deprecated = Some(version.clone()); |
1677 | 1.24k | deprecated_span = *span; |
1678 | | } |
1679 | 1.18k | ast::Attribute::Unstable { feature, span } => { |
1680 | 1.18k | if unstable.is_some() { |
1681 | 0 | return Err(ParseError::new_syntax( |
1682 | 0 | *span, |
1683 | 0 | "cannot specify @unstable twice".to_owned(), |
1684 | 0 | )); |
1685 | 1.18k | } |
1686 | 1.18k | unstable = Some(feature.name.to_string()); |
1687 | | } |
1688 | 123k | _ => {} |
1689 | | } |
1690 | | } |
1691 | 201k | match (since, deprecated, unstable) { |
1692 | 3.51k | (Some(since), deprecated, None) => Ok(Stability::Stable { since, deprecated }), |
1693 | 1.18k | (None, deprecated, Some(feature)) => Ok(Stability::Unstable { |
1694 | 1.18k | feature, |
1695 | 1.18k | deprecated, |
1696 | 1.18k | }), |
1697 | 0 | (Some(_), _deprecated, Some(_)) => { |
1698 | 0 | return Err(ParseError::new_syntax( |
1699 | 0 | since_span, |
1700 | 0 | "cannot specify both @since and @unstable".to_owned(), |
1701 | 0 | )); |
1702 | | } |
1703 | | (None, Some(_), None) => { |
1704 | 0 | return Err(ParseError::new_syntax( |
1705 | 0 | deprecated_span, |
1706 | 0 | "cannot specify both @deprecated without @since or @unstable".to_owned(), |
1707 | 0 | )); |
1708 | | } |
1709 | 196k | (None, None, None) => Ok(Stability::Unknown), |
1710 | | } |
1711 | 201k | } |
1712 | | |
1713 | 109k | fn external_id(&mut self, attrs: &[ast::Attribute<'_>]) -> ParseResult<Option<String>> { |
1714 | 109k | let mut external_id = None; |
1715 | 109k | for attr in attrs { |
1716 | 99.3k | match attr { |
1717 | 94.2k | ast::Attribute::ExternalId { span, id } => { |
1718 | 94.2k | if external_id.is_some() { |
1719 | 0 | return Err(ParseError::new_syntax( |
1720 | 0 | *span, |
1721 | 0 | "cannot specify @external-id twice".to_owned(), |
1722 | 0 | )); |
1723 | 94.2k | } |
1724 | 94.2k | external_id = Some(id.clone()) |
1725 | | } |
1726 | 5.15k | _ => {} |
1727 | | } |
1728 | | } |
1729 | 109k | Ok(external_id) |
1730 | 109k | } |
1731 | | |
1732 | 20.4k | fn resolve_params( |
1733 | 20.4k | &mut self, |
1734 | 20.4k | params: &ParamList<'_>, |
1735 | 20.4k | kind: &FunctionKind, |
1736 | 20.4k | span: Span, |
1737 | 20.4k | ) -> ParseResult<Vec<Param>> { |
1738 | 20.4k | let mut ret = Vec::new(); |
1739 | 20.4k | match *kind { |
1740 | | // These kinds of methods don't have any adjustments to the |
1741 | | // parameters, so do nothing here. |
1742 | | FunctionKind::Freestanding |
1743 | | | FunctionKind::AsyncFreestanding |
1744 | | | FunctionKind::Constructor(_) |
1745 | | | FunctionKind::Static(_) |
1746 | | | FunctionKind::AsyncStatic(_) |
1747 | | | FunctionKind::Getter |
1748 | | | FunctionKind::Setter |
1749 | | | FunctionKind::StaticGetter(_) |
1750 | 18.5k | | FunctionKind::StaticSetter(_) => {} |
1751 | | |
1752 | | // Methods automatically get a `self` initial argument so insert |
1753 | | // that here before processing the normal parameters. |
1754 | 407 | FunctionKind::Method(id) |
1755 | 1.51k | | FunctionKind::AsyncMethod(id) |
1756 | 0 | | FunctionKind::MethodGetter(id) |
1757 | 1.92k | | FunctionKind::MethodSetter(id) => { |
1758 | 1.92k | let kind = TypeDefKind::Handle(Handle::Borrow(id)); |
1759 | 1.92k | let stability = self.find_stability(&kind, &Stability::Unknown); |
1760 | 1.92k | let shared = self.anon_type_def(TypeDef { |
1761 | 1.92k | docs: Docs::default(), |
1762 | 1.92k | stability, |
1763 | 1.92k | kind, |
1764 | 1.92k | name: None, |
1765 | 1.92k | owner: TypeOwner::None, |
1766 | 1.92k | span, |
1767 | 1.92k | external_id: None, |
1768 | 1.92k | }); |
1769 | 1.92k | ret.push(Param { |
1770 | 1.92k | name: "self".to_string(), |
1771 | 1.92k | ty: shared, |
1772 | 1.92k | span, |
1773 | 1.92k | }); |
1774 | 1.92k | } |
1775 | | } |
1776 | | |
1777 | 20.4k | match kind.accessor() { |
1778 | | Some(AccessorKind::Getter) => { |
1779 | 0 | if let Some((name, _)) = params.first() { |
1780 | 0 | return Err(ParseError::new_syntax( |
1781 | 0 | name.span, |
1782 | 0 | "getters cannot have parameters".to_owned(), |
1783 | 0 | )); |
1784 | 0 | } |
1785 | | } |
1786 | | Some(AccessorKind::Setter) => { |
1787 | 0 | if params.len() != 1 { |
1788 | 0 | return Err(ParseError::new_syntax( |
1789 | 0 | params.get(1).map(|(name, _)| name.span).unwrap_or(span), |
1790 | 0 | "setters must have exactly one parameter".to_owned(), |
1791 | | )); |
1792 | 0 | } |
1793 | | } |
1794 | 20.4k | None => {} |
1795 | | } |
1796 | | |
1797 | 53.1k | for (name, ty) in params { |
1798 | 53.1k | if ret |
1799 | 53.1k | .iter() |
1800 | 111k | .any(|p| KebabStr::new(&p.name) == KebabStr::new(name.name)) |
1801 | | { |
1802 | 0 | return Err(ParseError::new_syntax( |
1803 | 0 | name.span, |
1804 | 0 | format!("param `{}` is defined more than once", name.name), |
1805 | 0 | )); |
1806 | 53.1k | } |
1807 | 53.1k | ret.push(Param { |
1808 | 53.1k | name: name.name.to_string(), |
1809 | 53.1k | ty: self.resolve_type(ty, &Stability::Unknown)?, |
1810 | 53.1k | span: name.span, |
1811 | | }); |
1812 | | } |
1813 | 20.4k | Ok(ret) |
1814 | 20.4k | } |
1815 | | |
1816 | 20.4k | fn resolve_result( |
1817 | 20.4k | &mut self, |
1818 | 20.4k | result: &Option<ast::Type<'_>>, |
1819 | 20.4k | kind: &FunctionKind, |
1820 | 20.4k | span: Span, |
1821 | 20.4k | ) -> ParseResult<Option<Type>> { |
1822 | 20.4k | match *kind { |
1823 | | // These kinds of methods don't have any adjustments to the return |
1824 | | // values, so plumb them through as-is. |
1825 | | FunctionKind::Freestanding |
1826 | | | FunctionKind::AsyncFreestanding |
1827 | | | FunctionKind::Method(_) |
1828 | | | FunctionKind::AsyncMethod(_) |
1829 | | | FunctionKind::Static(_) |
1830 | 20.0k | | FunctionKind::AsyncStatic(_) => match result { |
1831 | 14.9k | Some(ty) => Ok(Some(self.resolve_type(ty, &Stability::Unknown)?)), |
1832 | 5.06k | None => Ok(None), |
1833 | | }, |
1834 | | |
1835 | | // Getters must return a value. |
1836 | | FunctionKind::Getter |
1837 | | | FunctionKind::MethodGetter(_) |
1838 | 0 | | FunctionKind::StaticGetter(_) => match result { |
1839 | 0 | Some(ty) => Ok(Some(self.resolve_type(ty, &Stability::Unknown)?)), |
1840 | 0 | None => Err(ParseError::new_syntax( |
1841 | 0 | span, |
1842 | 0 | "getters must return a value".to_owned(), |
1843 | 0 | )), |
1844 | | }, |
1845 | | |
1846 | | // Setters must either return nothing or `result<_, error?>`. |
1847 | | FunctionKind::Setter |
1848 | | | FunctionKind::MethodSetter(_) |
1849 | 0 | | FunctionKind::StaticSetter(_) => match result { |
1850 | 0 | None => Ok(None), |
1851 | 0 | Some(ty) => { |
1852 | 0 | let resolved = self.resolve_type(ty, &Stability::Unknown)?; |
1853 | 0 | if let Type::Id(id) = resolved |
1854 | 0 | && let TypeDefKind::Result(r) = &self.types[id].kind |
1855 | 0 | && r.ok.is_none() |
1856 | | { |
1857 | 0 | Ok(Some(resolved)) |
1858 | | } else { |
1859 | 0 | Err(ParseError::new_syntax( |
1860 | 0 | ty.span(), |
1861 | 0 | "if a setter return type is declared it must be a `result` with no `ok` type".to_owned(), |
1862 | 0 | )) |
1863 | | } |
1864 | | } |
1865 | | }, |
1866 | | |
1867 | 478 | FunctionKind::Constructor(id) => match result { |
1868 | | // When constructors don't define a return type, they're |
1869 | | // implicitly assumed to return an owned handle to the type |
1870 | | // they construct. |
1871 | 478 | None => Ok(Some(Type::Id(id))), |
1872 | | |
1873 | | // If a constructor does define a return type, it must be in the |
1874 | | // form of `-> result<R, E?>` where `R` is the resource being |
1875 | | // constructed and `E` is an optional error type. |
1876 | 0 | Some(ty) => Ok(Some(self.resolve_constructor_result(id, ty)?)), |
1877 | | }, |
1878 | | } |
1879 | 20.4k | } |
1880 | | |
1881 | 0 | fn resolve_constructor_result( |
1882 | 0 | &mut self, |
1883 | 0 | resource_id: TypeId, |
1884 | 0 | result_ast: &ast::Type<'_>, |
1885 | 0 | ) -> ParseResult<Type> { |
1886 | 0 | let result = self.resolve_type(result_ast, &Stability::Unknown)?; |
1887 | 0 | let ok_type = match result { |
1888 | 0 | Type::Id(id) => match &self.types[id].kind { |
1889 | 0 | TypeDefKind::Result(r) => Some(r.ok), |
1890 | 0 | _ => None, |
1891 | | }, |
1892 | 0 | _ => None, |
1893 | | }; |
1894 | 0 | let Some(ok_type) = ok_type else { |
1895 | 0 | return Err(ParseError::new_syntax( |
1896 | 0 | result_ast.span(), |
1897 | 0 | "if a constructor return type is declared it must be a `result`".to_owned(), |
1898 | 0 | )); |
1899 | | }; |
1900 | 0 | match ok_type { |
1901 | 0 | Some(Type::Id(ok_id)) if resource_id == ok_id => Ok(result), |
1902 | | _ => { |
1903 | 0 | let ok_span = |
1904 | 0 | if let ast::Type::Result(ast::Result_ { ok: Some(ok), .. }) = result_ast { |
1905 | 0 | ok.span() |
1906 | | } else { |
1907 | 0 | result_ast.span() |
1908 | | }; |
1909 | 0 | return Err(ParseError::new_syntax( |
1910 | 0 | ok_span, |
1911 | 0 | "the `ok` type must be the resource being constructed".to_owned(), |
1912 | 0 | )); |
1913 | | } |
1914 | | } |
1915 | 0 | } |
1916 | | } |
1917 | | |
1918 | | /// Computes the mangled name and [`FunctionKind`] of a function which is not |
1919 | | /// attached to a resource. |
1920 | 16.8k | fn freestanding_func(name: &str, func: &ast::Func<'_>) -> (String, FunctionKind) { |
1921 | 0 | match func.accessor { |
1922 | | None => ( |
1923 | 16.8k | name.to_string(), |
1924 | 16.8k | if func.async_ { |
1925 | 10.8k | FunctionKind::AsyncFreestanding |
1926 | | } else { |
1927 | 6.03k | FunctionKind::Freestanding |
1928 | | }, |
1929 | | ), |
1930 | | Some(AccessorKind::Getter) => { |
1931 | 0 | assert!(!func.async_); |
1932 | 0 | (format!("[get]{name}"), FunctionKind::Getter) |
1933 | | } |
1934 | | Some(AccessorKind::Setter) => { |
1935 | 0 | assert!(!func.async_); |
1936 | 0 | (format!("[set]{name}"), FunctionKind::Setter) |
1937 | | } |
1938 | | } |
1939 | 16.8k | } |
1940 | | |
1941 | | /// Checks that `names` are strongly unique, which the component model |
1942 | | /// requires of record fields, flags and cases. |
1943 | 23.2k | fn check_unique_names<'b, 'a: 'b>( |
1944 | 23.2k | desc: &str, |
1945 | 23.2k | names: impl Iterator<Item = &'b ast::Id<'a>>, |
1946 | 23.2k | ) -> ParseResult<()> { |
1947 | 23.2k | let mut seen = HashMap::new(); |
1948 | 119k | for name in names { |
1949 | 119k | let Some(kebab) = KebabStr::new(name.name) else { |
1950 | 0 | continue; |
1951 | | }; |
1952 | 119k | if let Some(prev) = seen.insert(kebab, name.name) { |
1953 | 0 | return Err(ParseError::new_syntax( |
1954 | 0 | name.span, |
1955 | 0 | if prev == name.name { |
1956 | 0 | format!("duplicate {desc} `{prev}`") |
1957 | | } else { |
1958 | 0 | format!( |
1959 | | "{desc} `{}` conflicts with previous {desc} `{prev}`", |
1960 | | name.name |
1961 | | ) |
1962 | | }, |
1963 | | )); |
1964 | 119k | } |
1965 | | } |
1966 | 23.2k | Ok(()) |
1967 | 23.2k | } wit_parser::ast::resolve::check_unique_names::<core::iter::adapters::map::Map<core::slice::iter::Iter<wit_parser::ast::Case>, <wit_parser::ast::resolve::Resolver>::resolve_type_def::{closure#5}>>Line | Count | Source | 1943 | 4.62k | fn check_unique_names<'b, 'a: 'b>( | 1944 | 4.62k | desc: &str, | 1945 | 4.62k | names: impl Iterator<Item = &'b ast::Id<'a>>, | 1946 | 4.62k | ) -> ParseResult<()> { | 1947 | 4.62k | let mut seen = HashMap::new(); | 1948 | 15.2k | for name in names { | 1949 | 15.2k | let Some(kebab) = KebabStr::new(name.name) else { | 1950 | 0 | continue; | 1951 | | }; | 1952 | 15.2k | if let Some(prev) = seen.insert(kebab, name.name) { | 1953 | 0 | return Err(ParseError::new_syntax( | 1954 | 0 | name.span, | 1955 | 0 | if prev == name.name { | 1956 | 0 | format!("duplicate {desc} `{prev}`") | 1957 | | } else { | 1958 | 0 | format!( | 1959 | | "{desc} `{}` conflicts with previous {desc} `{prev}`", | 1960 | | name.name | 1961 | | ) | 1962 | | }, | 1963 | | )); | 1964 | 15.2k | } | 1965 | | } | 1966 | 4.62k | Ok(()) | 1967 | 4.62k | } |
wit_parser::ast::resolve::check_unique_names::<core::iter::adapters::map::Map<core::slice::iter::Iter<wit_parser::ast::Flag>, <wit_parser::ast::resolve::Resolver>::resolve_type_def::{closure#2}>>Line | Count | Source | 1943 | 1.31k | fn check_unique_names<'b, 'a: 'b>( | 1944 | 1.31k | desc: &str, | 1945 | 1.31k | names: impl Iterator<Item = &'b ast::Id<'a>>, | 1946 | 1.31k | ) -> ParseResult<()> { | 1947 | 1.31k | let mut seen = HashMap::new(); | 1948 | 5.31k | for name in names { | 1949 | 5.31k | let Some(kebab) = KebabStr::new(name.name) else { | 1950 | 0 | continue; | 1951 | | }; | 1952 | 5.31k | if let Some(prev) = seen.insert(kebab, name.name) { | 1953 | 0 | return Err(ParseError::new_syntax( | 1954 | 0 | name.span, | 1955 | 0 | if prev == name.name { | 1956 | 0 | format!("duplicate {desc} `{prev}`") | 1957 | | } else { | 1958 | 0 | format!( | 1959 | | "{desc} `{}` conflicts with previous {desc} `{prev}`", | 1960 | | name.name | 1961 | | ) | 1962 | | }, | 1963 | | )); | 1964 | 5.31k | } | 1965 | | } | 1966 | 1.31k | Ok(()) | 1967 | 1.31k | } |
wit_parser::ast::resolve::check_unique_names::<core::iter::adapters::map::Map<core::slice::iter::Iter<wit_parser::ast::Field>, <wit_parser::ast::resolve::Resolver>::resolve_type_def::{closure#0}>>Line | Count | Source | 1943 | 2.91k | fn check_unique_names<'b, 'a: 'b>( | 1944 | 2.91k | desc: &str, | 1945 | 2.91k | names: impl Iterator<Item = &'b ast::Id<'a>>, | 1946 | 2.91k | ) -> ParseResult<()> { | 1947 | 2.91k | let mut seen = HashMap::new(); | 1948 | 9.21k | for name in names { | 1949 | 9.21k | let Some(kebab) = KebabStr::new(name.name) else { | 1950 | 0 | continue; | 1951 | | }; | 1952 | 9.21k | if let Some(prev) = seen.insert(kebab, name.name) { | 1953 | 0 | return Err(ParseError::new_syntax( | 1954 | 0 | name.span, | 1955 | 0 | if prev == name.name { | 1956 | 0 | format!("duplicate {desc} `{prev}`") | 1957 | | } else { | 1958 | 0 | format!( | 1959 | | "{desc} `{}` conflicts with previous {desc} `{prev}`", | 1960 | | name.name | 1961 | | ) | 1962 | | }, | 1963 | | )); | 1964 | 9.21k | } | 1965 | | } | 1966 | 2.91k | Ok(()) | 1967 | 2.91k | } |
wit_parser::ast::resolve::check_unique_names::<core::iter::adapters::map::Map<core::slice::iter::Iter<wit_parser::ast::EnumCase>, <wit_parser::ast::resolve::Resolver>::resolve_type_def::{closure#7}>>Line | Count | Source | 1943 | 14.3k | fn check_unique_names<'b, 'a: 'b>( | 1944 | 14.3k | desc: &str, | 1945 | 14.3k | names: impl Iterator<Item = &'b ast::Id<'a>>, | 1946 | 14.3k | ) -> ParseResult<()> { | 1947 | 14.3k | let mut seen = HashMap::new(); | 1948 | 89.7k | for name in names { | 1949 | 89.7k | let Some(kebab) = KebabStr::new(name.name) else { | 1950 | 0 | continue; | 1951 | | }; | 1952 | 89.7k | if let Some(prev) = seen.insert(kebab, name.name) { | 1953 | 0 | return Err(ParseError::new_syntax( | 1954 | 0 | name.span, | 1955 | 0 | if prev == name.name { | 1956 | 0 | format!("duplicate {desc} `{prev}`") | 1957 | | } else { | 1958 | 0 | format!( | 1959 | | "{desc} `{}` conflicts with previous {desc} `{prev}`", | 1960 | | name.name | 1961 | | ) | 1962 | | }, | 1963 | | )); | 1964 | 89.7k | } | 1965 | | } | 1966 | 14.3k | Ok(()) | 1967 | 14.3k | } |
|
1968 | | |
1969 | | /// A container for names in a single scope of a component, used to check |
1970 | | /// strong uniqueness. A scope in WIT is an interface, or a world's imports |
1971 | | /// or exports. |
1972 | | /// |
1973 | | /// Also used to check other naming-related conditions like a matching getter |
1974 | | /// for every setter. |
1975 | | #[derive(Default)] |
1976 | | struct NameScope { |
1977 | | /// All names in this scope, keyed by their canonicalized form. |
1978 | | names: IndexMap<ComponentName, Span>, |
1979 | | /// All names in this scope exactly as written. |
1980 | | raw_names: HashSet<String>, |
1981 | | } |
1982 | | |
1983 | | impl NameScope { |
1984 | | /// Defines an already-mangled component name in this scope. Returns an |
1985 | | /// error if `name` is not strongly unique with all other names already in |
1986 | | /// the scope. |
1987 | 95.5k | fn define(&mut self, name: &str, span: Span) -> ParseResult<()> { |
1988 | 95.5k | let component_name = crate::parse_component_name(name).map_err(|e| { |
1989 | 0 | ParseError::new_syntax( |
1990 | 0 | span, |
1991 | 0 | format!( |
1992 | | "name `{name}` is not a valid component name: {}", |
1993 | 0 | e.message() |
1994 | | ), |
1995 | | ) |
1996 | 0 | })?; |
1997 | 95.5k | if let Some((prev, _)) = self.names.get_key_value(&component_name) { |
1998 | 0 | return Err(ParseError::new_syntax( |
1999 | 0 | span, |
2000 | 0 | if prev.as_str() == name { |
2001 | 0 | format!("duplicate name `{name}`") |
2002 | | } else { |
2003 | 0 | format!("name `{name}` conflicts with previous name `{prev}`") |
2004 | | }, |
2005 | | )); |
2006 | 95.5k | } |
2007 | 95.5k | self.names.insert(component_name, span); |
2008 | 95.5k | self.raw_names.insert(name.to_string()); |
2009 | 95.5k | Ok(()) |
2010 | 95.5k | } |
2011 | | |
2012 | | /// Validate that every setter in this scope has a corresponding getter. |
2013 | 44.1k | fn check_setters(&self) -> ParseResult<()> { |
2014 | | use wasmparser::names::AccessorKind as AK; |
2015 | | |
2016 | 53.6k | for (name, span) in self.names.iter() { |
2017 | 53.6k | let ComponentNameKind::Plain(plain) = name.kind() else { |
2018 | 0 | continue; |
2019 | | }; |
2020 | 53.6k | if plain.accessor == Some(AK::Set) { |
2021 | 0 | let getter = plain.getter_for_setter(); |
2022 | 0 | if !self.raw_names.contains(&getter) { |
2023 | 0 | return Err(ParseError::new_syntax( |
2024 | 0 | *span, |
2025 | 0 | format!("setter `{name}` has no corresponding getter `{getter}`"), |
2026 | 0 | )); |
2027 | 0 | } |
2028 | 53.6k | } |
2029 | | } |
2030 | 44.1k | Ok(()) |
2031 | 44.1k | } |
2032 | | } |
2033 | | |
2034 | 96.0k | fn collect_deps<'a>(ty: &ast::Type<'a>, deps: &mut Vec<ast::Id<'a>>) { |
2035 | 96.0k | match ty { |
2036 | | ast::Type::Bool(_) |
2037 | | | ast::Type::U8(_) |
2038 | | | ast::Type::U16(_) |
2039 | | | ast::Type::U32(_) |
2040 | | | ast::Type::U64(_) |
2041 | | | ast::Type::S8(_) |
2042 | | | ast::Type::S16(_) |
2043 | | | ast::Type::S32(_) |
2044 | | | ast::Type::S64(_) |
2045 | | | ast::Type::F32(_) |
2046 | | | ast::Type::F64(_) |
2047 | | | ast::Type::Char(_) |
2048 | | | ast::Type::String(_) |
2049 | | | ast::Type::Flags(_) |
2050 | | | ast::Type::Enum(_) |
2051 | 62.0k | | ast::Type::ErrorContext(_) => {} |
2052 | 606 | ast::Type::Name(name) => deps.push(name.clone()), |
2053 | 14 | ast::Type::Handle(handle) => match handle { |
2054 | 14 | ast::Handle::Own { resource } => deps.push(resource.clone()), |
2055 | 0 | ast::Handle::Borrow { resource } => deps.push(resource.clone()), |
2056 | | }, |
2057 | 2.14k | ast::Type::Resource(_) => {} |
2058 | 2.91k | ast::Type::Record(record) => { |
2059 | 9.21k | for field in record.fields.iter() { |
2060 | 9.21k | collect_deps(&field.ty, deps); |
2061 | 9.21k | } |
2062 | | } |
2063 | 10.2k | ast::Type::Tuple(t) => { |
2064 | 31.6k | for ty in t.types.iter() { |
2065 | 31.6k | collect_deps(ty, deps); |
2066 | 31.6k | } |
2067 | | } |
2068 | 4.62k | ast::Type::Variant(variant) => { |
2069 | 15.2k | for case in variant.cases.iter() { |
2070 | 15.2k | if let Some(ty) = &case.ty { |
2071 | 12.9k | collect_deps(ty, deps); |
2072 | 12.9k | } |
2073 | | } |
2074 | | } |
2075 | 8.45k | ast::Type::Option(ast::Option_ { ty, .. }) |
2076 | 1.11k | | ast::Type::List(ast::List { ty, .. }) |
2077 | 9.87k | | ast::Type::FixedLengthList(ast::FixedLengthList { ty, .. }) => collect_deps(ty, deps), |
2078 | 0 | ast::Type::Map(ast::Map { key, value, .. }) => { |
2079 | 0 | collect_deps(key, deps); |
2080 | 0 | collect_deps(value, deps); |
2081 | 0 | } |
2082 | 2.32k | ast::Type::Result(r) => { |
2083 | 2.32k | if let Some(ty) = &r.ok { |
2084 | 1.70k | collect_deps(ty, deps); |
2085 | 1.70k | } |
2086 | 2.32k | if let Some(ty) = &r.err { |
2087 | 1.77k | collect_deps(ty, deps); |
2088 | 1.77k | } |
2089 | | } |
2090 | 429 | ast::Type::Future(t) => { |
2091 | 429 | if let Some(t) = &t.ty { |
2092 | 373 | collect_deps(t, deps) |
2093 | 56 | } |
2094 | | } |
2095 | 801 | ast::Type::Stream(s) => { |
2096 | 801 | if let Some(t) = &s.ty { |
2097 | 801 | collect_deps(t, deps) |
2098 | 0 | } |
2099 | | } |
2100 | | } |
2101 | 96.0k | } |