1 | use crate::component::*; |
2 | use crate::core::{self, resolve::ResolveCoreType, ValType}; |
3 | use crate::kw; |
4 | use crate::names::Namespace; |
5 | use crate::token::Span; |
6 | use crate::token::{Id, Index}; |
7 | use crate::Error; |
8 | |
9 | /// Resolve the fields of a component and everything nested within it, changing |
10 | /// `Index::Id` to `Index::Num` and expanding alias syntax sugar. |
11 | pub fn resolve(component: &mut Component<'_>) -> Result<(), Error> { |
12 | let fields: &mut Vec> = match &mut component.kind { |
13 | ComponentKind::Text(fields: &mut Vec>) => fields, |
14 | ComponentKind::Binary(_) => return Ok(()), |
15 | }; |
16 | let mut resolver: Resolver<'_> = Resolver::default(); |
17 | resolver.fields(component.id, fields) |
18 | } |
19 | |
20 | impl<'a> From<Alias<'a>> for ComponentField<'a> { |
21 | fn from(a: Alias<'a>) -> Self { |
22 | Self::Alias(a) |
23 | } |
24 | } |
25 | |
26 | impl<'a> From<Alias<'a>> for ModuleTypeDecl<'a> { |
27 | fn from(a: Alias<'a>) -> Self { |
28 | Self::Alias(a) |
29 | } |
30 | } |
31 | |
32 | impl<'a> From<Alias<'a>> for ComponentTypeDecl<'a> { |
33 | fn from(a: Alias<'a>) -> Self { |
34 | Self::Alias(a) |
35 | } |
36 | } |
37 | |
38 | impl<'a> From<Alias<'a>> for InstanceTypeDecl<'a> { |
39 | fn from(a: Alias<'a>) -> Self { |
40 | Self::Alias(a) |
41 | } |
42 | } |
43 | |
44 | #[derive (Default)] |
45 | struct Resolver<'a> { |
46 | stack: Vec<ComponentState<'a>>, |
47 | |
48 | // When a name refers to a definition in an outer scope, we'll need to |
49 | // insert an outer alias before it. This collects the aliases to be |
50 | // inserted during resolution. |
51 | aliases_to_insert: Vec<Alias<'a>>, |
52 | } |
53 | |
54 | /// Context structure used to perform name resolution. |
55 | #[derive (Default)] |
56 | struct ComponentState<'a> { |
57 | id: Option<Id<'a>>, |
58 | |
59 | // Namespaces within each component. Note that each namespace carries |
60 | // with it information about the signature of the item in that namespace. |
61 | // The signature is later used to synthesize the type of a component and |
62 | // inject type annotations if necessary. |
63 | core_funcs: Namespace<'a>, |
64 | core_globals: Namespace<'a>, |
65 | core_tables: Namespace<'a>, |
66 | core_memories: Namespace<'a>, |
67 | core_types: Namespace<'a>, |
68 | core_tags: Namespace<'a>, |
69 | core_instances: Namespace<'a>, |
70 | core_modules: Namespace<'a>, |
71 | |
72 | funcs: Namespace<'a>, |
73 | types: Namespace<'a>, |
74 | instances: Namespace<'a>, |
75 | components: Namespace<'a>, |
76 | values: Namespace<'a>, |
77 | } |
78 | |
79 | impl<'a> ComponentState<'a> { |
80 | fn new(id: Option<Id<'a>>) -> ComponentState<'a> { |
81 | ComponentState { |
82 | id, |
83 | ..ComponentState::default() |
84 | } |
85 | } |
86 | |
87 | fn register_item_sig(&mut self, sig: &ItemSig<'a>) -> Result<u32, Error> { |
88 | match &sig.kind { |
89 | ItemSigKind::CoreModule(_) => self.core_modules.register(name:sig.id, desc:"core module" ), |
90 | ItemSigKind::Func(_) => self.funcs.register(name:sig.id, desc:"func" ), |
91 | ItemSigKind::Component(_) => self.components.register(name:sig.id, desc:"component" ), |
92 | ItemSigKind::Instance(_) => self.instances.register(name:sig.id, desc:"instance" ), |
93 | ItemSigKind::Value(_) => self.values.register(name:sig.id, desc:"value" ), |
94 | ItemSigKind::Type(_) => self.types.register(name:sig.id, desc:"type" ), |
95 | } |
96 | } |
97 | } |
98 | |
99 | impl<'a> Resolver<'a> { |
100 | fn current(&mut self) -> &mut ComponentState<'a> { |
101 | self.stack |
102 | .last_mut() |
103 | .expect("should have at least one component state" ) |
104 | } |
105 | |
106 | fn fields( |
107 | &mut self, |
108 | id: Option<Id<'a>>, |
109 | fields: &mut Vec<ComponentField<'a>>, |
110 | ) -> Result<(), Error> { |
111 | self.stack.push(ComponentState::new(id)); |
112 | self.resolve_prepending_aliases(fields, Resolver::field, ComponentState::register)?; |
113 | self.stack.pop(); |
114 | Ok(()) |
115 | } |
116 | |
117 | fn resolve_prepending_aliases<T>( |
118 | &mut self, |
119 | fields: &mut Vec<T>, |
120 | resolve: fn(&mut Self, &mut T) -> Result<(), Error>, |
121 | register: fn(&mut ComponentState<'a>, &T) -> Result<(), Error>, |
122 | ) -> Result<(), Error> |
123 | where |
124 | T: From<Alias<'a>>, |
125 | { |
126 | assert!(self.aliases_to_insert.is_empty()); |
127 | |
128 | // Iterate through the fields of the component. We use an index |
129 | // instead of an iterator because we'll be inserting aliases |
130 | // as we go. |
131 | let mut i = 0; |
132 | while i < fields.len() { |
133 | // Resolve names within the field. |
134 | resolve(self, &mut fields[i])?; |
135 | |
136 | // Name resolution may have emitted some aliases. Insert them before |
137 | // the current definition. |
138 | let amt = self.aliases_to_insert.len(); |
139 | fields.splice(i..i, self.aliases_to_insert.drain(..).map(T::from)); |
140 | i += amt; |
141 | |
142 | // Definitions can't refer to themselves or to definitions that appear |
143 | // later in the format. Now that we're done resolving this field, |
144 | // assign it an index for later definitions to refer to. |
145 | register(self.current(), &fields[i])?; |
146 | |
147 | i += 1; |
148 | } |
149 | |
150 | Ok(()) |
151 | } |
152 | |
153 | fn field(&mut self, field: &mut ComponentField<'a>) -> Result<(), Error> { |
154 | match field { |
155 | ComponentField::CoreModule(m) => self.core_module(m), |
156 | ComponentField::CoreInstance(i) => self.core_instance(i), |
157 | ComponentField::CoreType(t) => self.core_ty(t), |
158 | ComponentField::CoreRec(t) => self.core_rec(t), |
159 | ComponentField::Component(c) => self.component(c), |
160 | ComponentField::Instance(i) => self.instance(i), |
161 | ComponentField::Alias(a) => self.alias(a), |
162 | ComponentField::Type(t) => self.ty(t), |
163 | ComponentField::CanonicalFunc(f) => self.canonical_func(f), |
164 | ComponentField::CoreFunc(_) => unreachable!("should be expanded already" ), |
165 | ComponentField::Func(_) => unreachable!("should be expanded already" ), |
166 | ComponentField::Start(s) => self.start(s), |
167 | ComponentField::Import(i) => self.item_sig(&mut i.item), |
168 | ComponentField::Export(e) => { |
169 | if let Some(ty) = &mut e.ty { |
170 | self.item_sig(&mut ty.0)?; |
171 | } |
172 | self.export(&mut e.kind) |
173 | } |
174 | ComponentField::Custom(_) | ComponentField::Producers(_) => Ok(()), |
175 | } |
176 | } |
177 | |
178 | fn core_module(&mut self, module: &mut CoreModule) -> Result<(), Error> { |
179 | match &mut module.kind { |
180 | CoreModuleKind::Inline { fields } => { |
181 | crate::core::resolve::resolve(fields)?; |
182 | } |
183 | |
184 | CoreModuleKind::Import { .. } => { |
185 | unreachable!("should be expanded already" ) |
186 | } |
187 | } |
188 | |
189 | Ok(()) |
190 | } |
191 | |
192 | fn component(&mut self, component: &mut NestedComponent<'a>) -> Result<(), Error> { |
193 | match &mut component.kind { |
194 | NestedComponentKind::Import { .. } => unreachable!("should be expanded already" ), |
195 | NestedComponentKind::Inline(fields) => self.fields(component.id, fields), |
196 | } |
197 | } |
198 | |
199 | fn core_instance(&mut self, instance: &mut CoreInstance<'a>) -> Result<(), Error> { |
200 | match &mut instance.kind { |
201 | CoreInstanceKind::Instantiate { module, args } => { |
202 | self.component_item_ref(module)?; |
203 | for arg in args { |
204 | match &mut arg.kind { |
205 | CoreInstantiationArgKind::Instance(i) => { |
206 | self.core_item_ref(i)?; |
207 | } |
208 | CoreInstantiationArgKind::BundleOfExports(..) => { |
209 | unreachable!("should be expanded already" ); |
210 | } |
211 | } |
212 | } |
213 | } |
214 | CoreInstanceKind::BundleOfExports(exports) => { |
215 | for export in exports { |
216 | self.core_item_ref(&mut export.item)?; |
217 | } |
218 | } |
219 | } |
220 | Ok(()) |
221 | } |
222 | |
223 | fn instance(&mut self, instance: &mut Instance<'a>) -> Result<(), Error> { |
224 | match &mut instance.kind { |
225 | InstanceKind::Instantiate { component, args } => { |
226 | self.component_item_ref(component)?; |
227 | for arg in args { |
228 | match &mut arg.kind { |
229 | InstantiationArgKind::Item(e) => { |
230 | self.export(e)?; |
231 | } |
232 | InstantiationArgKind::BundleOfExports(..) => { |
233 | unreachable!("should be expanded already" ) |
234 | } |
235 | } |
236 | } |
237 | } |
238 | InstanceKind::BundleOfExports(exports) => { |
239 | for export in exports { |
240 | self.export(&mut export.kind)?; |
241 | } |
242 | } |
243 | InstanceKind::Import { .. } => { |
244 | unreachable!("should be expanded already" ) |
245 | } |
246 | } |
247 | Ok(()) |
248 | } |
249 | |
250 | fn item_sig(&mut self, item: &mut ItemSig<'a>) -> Result<(), Error> { |
251 | match &mut item.kind { |
252 | // Here we must be explicit otherwise the module type reference will |
253 | // be assumed to be in the component type namespace |
254 | ItemSigKind::CoreModule(t) => self.core_type_use(t), |
255 | ItemSigKind::Func(t) => self.component_type_use(t), |
256 | ItemSigKind::Component(t) => self.component_type_use(t), |
257 | ItemSigKind::Instance(t) => self.component_type_use(t), |
258 | ItemSigKind::Value(t) => self.component_val_type(&mut t.0), |
259 | ItemSigKind::Type(b) => match b { |
260 | TypeBounds::Eq(i) => { |
261 | self.resolve_ns(i, Ns::Type)?; |
262 | Ok(()) |
263 | } |
264 | TypeBounds::SubResource => Ok(()), |
265 | }, |
266 | } |
267 | } |
268 | |
269 | fn export(&mut self, kind: &mut ComponentExportKind<'a>) -> Result<(), Error> { |
270 | match kind { |
271 | // Here we do *not* have to be explicit as the item ref is to a core module |
272 | ComponentExportKind::CoreModule(r) => self.component_item_ref(r), |
273 | ComponentExportKind::Func(r) => self.component_item_ref(r), |
274 | ComponentExportKind::Value(r) => self.component_item_ref(r), |
275 | ComponentExportKind::Type(r) => self.component_item_ref(r), |
276 | ComponentExportKind::Component(r) => self.component_item_ref(r), |
277 | ComponentExportKind::Instance(r) => self.component_item_ref(r), |
278 | } |
279 | } |
280 | |
281 | fn start(&mut self, start: &mut Start<'a>) -> Result<(), Error> { |
282 | self.resolve_ns(&mut start.func, Ns::Func)?; |
283 | for arg in start.args.iter_mut() { |
284 | self.component_item_ref(arg)?; |
285 | } |
286 | Ok(()) |
287 | } |
288 | |
289 | fn outer_alias<T: Into<Ns>>( |
290 | &mut self, |
291 | outer: &mut Index<'a>, |
292 | index: &mut Index<'a>, |
293 | kind: T, |
294 | span: Span, |
295 | ) -> Result<(), Error> { |
296 | // Short-circuit when both indices are already resolved as this |
297 | // helps to write tests for invalid modules where wasmparser should |
298 | // be the one returning the error. |
299 | if let Index::Num(..) = outer { |
300 | if let Index::Num(..) = index { |
301 | return Ok(()); |
302 | } |
303 | } |
304 | |
305 | // Resolve `outer`, and compute the depth at which to look up |
306 | // `index`. |
307 | let depth = match outer { |
308 | Index::Id(id) => { |
309 | let mut depth = 0; |
310 | for resolver in self.stack.iter().rev() { |
311 | if resolver.id == Some(*id) { |
312 | break; |
313 | } |
314 | depth += 1; |
315 | } |
316 | if depth as usize == self.stack.len() { |
317 | return Err(Error::new( |
318 | span, |
319 | format!("outer component ` {}` not found" , id.name()), |
320 | )); |
321 | } |
322 | depth |
323 | } |
324 | Index::Num(n, _span) => *n, |
325 | }; |
326 | |
327 | if depth as usize >= self.stack.len() { |
328 | return Err(Error::new( |
329 | span, |
330 | format!("outer count of ` {}` is too large" , depth), |
331 | )); |
332 | } |
333 | |
334 | *outer = Index::Num(depth, span); |
335 | |
336 | // Resolve `index` within the computed scope depth. |
337 | let computed = self.stack.len() - 1 - depth as usize; |
338 | self.stack[computed].resolve(kind.into(), index)?; |
339 | |
340 | Ok(()) |
341 | } |
342 | |
343 | fn alias(&mut self, alias: &mut Alias<'a>) -> Result<(), Error> { |
344 | match &mut alias.target { |
345 | AliasTarget::Export { |
346 | instance, |
347 | name: _, |
348 | kind: _, |
349 | } => { |
350 | self.resolve_ns(instance, Ns::Instance)?; |
351 | } |
352 | AliasTarget::CoreExport { |
353 | instance, |
354 | name: _, |
355 | kind: _, |
356 | } => { |
357 | self.resolve_ns(instance, Ns::CoreInstance)?; |
358 | } |
359 | AliasTarget::Outer { outer, index, kind } => { |
360 | self.outer_alias(outer, index, *kind, alias.span)?; |
361 | } |
362 | } |
363 | Ok(()) |
364 | } |
365 | |
366 | fn canonical_func(&mut self, func: &mut CanonicalFunc<'a>) -> Result<(), Error> { |
367 | match &mut func.kind { |
368 | CanonicalFuncKind::Lift { ty, info } => { |
369 | self.component_type_use(ty)?; |
370 | self.core_item_ref(&mut info.func)?; |
371 | self.canon_opts(&mut info.opts)?; |
372 | } |
373 | CanonicalFuncKind::Lower(info) => { |
374 | self.component_item_ref(&mut info.func)?; |
375 | self.canon_opts(&mut info.opts)?; |
376 | } |
377 | CanonicalFuncKind::ResourceNew(info) => { |
378 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
379 | } |
380 | CanonicalFuncKind::ResourceRep(info) => { |
381 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
382 | } |
383 | CanonicalFuncKind::ResourceDrop(info) => { |
384 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
385 | } |
386 | CanonicalFuncKind::ThreadSpawn(info) => { |
387 | self.resolve_ns(&mut info.ty, Ns::CoreType)?; |
388 | } |
389 | CanonicalFuncKind::ThreadHwConcurrency(_) |
390 | | CanonicalFuncKind::TaskBackpressure |
391 | | CanonicalFuncKind::TaskYield(_) |
392 | | CanonicalFuncKind::SubtaskDrop |
393 | | CanonicalFuncKind::ErrorContextDrop => {} |
394 | CanonicalFuncKind::TaskReturn(info) => { |
395 | self.resolve_ns(&mut info.ty, Ns::CoreType)?; |
396 | } |
397 | CanonicalFuncKind::TaskWait(info) => { |
398 | self.core_item_ref(&mut info.memory)?; |
399 | } |
400 | CanonicalFuncKind::TaskPoll(info) => { |
401 | self.core_item_ref(&mut info.memory)?; |
402 | } |
403 | CanonicalFuncKind::StreamNew(info) => { |
404 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
405 | } |
406 | CanonicalFuncKind::StreamRead(info) => { |
407 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
408 | self.canon_opts(&mut info.opts)?; |
409 | } |
410 | CanonicalFuncKind::StreamWrite(info) => { |
411 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
412 | self.canon_opts(&mut info.opts)?; |
413 | } |
414 | CanonicalFuncKind::StreamCancelRead(info) => { |
415 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
416 | } |
417 | CanonicalFuncKind::StreamCancelWrite(info) => { |
418 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
419 | } |
420 | CanonicalFuncKind::StreamCloseReadable(info) => { |
421 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
422 | } |
423 | CanonicalFuncKind::StreamCloseWritable(info) => { |
424 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
425 | } |
426 | CanonicalFuncKind::FutureNew(info) => { |
427 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
428 | } |
429 | CanonicalFuncKind::FutureRead(info) => { |
430 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
431 | self.canon_opts(&mut info.opts)?; |
432 | } |
433 | CanonicalFuncKind::FutureWrite(info) => { |
434 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
435 | self.canon_opts(&mut info.opts)?; |
436 | } |
437 | CanonicalFuncKind::FutureCancelRead(info) => { |
438 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
439 | } |
440 | CanonicalFuncKind::FutureCancelWrite(info) => { |
441 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
442 | } |
443 | CanonicalFuncKind::FutureCloseReadable(info) => { |
444 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
445 | } |
446 | CanonicalFuncKind::FutureCloseWritable(info) => { |
447 | self.resolve_ns(&mut info.ty, Ns::Type)?; |
448 | } |
449 | CanonicalFuncKind::ErrorContextNew(info) => { |
450 | self.canon_opts(&mut info.opts)?; |
451 | } |
452 | CanonicalFuncKind::ErrorContextDebugMessage(info) => { |
453 | self.canon_opts(&mut info.opts)?; |
454 | } |
455 | } |
456 | |
457 | Ok(()) |
458 | } |
459 | |
460 | fn canon_opts(&mut self, opts: &mut [CanonOpt<'a>]) -> Result<(), Error> { |
461 | for opt in opts { |
462 | match opt { |
463 | CanonOpt::StringUtf8 |
464 | | CanonOpt::StringUtf16 |
465 | | CanonOpt::StringLatin1Utf16 |
466 | | CanonOpt::Async => {} |
467 | CanonOpt::Memory(r) => self.core_item_ref(r)?, |
468 | CanonOpt::Realloc(r) | CanonOpt::PostReturn(r) | CanonOpt::Callback(r) => { |
469 | self.core_item_ref(r)? |
470 | } |
471 | } |
472 | } |
473 | |
474 | Ok(()) |
475 | } |
476 | |
477 | fn core_type_use<T>(&mut self, ty: &mut CoreTypeUse<'a, T>) -> Result<(), Error> { |
478 | let item = match ty { |
479 | CoreTypeUse::Ref(r) => r, |
480 | CoreTypeUse::Inline(_) => { |
481 | unreachable!("inline type-use should be expanded by now" ) |
482 | } |
483 | }; |
484 | self.core_item_ref(item) |
485 | } |
486 | |
487 | fn component_type_use<T>(&mut self, ty: &mut ComponentTypeUse<'a, T>) -> Result<(), Error> { |
488 | let item = match ty { |
489 | ComponentTypeUse::Ref(r) => r, |
490 | ComponentTypeUse::Inline(_) => { |
491 | unreachable!("inline type-use should be expanded by now" ) |
492 | } |
493 | }; |
494 | self.component_item_ref(item) |
495 | } |
496 | |
497 | fn defined_type(&mut self, ty: &mut ComponentDefinedType<'a>) -> Result<(), Error> { |
498 | match ty { |
499 | ComponentDefinedType::Primitive(_) => {} |
500 | ComponentDefinedType::Flags(_) => {} |
501 | ComponentDefinedType::Enum(_) => {} |
502 | ComponentDefinedType::Record(r) => { |
503 | for field in r.fields.iter_mut() { |
504 | self.component_val_type(&mut field.ty)?; |
505 | } |
506 | } |
507 | ComponentDefinedType::Variant(v) => { |
508 | // Namespace for case identifier resolution |
509 | let mut ns = Namespace::default(); |
510 | for case in v.cases.iter_mut() { |
511 | let index = ns.register(case.id, "variant case" )?; |
512 | |
513 | if let Some(ty) = &mut case.ty { |
514 | self.component_val_type(ty)?; |
515 | } |
516 | |
517 | if let Some(refines) = &mut case.refines { |
518 | if let Refinement::Index(span, idx) = refines { |
519 | let resolved = ns.resolve(idx, "variant case" )?; |
520 | if resolved == index { |
521 | return Err(Error::new( |
522 | *span, |
523 | "variant case cannot refine itself" .to_string(), |
524 | )); |
525 | } |
526 | |
527 | *refines = Refinement::Resolved(resolved); |
528 | } |
529 | } |
530 | } |
531 | } |
532 | ComponentDefinedType::List(l) => { |
533 | self.component_val_type(&mut l.element)?; |
534 | } |
535 | ComponentDefinedType::Tuple(t) => { |
536 | for field in t.fields.iter_mut() { |
537 | self.component_val_type(field)?; |
538 | } |
539 | } |
540 | ComponentDefinedType::Option(o) => { |
541 | self.component_val_type(&mut o.element)?; |
542 | } |
543 | ComponentDefinedType::Result(r) => { |
544 | if let Some(ty) = &mut r.ok { |
545 | self.component_val_type(ty)?; |
546 | } |
547 | |
548 | if let Some(ty) = &mut r.err { |
549 | self.component_val_type(ty)?; |
550 | } |
551 | } |
552 | ComponentDefinedType::Own(t) | ComponentDefinedType::Borrow(t) => { |
553 | self.resolve_ns(t, Ns::Type)?; |
554 | } |
555 | ComponentDefinedType::Stream(s) => { |
556 | self.component_val_type(&mut s.element)?; |
557 | } |
558 | ComponentDefinedType::Future(f) => { |
559 | if let Some(ty) = &mut f.element { |
560 | self.component_val_type(ty)?; |
561 | } |
562 | } |
563 | } |
564 | Ok(()) |
565 | } |
566 | |
567 | fn component_val_type(&mut self, ty: &mut ComponentValType<'a>) -> Result<(), Error> { |
568 | match ty { |
569 | ComponentValType::Ref(idx) => { |
570 | self.resolve_ns(idx, Ns::Type)?; |
571 | Ok(()) |
572 | } |
573 | ComponentValType::Inline(ComponentDefinedType::Primitive(_)) => Ok(()), |
574 | ComponentValType::Inline(_) => unreachable!("should be expanded by now" ), |
575 | } |
576 | } |
577 | |
578 | fn core_ty(&mut self, field: &mut CoreType<'a>) -> Result<(), Error> { |
579 | match &mut field.def { |
580 | CoreTypeDef::Def(ty) => { |
581 | // See comments in `module_type` for why registration of ids happens |
582 | // here for core types early. |
583 | self.current().core_types.register(field.id, "core type" )?; |
584 | self.current().resolve_type_def(ty)?; |
585 | assert!(self.aliases_to_insert.is_empty()); |
586 | } |
587 | CoreTypeDef::Module(t) => { |
588 | self.stack.push(ComponentState::new(field.id)); |
589 | self.module_type(t)?; |
590 | self.stack.pop(); |
591 | } |
592 | } |
593 | Ok(()) |
594 | } |
595 | |
596 | fn core_rec(&mut self, rec: &mut core::Rec<'a>) -> Result<(), Error> { |
597 | // See comments in `module_type` for why registration of ids happens |
598 | // here for core types early. |
599 | for ty in rec.types.iter() { |
600 | self.current().core_types.register(ty.id, "core type" )?; |
601 | } |
602 | for ty in rec.types.iter_mut() { |
603 | self.current().resolve_type(ty)?; |
604 | } |
605 | assert!(self.aliases_to_insert.is_empty()); |
606 | Ok(()) |
607 | } |
608 | |
609 | fn ty(&mut self, field: &mut Type<'a>) -> Result<(), Error> { |
610 | match &mut field.def { |
611 | TypeDef::Defined(t) => { |
612 | self.defined_type(t)?; |
613 | } |
614 | TypeDef::Func(f) => { |
615 | for param in f.params.iter_mut() { |
616 | self.component_val_type(&mut param.ty)?; |
617 | } |
618 | |
619 | for result in f.results.iter_mut() { |
620 | self.component_val_type(&mut result.ty)?; |
621 | } |
622 | } |
623 | TypeDef::Component(c) => { |
624 | self.stack.push(ComponentState::new(field.id)); |
625 | self.component_type(c)?; |
626 | self.stack.pop(); |
627 | } |
628 | TypeDef::Instance(i) => { |
629 | self.stack.push(ComponentState::new(field.id)); |
630 | self.instance_type(i)?; |
631 | self.stack.pop(); |
632 | } |
633 | TypeDef::Resource(r) => { |
634 | match &mut r.rep { |
635 | ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => {} |
636 | ValType::Ref(r) => match &mut r.heap { |
637 | core::HeapType::Abstract { .. } => {} |
638 | core::HeapType::Concrete(id) => { |
639 | self.resolve_ns(id, Ns::Type)?; |
640 | } |
641 | }, |
642 | } |
643 | if let Some(dtor) = &mut r.dtor { |
644 | self.core_item_ref(dtor)?; |
645 | } |
646 | } |
647 | } |
648 | Ok(()) |
649 | } |
650 | |
651 | fn component_type(&mut self, c: &mut ComponentType<'a>) -> Result<(), Error> { |
652 | self.resolve_prepending_aliases( |
653 | &mut c.decls, |
654 | |resolver, decl| match decl { |
655 | ComponentTypeDecl::Alias(alias) => resolver.alias(alias), |
656 | ComponentTypeDecl::CoreType(ty) => resolver.core_ty(ty), |
657 | ComponentTypeDecl::Type(ty) => resolver.ty(ty), |
658 | ComponentTypeDecl::Import(import) => resolver.item_sig(&mut import.item), |
659 | ComponentTypeDecl::Export(export) => resolver.item_sig(&mut export.item), |
660 | }, |
661 | |state, decl| { |
662 | match decl { |
663 | ComponentTypeDecl::Alias(alias) => { |
664 | state.register_alias(alias)?; |
665 | } |
666 | ComponentTypeDecl::CoreType(ty) => { |
667 | state.core_types.register(ty.id, "core type" )?; |
668 | } |
669 | ComponentTypeDecl::Type(ty) => { |
670 | state.types.register(ty.id, "type" )?; |
671 | } |
672 | ComponentTypeDecl::Export(e) => { |
673 | state.register_item_sig(&e.item)?; |
674 | } |
675 | ComponentTypeDecl::Import(i) => { |
676 | state.register_item_sig(&i.item)?; |
677 | } |
678 | } |
679 | Ok(()) |
680 | }, |
681 | ) |
682 | } |
683 | |
684 | fn instance_type(&mut self, c: &mut InstanceType<'a>) -> Result<(), Error> { |
685 | self.resolve_prepending_aliases( |
686 | &mut c.decls, |
687 | |resolver, decl| match decl { |
688 | InstanceTypeDecl::Alias(alias) => resolver.alias(alias), |
689 | InstanceTypeDecl::CoreType(ty) => resolver.core_ty(ty), |
690 | InstanceTypeDecl::Type(ty) => resolver.ty(ty), |
691 | InstanceTypeDecl::Export(export) => resolver.item_sig(&mut export.item), |
692 | }, |
693 | |state, decl| { |
694 | match decl { |
695 | InstanceTypeDecl::Alias(alias) => { |
696 | state.register_alias(alias)?; |
697 | } |
698 | InstanceTypeDecl::CoreType(ty) => { |
699 | state.core_types.register(ty.id, "core type" )?; |
700 | } |
701 | InstanceTypeDecl::Type(ty) => { |
702 | state.types.register(ty.id, "type" )?; |
703 | } |
704 | InstanceTypeDecl::Export(export) => { |
705 | state.register_item_sig(&export.item)?; |
706 | } |
707 | } |
708 | Ok(()) |
709 | }, |
710 | ) |
711 | } |
712 | |
713 | fn core_item_ref<K>(&mut self, item: &mut CoreItemRef<'a, K>) -> Result<(), Error> |
714 | where |
715 | K: CoreItem + Copy, |
716 | { |
717 | // Check for not being an instance export reference |
718 | if item.export_name.is_none() { |
719 | self.resolve_ns(&mut item.idx, item.kind.ns())?; |
720 | return Ok(()); |
721 | } |
722 | |
723 | // This is a reference to a core instance export |
724 | let mut index = item.idx; |
725 | self.resolve_ns(&mut index, Ns::CoreInstance)?; |
726 | |
727 | // Record an alias to reference the export |
728 | let span = item.idx.span(); |
729 | let alias = Alias { |
730 | span, |
731 | id: None, |
732 | name: None, |
733 | target: AliasTarget::CoreExport { |
734 | instance: index, |
735 | name: item.export_name.unwrap(), |
736 | kind: item.kind.ns().into(), |
737 | }, |
738 | }; |
739 | |
740 | index = Index::Num(self.current().register_alias(&alias)?, span); |
741 | self.aliases_to_insert.push(alias); |
742 | |
743 | item.idx = index; |
744 | item.export_name = None; |
745 | |
746 | Ok(()) |
747 | } |
748 | |
749 | fn component_item_ref<K>(&mut self, item: &mut ItemRef<'a, K>) -> Result<(), Error> |
750 | where |
751 | K: ComponentItem + Copy, |
752 | { |
753 | // Check for not being an instance export reference |
754 | if item.export_names.is_empty() { |
755 | self.resolve_ns(&mut item.idx, item.kind.ns())?; |
756 | return Ok(()); |
757 | } |
758 | |
759 | // This is a reference to an instance export |
760 | let mut index = item.idx; |
761 | self.resolve_ns(&mut index, Ns::Instance)?; |
762 | |
763 | let span = item.idx.span(); |
764 | for (pos, export_name) in item.export_names.iter().enumerate() { |
765 | // Record an alias to reference the export |
766 | let alias = Alias { |
767 | span, |
768 | id: None, |
769 | name: None, |
770 | target: AliasTarget::Export { |
771 | instance: index, |
772 | name: export_name, |
773 | kind: if pos == item.export_names.len() - 1 { |
774 | item.kind.ns().into() |
775 | } else { |
776 | ComponentExportAliasKind::Instance |
777 | }, |
778 | }, |
779 | }; |
780 | |
781 | index = Index::Num(self.current().register_alias(&alias)?, span); |
782 | self.aliases_to_insert.push(alias); |
783 | } |
784 | |
785 | item.idx = index; |
786 | item.export_names = Vec::new(); |
787 | |
788 | Ok(()) |
789 | } |
790 | |
791 | fn resolve_ns(&mut self, idx: &mut Index<'a>, ns: Ns) -> Result<u32, Error> { |
792 | // Perform resolution on a local clone walking up the stack of components |
793 | // that we have. Note that a local clone is used since we don't want to use |
794 | // the parent's resolved index if a parent matches, instead we want to use |
795 | // the index of the alias that we will automatically insert. |
796 | let mut idx_clone = *idx; |
797 | for (depth, resolver) in self.stack.iter_mut().rev().enumerate() { |
798 | let depth = depth as u32; |
799 | let found = match resolver.resolve(ns, &mut idx_clone) { |
800 | Ok(idx) => idx, |
801 | // Try the next parent |
802 | Err(_) => continue, |
803 | }; |
804 | |
805 | // If this is the current component then no extra alias is necessary, so |
806 | // return success. |
807 | if depth == 0 { |
808 | *idx = idx_clone; |
809 | return Ok(found); |
810 | } |
811 | let id = match idx { |
812 | Index::Id(id) => *id, |
813 | Index::Num(..) => unreachable!(), |
814 | }; |
815 | |
816 | // When resolution succeeds in a parent then an outer alias is |
817 | // automatically inserted here in this component. |
818 | let span = idx.span(); |
819 | let alias = Alias { |
820 | span, |
821 | id: Some(id), |
822 | name: None, |
823 | target: AliasTarget::Outer { |
824 | outer: Index::Num(depth, span), |
825 | index: Index::Num(found, span), |
826 | kind: ns.into(), |
827 | }, |
828 | }; |
829 | let local_index = self.current().register_alias(&alias)?; |
830 | self.aliases_to_insert.push(alias); |
831 | *idx = Index::Num(local_index, span); |
832 | return Ok(local_index); |
833 | } |
834 | |
835 | // If resolution in any parent failed then simply return the error from our |
836 | // local namespace |
837 | self.current().resolve(ns, idx)?; |
838 | unreachable!() |
839 | } |
840 | |
841 | fn module_type(&mut self, ty: &mut ModuleType<'a>) -> Result<(), Error> { |
842 | return self.resolve_prepending_aliases( |
843 | &mut ty.decls, |
844 | |resolver, decl| match decl { |
845 | ModuleTypeDecl::Alias(alias) => resolver.alias(alias), |
846 | |
847 | // For types since the GC proposal to core wasm they're allowed |
848 | // to both refer to themselves and additionally a recursion |
849 | // group can define a set of types that all refer to one |
850 | // another. That means that the type names must be registered |
851 | // first before the type is resolved so the type's own name is |
852 | // in scope for itself. |
853 | // |
854 | // Note though that this means that aliases cannot be injected |
855 | // automatically for references to outer types. We don't know |
856 | // how many aliases are going to be created so we otherwise |
857 | // don't know the type index to register. |
858 | // |
859 | // As a compromise for now core types don't support |
860 | // auto-injection of aliases from outer scopes. They must be |
861 | // explicitly aliased in. Also note that the error message isn't |
862 | // great either. This may be something we want to improve in the |
863 | // future with a better error message or a pass that goes over |
864 | // everything first to inject aliases and then afterwards all |
865 | // other names are registered. |
866 | ModuleTypeDecl::Type(t) => { |
867 | resolver.current().core_types.register(t.id, "type" )?; |
868 | resolver.current().resolve_type(t) |
869 | } |
870 | ModuleTypeDecl::Rec(t) => { |
871 | for t in t.types.iter_mut() { |
872 | resolver.current().core_types.register(t.id, "type" )?; |
873 | } |
874 | for t in t.types.iter_mut() { |
875 | resolver.current().resolve_type(t)?; |
876 | } |
877 | Ok(()) |
878 | } |
879 | |
880 | ModuleTypeDecl::Import(import) => resolve_item_sig(resolver, &mut import.item), |
881 | ModuleTypeDecl::Export(_, item) => resolve_item_sig(resolver, item), |
882 | }, |
883 | |state, decl| { |
884 | match decl { |
885 | ModuleTypeDecl::Alias(alias) => { |
886 | state.register_alias(alias)?; |
887 | } |
888 | // These were registered above already |
889 | ModuleTypeDecl::Type(_) | ModuleTypeDecl::Rec(_) => {} |
890 | // Only the type namespace is populated within the module type |
891 | // namespace so these are ignored here. |
892 | ModuleTypeDecl::Import(_) | ModuleTypeDecl::Export(..) => {} |
893 | } |
894 | Ok(()) |
895 | }, |
896 | ); |
897 | |
898 | fn resolve_item_sig<'a>( |
899 | resolver: &Resolver<'a>, |
900 | sig: &mut core::ItemSig<'a>, |
901 | ) -> Result<(), Error> { |
902 | match &mut sig.kind { |
903 | core::ItemKind::Func(ty) | core::ItemKind::Tag(core::TagType::Exception(ty)) => { |
904 | let idx = ty.index.as_mut().expect("index should be filled in" ); |
905 | resolver |
906 | .stack |
907 | .last() |
908 | .unwrap() |
909 | .core_types |
910 | .resolve(idx, "type" )?; |
911 | } |
912 | core::ItemKind::Memory(_) |
913 | | core::ItemKind::Global(_) |
914 | | core::ItemKind::Table(_) => {} |
915 | } |
916 | Ok(()) |
917 | } |
918 | } |
919 | } |
920 | |
921 | impl<'a> ComponentState<'a> { |
922 | fn resolve(&self, ns: Ns, idx: &mut Index<'a>) -> Result<u32, Error> { |
923 | match ns { |
924 | Ns::CoreFunc => self.core_funcs.resolve(idx, "core func" ), |
925 | Ns::CoreGlobal => self.core_globals.resolve(idx, "core global" ), |
926 | Ns::CoreTable => self.core_tables.resolve(idx, "core table" ), |
927 | Ns::CoreMemory => self.core_memories.resolve(idx, "core memory" ), |
928 | Ns::CoreType => self.core_types.resolve(idx, "core type" ), |
929 | Ns::CoreTag => self.core_tags.resolve(idx, "core tag" ), |
930 | Ns::CoreInstance => self.core_instances.resolve(idx, "core instance" ), |
931 | Ns::CoreModule => self.core_modules.resolve(idx, "core module" ), |
932 | Ns::Func => self.funcs.resolve(idx, "func" ), |
933 | Ns::Type => self.types.resolve(idx, "type" ), |
934 | Ns::Instance => self.instances.resolve(idx, "instance" ), |
935 | Ns::Component => self.components.resolve(idx, "component" ), |
936 | Ns::Value => self.values.resolve(idx, "value" ), |
937 | } |
938 | } |
939 | |
940 | /// Assign an index to the given field. |
941 | fn register(&mut self, item: &ComponentField<'a>) -> Result<(), Error> { |
942 | match item { |
943 | ComponentField::CoreModule(m) => self.core_modules.register(m.id, "core module" )?, |
944 | ComponentField::CoreInstance(i) => { |
945 | self.core_instances.register(i.id, "core instance" )? |
946 | } |
947 | ComponentField::CoreType(ty) => match &ty.def { |
948 | CoreTypeDef::Def(_) => 0, // done above in `core_rec` |
949 | CoreTypeDef::Module(_) => self.core_types.register(ty.id, "core type" )?, |
950 | }, |
951 | ComponentField::CoreRec(_) => 0, // done above in `core_rec` |
952 | ComponentField::Component(c) => self.components.register(c.id, "component" )?, |
953 | ComponentField::Instance(i) => self.instances.register(i.id, "instance" )?, |
954 | ComponentField::Alias(a) => self.register_alias(a)?, |
955 | ComponentField::Type(t) => self.types.register(t.id, "type" )?, |
956 | ComponentField::CanonicalFunc(f) => match &f.kind { |
957 | CanonicalFuncKind::Lift { .. } => self.funcs.register(f.id, "func" )?, |
958 | CanonicalFuncKind::Lower(_) |
959 | | CanonicalFuncKind::ResourceNew(_) |
960 | | CanonicalFuncKind::ResourceRep(_) |
961 | | CanonicalFuncKind::ResourceDrop(_) |
962 | | CanonicalFuncKind::ThreadSpawn(_) |
963 | | CanonicalFuncKind::ThreadHwConcurrency(_) |
964 | | CanonicalFuncKind::TaskBackpressure |
965 | | CanonicalFuncKind::TaskReturn(_) |
966 | | CanonicalFuncKind::TaskWait(_) |
967 | | CanonicalFuncKind::TaskPoll(_) |
968 | | CanonicalFuncKind::TaskYield(_) |
969 | | CanonicalFuncKind::SubtaskDrop |
970 | | CanonicalFuncKind::StreamNew(_) |
971 | | CanonicalFuncKind::StreamRead(_) |
972 | | CanonicalFuncKind::StreamWrite(_) |
973 | | CanonicalFuncKind::StreamCancelRead(_) |
974 | | CanonicalFuncKind::StreamCancelWrite(_) |
975 | | CanonicalFuncKind::StreamCloseReadable(_) |
976 | | CanonicalFuncKind::StreamCloseWritable(_) |
977 | | CanonicalFuncKind::FutureNew(_) |
978 | | CanonicalFuncKind::FutureRead(_) |
979 | | CanonicalFuncKind::FutureWrite(_) |
980 | | CanonicalFuncKind::FutureCancelRead(_) |
981 | | CanonicalFuncKind::FutureCancelWrite(_) |
982 | | CanonicalFuncKind::FutureCloseReadable(_) |
983 | | CanonicalFuncKind::FutureCloseWritable(_) |
984 | | CanonicalFuncKind::ErrorContextNew(_) |
985 | | CanonicalFuncKind::ErrorContextDebugMessage(_) |
986 | | CanonicalFuncKind::ErrorContextDrop => { |
987 | self.core_funcs.register(f.id, "core func" )? |
988 | } |
989 | }, |
990 | ComponentField::CoreFunc(_) | ComponentField::Func(_) => { |
991 | unreachable!("should be expanded already" ) |
992 | } |
993 | ComponentField::Start(s) => { |
994 | for r in &s.results { |
995 | self.values.register(*r, "value" )?; |
996 | } |
997 | return Ok(()); |
998 | } |
999 | ComponentField::Import(i) => self.register_item_sig(&i.item)?, |
1000 | ComponentField::Export(e) => match &e.kind { |
1001 | ComponentExportKind::CoreModule(_) => { |
1002 | self.core_modules.register(e.id, "core module" )? |
1003 | } |
1004 | ComponentExportKind::Func(_) => self.funcs.register(e.id, "func" )?, |
1005 | ComponentExportKind::Instance(_) => self.instances.register(e.id, "instance" )?, |
1006 | ComponentExportKind::Value(_) => self.values.register(e.id, "value" )?, |
1007 | ComponentExportKind::Component(_) => self.components.register(e.id, "component" )?, |
1008 | ComponentExportKind::Type(_) => self.types.register(e.id, "type" )?, |
1009 | }, |
1010 | ComponentField::Custom(_) | ComponentField::Producers(_) => return Ok(()), |
1011 | }; |
1012 | |
1013 | Ok(()) |
1014 | } |
1015 | |
1016 | fn register_alias(&mut self, alias: &Alias<'a>) -> Result<u32, Error> { |
1017 | match alias.target { |
1018 | AliasTarget::Export { kind, .. } => match kind { |
1019 | ComponentExportAliasKind::CoreModule => { |
1020 | self.core_modules.register(alias.id, "core module" ) |
1021 | } |
1022 | ComponentExportAliasKind::Func => self.funcs.register(alias.id, "func" ), |
1023 | ComponentExportAliasKind::Value => self.values.register(alias.id, "value" ), |
1024 | ComponentExportAliasKind::Type => self.types.register(alias.id, "type" ), |
1025 | ComponentExportAliasKind::Component => { |
1026 | self.components.register(alias.id, "component" ) |
1027 | } |
1028 | ComponentExportAliasKind::Instance => self.instances.register(alias.id, "instance" ), |
1029 | }, |
1030 | AliasTarget::CoreExport { kind, .. } => match kind { |
1031 | core::ExportKind::Func => self.core_funcs.register(alias.id, "core func" ), |
1032 | core::ExportKind::Table => self.core_tables.register(alias.id, "core table" ), |
1033 | core::ExportKind::Memory => self.core_memories.register(alias.id, "core memory" ), |
1034 | core::ExportKind::Global => self.core_globals.register(alias.id, "core global" ), |
1035 | core::ExportKind::Tag => self.core_tags.register(alias.id, "core tag" ), |
1036 | }, |
1037 | AliasTarget::Outer { kind, .. } => match kind { |
1038 | ComponentOuterAliasKind::CoreModule => { |
1039 | self.core_modules.register(alias.id, "core module" ) |
1040 | } |
1041 | ComponentOuterAliasKind::CoreType => { |
1042 | self.core_types.register(alias.id, "core type" ) |
1043 | } |
1044 | ComponentOuterAliasKind::Type => self.types.register(alias.id, "type" ), |
1045 | ComponentOuterAliasKind::Component => { |
1046 | self.components.register(alias.id, "component" ) |
1047 | } |
1048 | }, |
1049 | } |
1050 | } |
1051 | } |
1052 | |
1053 | impl<'a> ResolveCoreType<'a> for ComponentState<'a> { |
1054 | fn resolve_type_name(&mut self, name: &mut Index<'a>) -> Result<u32, Error> { |
1055 | self.resolve(Ns::CoreType, idx:name) |
1056 | } |
1057 | } |
1058 | |
1059 | #[derive (PartialEq, Eq, Hash, Copy, Clone, Debug)] |
1060 | enum Ns { |
1061 | CoreFunc, |
1062 | CoreGlobal, |
1063 | CoreTable, |
1064 | CoreMemory, |
1065 | CoreType, |
1066 | CoreTag, |
1067 | CoreInstance, |
1068 | CoreModule, |
1069 | Func, |
1070 | Type, |
1071 | Instance, |
1072 | Component, |
1073 | Value, |
1074 | } |
1075 | |
1076 | trait ComponentItem { |
1077 | fn ns(&self) -> Ns; |
1078 | } |
1079 | |
1080 | trait CoreItem { |
1081 | fn ns(&self) -> Ns; |
1082 | } |
1083 | |
1084 | macro_rules! component_item { |
1085 | ($kw:path, $kind:ident) => { |
1086 | impl ComponentItem for $kw { |
1087 | fn ns(&self) -> Ns { |
1088 | Ns::$kind |
1089 | } |
1090 | } |
1091 | }; |
1092 | } |
1093 | |
1094 | macro_rules! core_item { |
1095 | ($kw:path, $kind:ident) => { |
1096 | impl CoreItem for $kw { |
1097 | fn ns(&self) -> Ns { |
1098 | Ns::$kind |
1099 | } |
1100 | } |
1101 | }; |
1102 | } |
1103 | |
1104 | component_item!(kw::func, Func); |
1105 | component_item!(kw::r#type, Type); |
1106 | component_item!(kw::r#instance, Instance); |
1107 | component_item!(kw::component, Component); |
1108 | component_item!(kw::value, Value); |
1109 | component_item!(kw::module, CoreModule); |
1110 | |
1111 | core_item!(kw::func, CoreFunc); |
1112 | core_item!(kw::memory, CoreMemory); |
1113 | core_item!(kw::r#type, CoreType); |
1114 | core_item!(kw::r#instance, CoreInstance); |
1115 | |
1116 | impl From<Ns> for ComponentExportAliasKind { |
1117 | fn from(ns: Ns) -> Self { |
1118 | match ns { |
1119 | Ns::CoreModule => Self::CoreModule, |
1120 | Ns::Func => Self::Func, |
1121 | Ns::Type => Self::Type, |
1122 | Ns::Instance => Self::Instance, |
1123 | Ns::Component => Self::Component, |
1124 | Ns::Value => Self::Value, |
1125 | _ => unreachable!("not a component exportable namespace" ), |
1126 | } |
1127 | } |
1128 | } |
1129 | |
1130 | impl From<Ns> for ComponentOuterAliasKind { |
1131 | fn from(ns: Ns) -> Self { |
1132 | match ns { |
1133 | Ns::CoreModule => Self::CoreModule, |
1134 | Ns::CoreType => Self::CoreType, |
1135 | Ns::Type => Self::Type, |
1136 | Ns::Component => Self::Component, |
1137 | _ => unreachable!("not an outer alias namespace" ), |
1138 | } |
1139 | } |
1140 | } |
1141 | |
1142 | impl From<Ns> for core::ExportKind { |
1143 | fn from(ns: Ns) -> Self { |
1144 | match ns { |
1145 | Ns::CoreFunc => Self::Func, |
1146 | Ns::CoreTable => Self::Table, |
1147 | Ns::CoreGlobal => Self::Global, |
1148 | Ns::CoreMemory => Self::Memory, |
1149 | Ns::CoreTag => Self::Tag, |
1150 | _ => unreachable!("not a core exportable namespace" ), |
1151 | } |
1152 | } |
1153 | } |
1154 | |
1155 | impl From<ComponentOuterAliasKind> for Ns { |
1156 | fn from(kind: ComponentOuterAliasKind) -> Self { |
1157 | match kind { |
1158 | ComponentOuterAliasKind::CoreModule => Self::CoreModule, |
1159 | ComponentOuterAliasKind::CoreType => Self::CoreType, |
1160 | ComponentOuterAliasKind::Type => Self::Type, |
1161 | ComponentOuterAliasKind::Component => Self::Component, |
1162 | } |
1163 | } |
1164 | } |
1165 | |
1166 | impl CoreItem for core::ExportKind { |
1167 | fn ns(&self) -> Ns { |
1168 | match self { |
1169 | Self::Func => Ns::CoreFunc, |
1170 | Self::Table => Ns::CoreTable, |
1171 | Self::Global => Ns::CoreGlobal, |
1172 | Self::Memory => Ns::CoreMemory, |
1173 | Self::Tag => Ns::CoreTag, |
1174 | } |
1175 | } |
1176 | } |
1177 | |