1use fuel_abi_types::abi::program::{
2 self as program_abi, ConcreteTypeId, MetadataTypeId, TypeConcreteDeclaration,
3};
4use sha2::{Digest, Sha256};
5use std::collections::{HashMap, HashSet};
6use sway_error::handler::{ErrorEmitted, Handler};
7use sway_types::Span;
8
9use crate::{
10 language::ty::{TyFunctionDecl, TyProgram, TyProgramKind},
11 transform::AttributesMap,
12 Engines, TypeId, TypeInfo, TypeParameter,
13};
14
15use super::abi_str::AbiStrContext;
16
17pub struct AbiContext<'a> {
18 pub program: &'a TyProgram,
19 pub abi_with_callpaths: bool,
20 pub type_ids_to_full_type_str: HashMap<String, String>,
21}
22
23impl AbiContext<'_> {
24 fn to_str_context(&self) -> AbiStrContext {
25 AbiStrContext {
26 program_name: self.program.namespace.current_package_name().to_string(),
27 abi_with_callpaths: self.abi_with_callpaths,
28 abi_with_fully_specified_types: false,
29 abi_root_type_without_generic_type_parameters: true,
30 }
31 }
32}
33
34impl TypeId {
35 fn get_abi_type_field_and_concrete_id(
36 &self,
37 handler: &Handler,
38 ctx: &mut AbiContext,
39 engines: &Engines,
40 resolved_type_id: TypeId,
41 ) -> Result<(String, ConcreteTypeId), ErrorEmitted> {
42 let type_str = self.get_abi_type_str(
43 &AbiStrContext {
44 program_name: ctx.program.namespace.current_package_name().to_string(),
45 abi_with_callpaths: true,
46 abi_with_fully_specified_types: true,
47 abi_root_type_without_generic_type_parameters: false,
48 },
49 engines,
50 resolved_type_id,
51 );
52 let mut hasher = Sha256::new();
53 hasher.update(type_str.clone());
54 let result = hasher.finalize();
55 let type_id = format!("{:x}", result);
56
57 if let Some(old_type_str) = ctx
58 .type_ids_to_full_type_str
59 .insert(type_id.clone(), type_str.clone())
60 {
61 if old_type_str != type_str {
62 return Err(
63 handler.emit_err(sway_error::error::CompileError::ABIHashCollision {
64 span: Span::dummy(),
65 hash: type_id,
66 first_type: old_type_str,
67 second_type: type_str,
68 }),
69 );
70 }
71 }
72
73 Ok((type_str, ConcreteTypeId(type_id)))
74 }
75}
76
77pub fn generate_program_abi(
78 handler: &Handler,
79 ctx: &mut AbiContext,
80 engines: &Engines,
81 encoding_version: program_abi::Version,
82 spec_version: program_abi::Version,
83) -> Result<program_abi::ProgramABI, ErrorEmitted> {
84 let decl_engine = engines.de();
85 let metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration> = &mut vec![];
86 let concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration> = &mut vec![];
87 let mut program_abi = match &ctx.program.kind {
88 TyProgramKind::Contract { abi_entries, .. } => {
89 let functions = abi_entries
90 .iter()
91 .map(|x| {
92 let fn_decl = decl_engine.get_function(x);
93 fn_decl.generate_abi_function(
94 handler,
95 ctx,
96 engines,
97 metadata_types,
98 concrete_types,
99 )
100 })
101 .collect::<Result<Vec<_>, _>>()?;
102 let logged_types =
103 generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?;
104 let messages_types =
105 generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?;
106 let configurables =
107 generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?;
108 program_abi::ProgramABI {
109 program_type: "contract".to_string(),
110 spec_version,
111 encoding_version,
112 metadata_types: metadata_types.to_vec(),
113 concrete_types: concrete_types.to_vec(),
114 functions,
115 logged_types: Some(logged_types),
116 messages_types: Some(messages_types),
117 configurables: Some(configurables),
118 }
119 }
120 TyProgramKind::Script { main_function, .. } => {
121 let main_function = decl_engine.get_function(main_function);
122 let functions = vec![main_function.generate_abi_function(
123 handler,
124 ctx,
125 engines,
126 metadata_types,
127 concrete_types,
128 )?];
129 let logged_types =
130 generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?;
131 let messages_types =
132 generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?;
133 let configurables =
134 generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?;
135 program_abi::ProgramABI {
136 program_type: "script".to_string(),
137 spec_version,
138 encoding_version,
139 metadata_types: metadata_types.to_vec(),
140 concrete_types: concrete_types.to_vec(),
141 functions,
142 logged_types: Some(logged_types),
143 messages_types: Some(messages_types),
144 configurables: Some(configurables),
145 }
146 }
147 TyProgramKind::Predicate { main_function, .. } => {
148 let main_function = decl_engine.get_function(main_function);
149 let functions = vec![main_function.generate_abi_function(
150 handler,
151 ctx,
152 engines,
153 metadata_types,
154 concrete_types,
155 )?];
156 let logged_types =
157 generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?;
158 let messages_types =
159 generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?;
160 let configurables =
161 generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?;
162 program_abi::ProgramABI {
163 program_type: "predicate".to_string(),
164 spec_version,
165 encoding_version,
166 metadata_types: metadata_types.to_vec(),
167 concrete_types: concrete_types.to_vec(),
168 functions,
169 logged_types: Some(logged_types),
170 messages_types: Some(messages_types),
171 configurables: Some(configurables),
172 }
173 }
174 TyProgramKind::Library { .. } => {
175 let logged_types =
176 generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?;
177 let messages_types =
178 generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?;
179
180 program_abi::ProgramABI {
181 program_type: "library".to_string(),
182 spec_version,
183 encoding_version,
184 metadata_types: metadata_types.to_vec(),
185 concrete_types: concrete_types.to_vec(),
186 functions: vec![],
187 logged_types: Some(logged_types),
188 messages_types: Some(messages_types),
189 configurables: None,
190 }
191 }
192 };
193
194 standardize_json_abi_types(&mut program_abi);
195
196 Ok(program_abi)
197}
198
199fn standardize_json_abi_types(json_abi_program: &mut program_abi::ProgramABI) {
202 loop {
204 let mut old_to_new_id: HashMap<MetadataTypeId, program_abi::TypeId> = HashMap::new();
207
208 let mut deduped_types: Vec<program_abi::TypeMetadataDeclaration> = Vec::new();
214
215 for decl in &json_abi_program.metadata_types {
218 if let Some(ty) = json_abi_program.concrete_types.iter().find(|d| {
220 d.type_field == decl.type_field
221 && decl.components.is_none()
222 && decl.type_parameters.is_none()
223 }) {
224 old_to_new_id.insert(
225 decl.metadata_type_id.clone(),
226 program_abi::TypeId::Concrete(ty.concrete_type_id.clone()),
227 );
228 } else {
229 if let Some(ty) = deduped_types.iter().find(|d| {
231 d.type_field == decl.type_field
232 && d.components == decl.components
233 && d.type_parameters == decl.type_parameters
234 }) {
235 old_to_new_id.insert(
236 decl.metadata_type_id.clone(),
237 program_abi::TypeId::Metadata(ty.metadata_type_id.clone()),
238 );
239 } else {
240 deduped_types.push(decl.clone());
241 }
242 }
243 }
244
245 if old_to_new_id.is_empty() {
248 break;
249 }
250
251 json_abi_program.metadata_types = deduped_types;
252
253 update_all_types(json_abi_program, &old_to_new_id);
254 }
255
256 let mut concrete_declarations_map: HashMap<ConcreteTypeId, TypeConcreteDeclaration> =
258 HashMap::new();
259 for decl in &json_abi_program.concrete_types {
260 concrete_declarations_map.insert(decl.concrete_type_id.clone(), decl.clone());
261 }
262 json_abi_program.concrete_types = concrete_declarations_map.values().cloned().collect();
263
264 json_abi_program
266 .metadata_types
267 .sort_by(|t1, t2| t1.type_field.cmp(&t2.type_field));
268
269 json_abi_program
271 .concrete_types
272 .sort_by(|t1, t2| t1.type_field.cmp(&t2.type_field));
273
274 let mut old_to_new_id: HashMap<MetadataTypeId, program_abi::TypeId> = HashMap::new();
276 for (ix, decl) in json_abi_program.metadata_types.iter_mut().enumerate() {
277 old_to_new_id.insert(
278 decl.metadata_type_id.clone(),
279 program_abi::TypeId::Metadata(MetadataTypeId(ix)),
280 );
281 decl.metadata_type_id = MetadataTypeId(ix);
282 }
283
284 update_all_types(json_abi_program, &old_to_new_id);
285}
286
287fn update_all_types(
289 json_abi_program: &mut program_abi::ProgramABI,
290 old_to_new_id: &HashMap<MetadataTypeId, program_abi::TypeId>,
291) {
292 for decl in &mut json_abi_program.metadata_types {
294 update_json_type_metadata_declaration(decl, old_to_new_id);
295 }
296
297 for decl in &mut json_abi_program.concrete_types {
299 update_json_type_concrete_declaration(decl, old_to_new_id);
300 }
301}
302
303fn update_json_type_application(
306 type_application: &mut program_abi::TypeApplication,
307 old_to_new_id: &HashMap<MetadataTypeId, program_abi::TypeId>,
308) {
309 if let fuel_abi_types::abi::program::TypeId::Metadata(metadata_type_id) =
310 &type_application.type_id
311 {
312 if let Some(new_id) = old_to_new_id.get(metadata_type_id) {
313 type_application.type_id = new_id.clone();
314 }
315 }
316
317 if let Some(args) = &mut type_application.type_arguments {
318 for arg in args.iter_mut() {
319 update_json_type_application(arg, old_to_new_id);
320 }
321 }
322}
323
324fn update_json_type_metadata_declaration(
327 type_declaration: &mut program_abi::TypeMetadataDeclaration,
328 old_to_new_id: &HashMap<MetadataTypeId, program_abi::TypeId>,
329) {
330 if let Some(params) = &mut type_declaration.type_parameters {
331 for param in params.iter_mut() {
332 if let Some(fuel_abi_types::abi::program::TypeId::Metadata(new_id)) =
333 old_to_new_id.get(param)
334 {
335 *param = new_id.clone();
336 }
337 }
338 }
339
340 if let Some(components) = &mut type_declaration.components {
341 for component in components.iter_mut() {
342 update_json_type_application(component, old_to_new_id);
343 }
344 }
345}
346
347fn update_json_type_concrete_declaration(
350 type_declaration: &mut program_abi::TypeConcreteDeclaration,
351 old_to_new_id: &HashMap<MetadataTypeId, program_abi::TypeId>,
352) {
353 if let Some(metadata_type_id) = &mut type_declaration.metadata_type_id {
354 if let Some(fuel_abi_types::abi::program::TypeId::Metadata(new_id)) =
355 old_to_new_id.get(metadata_type_id)
356 {
357 *metadata_type_id = new_id.clone();
358 }
359 }
360}
361
362fn generate_concrete_type_declaration(
363 handler: &Handler,
364 ctx: &mut AbiContext,
365 engines: &Engines,
366 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
367 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
368 type_id: TypeId,
369 resolved_type_id: TypeId,
370) -> Result<ConcreteTypeId, ErrorEmitted> {
371 let mut new_metadata_types_to_add = Vec::<program_abi::TypeMetadataDeclaration>::new();
372 let type_metadata_decl = program_abi::TypeMetadataDeclaration {
373 metadata_type_id: MetadataTypeId(type_id.index()),
374 type_field: type_id.get_abi_type_str(&ctx.to_str_context(), engines, resolved_type_id),
375 components: type_id.get_abi_type_components(
376 handler,
377 ctx,
378 engines,
379 metadata_types,
380 concrete_types,
381 resolved_type_id,
382 &mut new_metadata_types_to_add,
383 )?,
384 type_parameters: type_id.get_abi_type_parameters(
385 handler,
386 ctx,
387 engines,
388 metadata_types,
389 concrete_types,
390 resolved_type_id,
391 &mut new_metadata_types_to_add,
392 )?,
393 };
394
395 let metadata_type_id = if type_metadata_decl.type_parameters.is_some()
396 || type_metadata_decl.components.is_some()
397 {
398 Some(type_metadata_decl.metadata_type_id.clone())
399 } else {
400 None
401 };
402 let type_arguments = if type_metadata_decl.type_parameters.is_some() {
403 type_id.get_abi_type_arguments_as_concrete_type_ids(
404 handler,
405 ctx,
406 engines,
407 metadata_types,
408 concrete_types,
409 resolved_type_id,
410 )?
411 } else {
412 None
413 };
414
415 metadata_types.push(type_metadata_decl);
416 metadata_types.extend(new_metadata_types_to_add);
417
418 let (type_field, concrete_type_id) =
419 type_id.get_abi_type_field_and_concrete_id(handler, ctx, engines, resolved_type_id)?;
420 let concrete_type_decl = TypeConcreteDeclaration {
421 type_field,
422 concrete_type_id: concrete_type_id.clone(),
423 metadata_type_id,
424 type_arguments,
425 };
426
427 concrete_types.push(concrete_type_decl);
428
429 Ok(concrete_type_id)
430}
431
432#[allow(clippy::too_many_arguments)]
433fn generate_type_metadata_declaration(
434 handler: &Handler,
435 ctx: &mut AbiContext,
436 engines: &Engines,
437 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
438 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
439 type_id: TypeId,
440 resolved_type_id: TypeId,
441 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
442) -> Result<(), ErrorEmitted> {
443 let mut new_metadata_types_to_add = Vec::<program_abi::TypeMetadataDeclaration>::new();
444 let components = type_id.get_abi_type_components(
445 handler,
446 ctx,
447 engines,
448 metadata_types,
449 concrete_types,
450 resolved_type_id,
451 &mut new_metadata_types_to_add,
452 )?;
453 let type_parameters = type_id.get_abi_type_parameters(
454 handler,
455 ctx,
456 engines,
457 metadata_types,
458 concrete_types,
459 resolved_type_id,
460 &mut new_metadata_types_to_add,
461 )?;
462 let type_metadata_decl = program_abi::TypeMetadataDeclaration {
463 metadata_type_id: MetadataTypeId(type_id.index()),
464 type_field: type_id.get_abi_type_str(&ctx.to_str_context(), engines, resolved_type_id),
465 components,
466 type_parameters,
467 };
468
469 metadata_types_to_add.push(type_metadata_decl.clone());
470 metadata_types_to_add.extend(new_metadata_types_to_add);
471
472 Ok(())
473}
474
475fn generate_logged_types(
476 handler: &Handler,
477 ctx: &mut AbiContext,
478 engines: &Engines,
479 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
480 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
481) -> Result<Vec<program_abi::LoggedType>, ErrorEmitted> {
482 let mut log_ids: HashSet<u64> = HashSet::default();
484 Ok(ctx
485 .program
486 .logged_types
487 .iter()
488 .map(|(log_id, type_id)| {
489 let log_id = log_id.hash_id;
490 if log_ids.contains(&log_id) {
491 Ok(None)
492 } else {
493 log_ids.insert(log_id);
494 Ok(Some(program_abi::LoggedType {
495 log_id: log_id.to_string(),
496 concrete_type_id: generate_concrete_type_declaration(
497 handler,
498 ctx,
499 engines,
500 metadata_types,
501 concrete_types,
502 *type_id,
503 *type_id,
504 )?,
505 }))
506 }
507 })
508 .collect::<Result<Vec<_>, _>>()?
509 .into_iter()
510 .flatten()
511 .collect())
512}
513
514fn generate_messages_types(
515 handler: &Handler,
516 ctx: &mut AbiContext,
517 engines: &Engines,
518 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
519 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
520) -> Result<Vec<program_abi::MessageType>, ErrorEmitted> {
521 ctx.program
523 .messages_types
524 .iter()
525 .map(|(message_id, type_id)| {
526 Ok(program_abi::MessageType {
527 message_id: (**message_id as u64).to_string(),
528 concrete_type_id: generate_concrete_type_declaration(
529 handler,
530 ctx,
531 engines,
532 metadata_types,
533 concrete_types,
534 *type_id,
535 *type_id,
536 )?,
537 })
538 })
539 .collect::<Result<Vec<_>, _>>()
540}
541
542fn generate_configurables(
543 handler: &Handler,
544 ctx: &mut AbiContext,
545 engines: &Engines,
546 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
547 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
548) -> Result<Vec<program_abi::Configurable>, ErrorEmitted> {
549 ctx.program
551 .configurables
552 .iter()
553 .map(|decl| {
554 Ok(program_abi::Configurable {
555 name: decl.call_path.suffix.to_string(),
556 concrete_type_id: generate_concrete_type_declaration(
557 handler,
558 ctx,
559 engines,
560 metadata_types,
561 concrete_types,
562 decl.type_ascription.type_id,
563 decl.type_ascription.type_id,
564 )?,
565 offset: 0,
566 })
567 })
568 .collect::<Result<Vec<_>, _>>()
569}
570
571impl TypeId {
572 #[allow(clippy::too_many_arguments)]
578 pub(self) fn get_abi_type_parameters(
579 &self,
580 handler: &Handler,
581 ctx: &mut AbiContext,
582 engines: &Engines,
583 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
584 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
585 resolved_type_id: TypeId,
586 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
587 ) -> Result<Option<Vec<MetadataTypeId>>, ErrorEmitted> {
588 match self.is_generic_parameter(engines, resolved_type_id) {
589 true => Ok(None),
590 false => resolved_type_id
591 .get_type_parameters(engines)
592 .map(|v| {
593 v.iter()
594 .map(|v| {
595 v.get_abi_type_parameter(
596 handler,
597 ctx,
598 engines,
599 metadata_types,
600 concrete_types,
601 metadata_types_to_add,
602 )
603 })
604 .collect::<Result<Vec<_>, _>>()
605 })
606 .map_or(Ok(None), |v| v.map(Some)),
607 }
608 }
609
610 #[allow(clippy::too_many_arguments)]
615 pub(self) fn get_abi_type_components(
616 &self,
617 handler: &Handler,
618 ctx: &mut AbiContext,
619 engines: &Engines,
620 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
621 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
622 resolved_type_id: TypeId,
623 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
624 ) -> Result<Option<Vec<program_abi::TypeApplication>>, ErrorEmitted> {
625 let type_engine = engines.te();
626 let decl_engine = engines.de();
627 Ok(match &*type_engine.get(*self) {
628 TypeInfo::Enum(decl_ref) => {
629 let decl = decl_engine.get_enum(decl_ref);
630
631 let mut new_metadata_types_to_add =
632 Vec::<program_abi::TypeMetadataDeclaration>::new();
633 for x in decl.variants.iter() {
634 generate_type_metadata_declaration(
635 handler,
636 ctx,
637 engines,
638 metadata_types,
639 concrete_types,
640 x.type_argument.initial_type_id,
641 x.type_argument.type_id,
642 &mut new_metadata_types_to_add,
643 )?;
644 }
645
646 let components = decl
649 .variants
650 .iter()
651 .map(|x| {
652 Ok(program_abi::TypeApplication {
653 name: x.name.to_string(),
654 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
655 x.type_argument.initial_type_id.index(),
656 )),
657 type_arguments: x
658 .type_argument
659 .initial_type_id
660 .get_abi_type_arguments(
661 handler,
662 ctx,
663 engines,
664 metadata_types,
665 concrete_types,
666 x.type_argument.type_id,
667 &mut new_metadata_types_to_add,
668 )?,
669 })
670 })
671 .collect::<Result<Vec<_>, _>>()?;
672
673 if components.is_empty() {
674 None
675 } else {
676 metadata_types_to_add.extend(new_metadata_types_to_add);
677 Some(components)
678 }
679 }
680 TypeInfo::Struct(decl_ref) => {
681 let decl = decl_engine.get_struct(decl_ref);
682
683 let mut new_metadata_types_to_add =
684 Vec::<program_abi::TypeMetadataDeclaration>::new();
685 for x in decl.fields.iter() {
686 generate_type_metadata_declaration(
687 handler,
688 ctx,
689 engines,
690 metadata_types,
691 concrete_types,
692 x.type_argument.initial_type_id,
693 x.type_argument.type_id,
694 &mut new_metadata_types_to_add,
695 )?;
696 }
697
698 let components = decl
701 .fields
702 .iter()
703 .map(|x| {
704 Ok(program_abi::TypeApplication {
705 name: x.name.to_string(),
706 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
707 x.type_argument.initial_type_id.index(),
708 )),
709 type_arguments: x
710 .type_argument
711 .initial_type_id
712 .get_abi_type_arguments(
713 handler,
714 ctx,
715 engines,
716 metadata_types,
717 concrete_types,
718 x.type_argument.type_id,
719 &mut new_metadata_types_to_add,
720 )?,
721 })
722 })
723 .collect::<Result<Vec<_>, _>>()?;
724
725 if components.is_empty() {
726 None
727 } else {
728 metadata_types_to_add.extend(new_metadata_types_to_add);
729 Some(components)
730 }
731 }
732 TypeInfo::Array(..) => {
733 if let TypeInfo::Array(elem_ty, _) = &*type_engine.get(resolved_type_id) {
734 generate_type_metadata_declaration(
735 handler,
736 ctx,
737 engines,
738 metadata_types,
739 concrete_types,
740 elem_ty.initial_type_id,
741 elem_ty.type_id,
742 metadata_types_to_add,
743 )?;
744
745 Some(vec![program_abi::TypeApplication {
748 name: "__array_element".to_string(),
749 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
750 elem_ty.initial_type_id.index(),
751 )),
752 type_arguments: elem_ty.initial_type_id.get_abi_type_arguments(
753 handler,
754 ctx,
755 engines,
756 metadata_types,
757 concrete_types,
758 elem_ty.type_id,
759 metadata_types_to_add,
760 )?,
761 }])
762 } else {
763 unreachable!();
764 }
765 }
766 TypeInfo::Slice(..) => {
767 if let TypeInfo::Slice(elem_ty) = &*type_engine.get(resolved_type_id) {
768 generate_type_metadata_declaration(
769 handler,
770 ctx,
771 engines,
772 metadata_types,
773 concrete_types,
774 elem_ty.initial_type_id,
775 elem_ty.type_id,
776 metadata_types_to_add,
777 )?;
778
779 Some(vec![program_abi::TypeApplication {
782 name: "__slice_element".to_string(),
783 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
784 elem_ty.initial_type_id.index(),
785 )),
786 type_arguments: elem_ty.initial_type_id.get_abi_type_arguments(
787 handler,
788 ctx,
789 engines,
790 metadata_types,
791 concrete_types,
792 elem_ty.type_id,
793 metadata_types_to_add,
794 )?,
795 }])
796 } else {
797 unreachable!();
798 }
799 }
800 TypeInfo::Tuple(_) => {
801 if let TypeInfo::Tuple(fields) = &*type_engine.get(resolved_type_id) {
802 let mut new_metadata_types_to_add =
803 Vec::<program_abi::TypeMetadataDeclaration>::new();
804 for x in fields.iter() {
805 generate_type_metadata_declaration(
806 handler,
807 ctx,
808 engines,
809 metadata_types,
810 concrete_types,
811 x.initial_type_id,
812 x.type_id,
813 &mut new_metadata_types_to_add,
814 )?;
815 }
816
817 let components = fields
820 .iter()
821 .map(|x| {
822 Ok(program_abi::TypeApplication {
823 name: "__tuple_element".to_string(),
824 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
825 x.initial_type_id.index(),
826 )),
827 type_arguments: x.initial_type_id.get_abi_type_arguments(
828 handler,
829 ctx,
830 engines,
831 metadata_types,
832 concrete_types,
833 x.type_id,
834 metadata_types_to_add,
835 )?,
836 })
837 })
838 .collect::<Result<Vec<_>, _>>()?;
839 if components.is_empty() {
840 None
841 } else {
842 metadata_types_to_add.extend(new_metadata_types_to_add);
843 Some(components)
844 }
845 } else {
846 unreachable!()
847 }
848 }
849 TypeInfo::Custom { type_arguments, .. } => {
850 if !self.is_generic_parameter(engines, resolved_type_id) {
851 for (v, p) in type_arguments.clone().unwrap_or_default().iter().zip(
852 resolved_type_id
853 .get_type_parameters(engines)
854 .unwrap_or_default()
855 .iter(),
856 ) {
857 generate_type_metadata_declaration(
858 handler,
859 ctx,
860 engines,
861 metadata_types,
862 concrete_types,
863 v.initial_type_id,
864 p.type_id,
865 metadata_types_to_add,
866 )?;
867 }
868 resolved_type_id.get_abi_type_components(
869 handler,
870 ctx,
871 engines,
872 metadata_types,
873 concrete_types,
874 resolved_type_id,
875 metadata_types_to_add,
876 )?
877 } else {
878 None
879 }
880 }
881 TypeInfo::Alias { .. } => {
882 if let TypeInfo::Alias { ty, .. } = &*type_engine.get(resolved_type_id) {
883 ty.initial_type_id.get_abi_type_components(
884 handler,
885 ctx,
886 engines,
887 metadata_types,
888 concrete_types,
889 ty.type_id,
890 metadata_types_to_add,
891 )?
892 } else {
893 None
894 }
895 }
896 TypeInfo::UnknownGeneric { .. } => {
897 if *self == resolved_type_id {
899 None
900 } else {
901 resolved_type_id.get_abi_type_components(
902 handler,
903 ctx,
904 engines,
905 metadata_types,
906 concrete_types,
907 resolved_type_id,
908 metadata_types_to_add,
909 )?
910 }
911 }
912 _ => None,
913 })
914 }
915
916 #[allow(clippy::too_many_arguments)]
921 pub(self) fn get_abi_type_arguments(
922 &self,
923 handler: &Handler,
924 ctx: &mut AbiContext,
925 engines: &Engines,
926 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
927 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
928 resolved_type_id: TypeId,
929 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
930 ) -> Result<Option<Vec<program_abi::TypeApplication>>, ErrorEmitted> {
931 let type_engine = engines.te();
932 let decl_engine = engines.de();
933 let resolved_params = resolved_type_id.get_type_parameters(engines);
934 Ok(match &*type_engine.get(*self) {
935 TypeInfo::Custom {
936 type_arguments: Some(type_arguments),
937 ..
938 } => (!type_arguments.is_empty()).then_some({
939 let resolved_params = resolved_params.unwrap_or_default();
940
941 for (v, p) in type_arguments.iter().zip(resolved_params.iter()) {
942 generate_type_metadata_declaration(
943 handler,
944 ctx,
945 engines,
946 metadata_types,
947 concrete_types,
948 v.type_id,
949 p.type_id,
950 metadata_types_to_add,
951 )?;
952 }
953
954 type_arguments
955 .iter()
956 .zip(resolved_params.iter())
957 .map(|(arg, p)| {
958 Ok(program_abi::TypeApplication {
959 name: "".to_string(),
960 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
961 arg.initial_type_id.index(),
962 )),
963 type_arguments: arg.initial_type_id.get_abi_type_arguments(
964 handler,
965 ctx,
966 engines,
967 metadata_types,
968 concrete_types,
969 p.type_id,
970 metadata_types_to_add,
971 )?,
972 })
973 })
974 .collect::<Result<Vec<_>, _>>()?
975 }),
976 TypeInfo::Enum(decl_ref) => {
977 let decl = decl_engine.get_enum(decl_ref);
978
979 let mut new_metadata_types_to_add =
980 Vec::<program_abi::TypeMetadataDeclaration>::new();
981 for v in decl.type_parameters.iter() {
982 generate_type_metadata_declaration(
983 handler,
984 ctx,
985 engines,
986 metadata_types,
987 concrete_types,
988 v.type_id,
989 v.type_id,
990 &mut new_metadata_types_to_add,
991 )?;
992 }
993
994 let type_arguments = decl
995 .type_parameters
996 .iter()
997 .map(|arg| {
998 Ok(program_abi::TypeApplication {
999 name: "".to_string(),
1000 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1001 arg.type_id.index(),
1002 )),
1003 type_arguments: arg.type_id.get_abi_type_arguments(
1004 handler,
1005 ctx,
1006 engines,
1007 metadata_types,
1008 concrete_types,
1009 arg.type_id,
1010 &mut new_metadata_types_to_add,
1011 )?,
1012 })
1013 })
1014 .collect::<Result<Vec<_>, _>>()?;
1015
1016 if type_arguments.is_empty() {
1017 None
1018 } else {
1019 metadata_types_to_add.extend(new_metadata_types_to_add);
1020 Some(type_arguments)
1021 }
1022 }
1023
1024 TypeInfo::Struct(decl_ref) => {
1025 let decl = decl_engine.get_struct(decl_ref);
1026
1027 let mut new_metadata_types_to_add =
1028 Vec::<program_abi::TypeMetadataDeclaration>::new();
1029 for v in decl.type_parameters.iter() {
1030 generate_type_metadata_declaration(
1031 handler,
1032 ctx,
1033 engines,
1034 metadata_types,
1035 concrete_types,
1036 v.type_id,
1037 v.type_id,
1038 &mut new_metadata_types_to_add,
1039 )?;
1040 }
1041
1042 let type_arguments = decl
1043 .type_parameters
1044 .iter()
1045 .map(|arg| {
1046 Ok(program_abi::TypeApplication {
1047 name: "".to_string(),
1048 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1049 arg.type_id.index(),
1050 )),
1051 type_arguments: arg.type_id.get_abi_type_arguments(
1052 handler,
1053 ctx,
1054 engines,
1055 metadata_types,
1056 concrete_types,
1057 arg.type_id,
1058 &mut new_metadata_types_to_add,
1059 )?,
1060 })
1061 })
1062 .collect::<Result<Vec<_>, _>>()?;
1063
1064 if type_arguments.is_empty() {
1065 None
1066 } else {
1067 metadata_types_to_add.extend(new_metadata_types_to_add);
1068 Some(type_arguments)
1069 }
1070 }
1071 _ => None,
1072 })
1073 }
1074
1075 pub(self) fn get_abi_type_arguments_as_concrete_type_ids(
1080 &self,
1081 handler: &Handler,
1082 ctx: &mut AbiContext,
1083 engines: &Engines,
1084 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
1085 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
1086 resolved_type_id: TypeId,
1087 ) -> Result<Option<Vec<program_abi::ConcreteTypeId>>, ErrorEmitted> {
1088 let type_engine = engines.te();
1089 let decl_engine = engines.de();
1090 let resolved_params = resolved_type_id.get_type_parameters(engines);
1091 Ok(match &*type_engine.get(*self) {
1092 TypeInfo::Custom {
1093 type_arguments: Some(type_arguments),
1094 ..
1095 } => (!type_arguments.is_empty()).then_some({
1096 let resolved_params = resolved_params.unwrap_or_default();
1097 type_arguments
1098 .iter()
1099 .zip(resolved_params.iter())
1100 .map(|(arg, p)| {
1101 generate_concrete_type_declaration(
1102 handler,
1103 ctx,
1104 engines,
1105 metadata_types,
1106 concrete_types,
1107 arg.initial_type_id,
1108 p.type_id,
1109 )
1110 })
1111 .collect::<Result<Vec<_>, _>>()?
1112 }),
1113 TypeInfo::Enum(decl_ref) => {
1114 let decl = decl_engine.get_enum(decl_ref);
1115 Some(
1116 decl.type_parameters
1117 .iter()
1118 .map(|arg| {
1119 generate_concrete_type_declaration(
1120 handler,
1121 ctx,
1122 engines,
1123 metadata_types,
1124 concrete_types,
1125 arg.type_id,
1126 arg.type_id,
1127 )
1128 })
1129 .collect::<Result<Vec<_>, _>>()?,
1130 )
1131 }
1132 TypeInfo::Struct(decl_ref) => {
1133 let decl = decl_engine.get_struct(decl_ref);
1134 Some(
1135 decl.type_parameters
1136 .iter()
1137 .map(|arg| {
1138 generate_concrete_type_declaration(
1139 handler,
1140 ctx,
1141 engines,
1142 metadata_types,
1143 concrete_types,
1144 arg.type_id,
1145 arg.type_id,
1146 )
1147 })
1148 .collect::<Result<Vec<_>, _>>()?,
1149 )
1150 }
1151 _ => None,
1152 })
1153 }
1154}
1155
1156impl TyFunctionDecl {
1157 pub(self) fn generate_abi_function(
1158 &self,
1159 handler: &Handler,
1160 ctx: &mut AbiContext,
1161 engines: &Engines,
1162 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
1163 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
1164 ) -> Result<program_abi::ABIFunction, ErrorEmitted> {
1165 Ok(program_abi::ABIFunction {
1167 name: self.name.as_str().to_string(),
1168 inputs: self
1169 .parameters
1170 .iter()
1171 .map(|x| {
1172 Ok(program_abi::TypeConcreteParameter {
1173 name: x.name.to_string(),
1174 concrete_type_id: generate_concrete_type_declaration(
1175 handler,
1176 ctx,
1177 engines,
1178 metadata_types,
1179 concrete_types,
1180 x.type_argument.initial_type_id,
1181 x.type_argument.type_id,
1182 )?,
1183 })
1184 })
1185 .collect::<Result<Vec<_>, _>>()?,
1186 output: generate_concrete_type_declaration(
1187 handler,
1188 ctx,
1189 engines,
1190 metadata_types,
1191 concrete_types,
1192 self.return_type.initial_type_id,
1193 self.return_type.type_id,
1194 )?,
1195 attributes: generate_attributes_map(&self.attributes),
1196 })
1197 }
1198}
1199
1200fn generate_attributes_map(attr_map: &AttributesMap) -> Option<Vec<program_abi::Attribute>> {
1201 if attr_map.is_empty() {
1202 None
1203 } else {
1204 Some(
1205 attr_map
1206 .iter()
1207 .flat_map(|(_attr_kind, attrs)| {
1208 attrs.iter().map(|attr| program_abi::Attribute {
1209 name: attr.name.to_string(),
1210 arguments: attr.args.iter().map(|arg| arg.name.to_string()).collect(),
1211 })
1212 })
1213 .collect(),
1214 )
1215 }
1216}
1217
1218impl TypeParameter {
1219 pub(self) fn get_abi_type_parameter(
1222 &self,
1223 handler: &Handler,
1224 ctx: &mut AbiContext,
1225 engines: &Engines,
1226 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
1227 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
1228 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
1229 ) -> Result<MetadataTypeId, ErrorEmitted> {
1230 let type_id = MetadataTypeId(self.initial_type_id.index());
1231 let type_parameter = program_abi::TypeMetadataDeclaration {
1232 metadata_type_id: type_id.clone(),
1233 type_field: self.initial_type_id.get_abi_type_str(
1234 &ctx.to_str_context(),
1235 engines,
1236 self.type_id,
1237 ),
1238 components: self.initial_type_id.get_abi_type_components(
1239 handler,
1240 ctx,
1241 engines,
1242 metadata_types,
1243 concrete_types,
1244 self.type_id,
1245 metadata_types_to_add,
1246 )?,
1247 type_parameters: None,
1248 };
1249 metadata_types_to_add.push(type_parameter);
1250 Ok(type_id)
1251 }
1252}