1use fuel_abi_types::abi::program::{
2 self as program_abi, ConcreteTypeId, ErrorDetails, ErrorPosition, MetadataTypeId,
3 PanickingCall, TypeConcreteDeclaration,
4};
5use sha2::{Digest, Sha256};
6use std::collections::{BTreeMap, HashMap, HashSet};
7use sway_error::{
8 error::CompileError,
9 handler::{ErrorEmitted, Handler},
10};
11use sway_parse::is_valid_identifier_or_path;
12use sway_types::{BaseIdent, Named, Span, Spanned};
13
14use crate::{
15 ast_elements::type_parameter::GenericTypeParameter,
16 language::ty::{TyFunctionDecl, TyProgram, TyProgramKind},
17 transform::Attributes,
18 AbiEncodeSizeHint, Engines, PanicOccurrences, PanickingCallOccurrences, TypeId, TypeInfo,
19};
20
21use super::abi_str::AbiStrContext;
22
23#[derive(Clone, Debug)]
24pub enum AbiNameDiagnosticSpan {
25 Attribute(Span),
26 Type(Span),
27}
28
29impl AbiNameDiagnosticSpan {
30 pub fn span(self) -> Span {
31 match self {
32 Self::Attribute(span) | Self::Type(span) => span,
33 }
34 }
35}
36
37pub struct AbiContext<'a> {
38 pub program: &'a TyProgram,
39 pub panic_occurrences: &'a PanicOccurrences,
40 pub panicking_call_occurrences: &'a PanickingCallOccurrences,
41 pub abi_with_callpaths: bool,
42 pub type_ids_to_full_type_str: HashMap<String, String>,
43 pub unique_names: HashMap<String, AbiNameDiagnosticSpan>,
44}
45
46impl AbiContext<'_> {
47 fn to_str_context(&self) -> AbiStrContext {
48 AbiStrContext {
49 program_name: self.program.namespace.current_package_name().to_string(),
50 abi_with_callpaths: self.abi_with_callpaths,
51 abi_with_fully_specified_types: false,
52 abi_root_type_without_generic_type_parameters: true,
53 }
54 }
55}
56
57pub fn extract_abi_name_inner(span: &Span) -> Option<Span> {
58 let text = &span.src().text;
59 let full_attr = span.as_str();
60
61 let name_key_pos = full_attr.find("name")?;
63 let after_name = &full_attr[name_key_pos..];
64
65 let eq_offset_rel = after_name.find('=')?;
67 let after_eq = &after_name[eq_offset_rel + 1..];
68
69 let first_quote_rel = after_eq.find('"')?;
71 let ident_abs_start = span.start()
72 + name_key_pos
73 + eq_offset_rel
74 + 1 + first_quote_rel
76 + 1; let rest_after_ident = &text[ident_abs_start..span.end()];
80 let second_quote_rel = rest_after_ident.find('"')?;
81 let ident_abs_end = ident_abs_start + second_quote_rel;
82
83 Span::new(
84 span.src().clone(),
85 ident_abs_start - 1,
86 ident_abs_end + 1,
87 span.source_id().cloned(),
88 )
89}
90
91impl TypeId {
92 fn get_abi_name_and_span_from_type_id(
93 engines: &Engines,
94 type_id: TypeId,
95 ) -> Result<Option<(String, Span)>, ErrorEmitted> {
96 let handler = Handler::default();
97 match *engines.te().get(type_id) {
98 TypeInfo::Enum(decl_id) => {
99 let enum_decl = engines.de().get_enum(&decl_id);
100 match enum_decl.attributes.abi_name() {
101 Some(abi_name_attr) => {
102 let name = abi_name_attr
103 .args
104 .first()
105 .unwrap()
106 .get_string(&handler, abi_name_attr)?;
107 Ok(Some((name.clone(), abi_name_attr.span.clone())))
108 }
109 None => Ok(None),
110 }
111 }
112 TypeInfo::Struct(decl_id) => {
113 let struct_decl = engines.de().get_struct(&decl_id);
114 match struct_decl.attributes.abi_name() {
115 Some(abi_name_attr) => {
116 let name = abi_name_attr
117 .args
118 .first()
119 .unwrap()
120 .get_string(&handler, abi_name_attr)?;
121 Ok(Some((name.clone(), abi_name_attr.span.clone())))
122 }
123 None => Ok(None),
124 }
125 }
126 _ => Ok(None),
127 }
128 }
129
130 fn get_abi_type_field_and_concrete_id(
131 &self,
132 handler: &Handler,
133 ctx: &mut AbiContext,
134 engines: &Engines,
135 resolved_type_id: TypeId,
136 ) -> Result<(String, ConcreteTypeId), ErrorEmitted> {
137 let type_str = self.get_abi_type_str(
138 handler,
139 &AbiStrContext {
140 program_name: ctx.program.namespace.current_package_name().to_string(),
141 abi_with_callpaths: true,
142 abi_with_fully_specified_types: true,
143 abi_root_type_without_generic_type_parameters: false,
144 },
145 engines,
146 resolved_type_id,
147 )?;
148
149 let mut err: Option<ErrorEmitted> = None;
150
151 let should_check_name = matches!(
153 *engines.te().get(resolved_type_id),
154 TypeInfo::Enum(_) | TypeInfo::Struct(_)
155 );
156
157 if should_check_name {
158 let (has_abi_name_attribute, name, attribute_span) =
159 match Self::get_abi_name_and_span_from_type_id(engines, resolved_type_id)? {
160 Some(res) => (true, res.0, res.1),
161 None => (false, String::new(), Span::dummy()),
162 };
163
164 let attribute_name_span =
165 extract_abi_name_inner(&attribute_span).unwrap_or(attribute_span.clone());
166
167 let type_span = match *engines.te().get(resolved_type_id) {
168 TypeInfo::Enum(decl_id) => engines.de().get_enum(&decl_id).name().span(),
169 TypeInfo::Struct(decl_id) => engines.de().get_struct(&decl_id).name().span(),
170 _ => unreachable!(),
171 };
172
173 let insert_span = if has_abi_name_attribute {
174 AbiNameDiagnosticSpan::Attribute(attribute_span.clone())
175 } else {
176 AbiNameDiagnosticSpan::Type(type_span.clone())
177 };
178
179 let prev_span_opt = if ctx.unique_names.contains_key(&type_str) {
180 ctx.unique_names.get(&type_str).cloned()
181 } else {
182 ctx.unique_names.insert(type_str.clone(), insert_span)
183 };
184
185 if has_abi_name_attribute {
186 if name.is_empty()
187 || !is_valid_identifier_or_path(name.as_str())
188 || name.starts_with("::")
189 {
190 err = Some(handler.emit_err(CompileError::ABIInvalidName {
191 span: attribute_name_span.clone(),
192 name,
193 }));
194 }
195
196 if let Some(prev_span) = prev_span_opt {
197 let is_attribute = matches!(prev_span, AbiNameDiagnosticSpan::Attribute(_));
198 err = Some(handler.emit_err(CompileError::ABIDuplicateName {
199 span: attribute_name_span.clone(),
200 other_span: prev_span.span(),
201 is_attribute,
202 }));
203 }
204 }
205 }
206
207 let mut hasher = Sha256::new();
208 hasher.update(type_str.clone());
209 let result = hasher.finalize();
210 let type_id = format!("{result:x}");
211
212 if let Some(old_type_str) = ctx
213 .type_ids_to_full_type_str
214 .insert(type_id.clone(), type_str.clone())
215 {
216 if old_type_str != type_str {
217 err = Some(
218 handler.emit_err(sway_error::error::CompileError::ABIHashCollision {
219 span: Span::dummy(),
220 hash: type_id.clone(),
221 first_type: old_type_str,
222 second_type: type_str.clone(),
223 }),
224 );
225 }
226 }
227
228 match err {
229 Some(err) => Err(err),
230 None => Ok((type_str, ConcreteTypeId(type_id))),
231 }
232 }
233}
234
235fn insert_unique_type(ctx: &mut AbiContext, name: String, span: Span) {
236 let _ = ctx
237 .unique_names
238 .insert(name, AbiNameDiagnosticSpan::Type(span));
239}
240
241fn process_type_name(ctx: &mut AbiContext, engines: &Engines, type_id: TypeId) {
242 match &*engines.te().get(type_id) {
243 TypeInfo::Enum(decl_id) => {
244 let enum_decl = engines.de().get_enum(decl_id);
245 insert_unique_type(
246 ctx,
247 format!("enum {}", enum_decl.name()),
248 enum_decl.name().span(),
249 );
250 }
251 TypeInfo::Struct(decl_id) => {
252 let struct_decl = engines.de().get_struct(decl_id);
253 insert_unique_type(
254 ctx,
255 format!("struct {}", struct_decl.name()),
256 struct_decl.name().span(),
257 );
258 }
259 TypeInfo::Alias { name: _, ty } => process_type_name(ctx, engines, ty.type_id),
260 _ => {}
261 }
262}
263
264fn process_type_names_from_function(
265 ctx: &mut AbiContext,
266 engines: &Engines,
267 function: &TyFunctionDecl,
268) {
269 process_type_name(ctx, engines, function.return_type.type_id);
270
271 for param in &function.parameters {
272 process_type_name(ctx, engines, param.type_argument.type_id);
273 }
274}
275
276pub fn generate_program_abi(
277 handler: &Handler,
278 ctx: &mut AbiContext,
279 engines: &Engines,
280 encoding_version: program_abi::Version,
281 spec_version: program_abi::Version,
282) -> Result<program_abi::ProgramABI, ErrorEmitted> {
283 let decl_engine = engines.de();
284 let metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration> = &mut vec![];
285 let concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration> = &mut vec![];
286
287 match &ctx.program.kind {
288 TyProgramKind::Contract { abi_entries, .. } => {
289 abi_entries.iter().for_each(|x| {
290 let fn_decl = decl_engine.get_function(x);
291 process_type_names_from_function(ctx, engines, &fn_decl);
292 });
293 }
294 TyProgramKind::Script { main_function, .. } => {
295 let main_function = decl_engine.get_function(main_function);
296 process_type_names_from_function(ctx, engines, &main_function);
297 }
298 TyProgramKind::Predicate { main_function, .. } => {
299 let main_function = decl_engine.get_function(main_function);
300 process_type_names_from_function(ctx, engines, &main_function);
301 }
302 TyProgramKind::Library { .. } => {}
303 };
304
305 let mut program_abi = handler.scope(|handler| match &ctx.program.kind {
306 TyProgramKind::Contract { abi_entries, .. } => {
307 let functions = abi_entries
308 .iter()
309 .map(|x| {
310 let fn_decl = decl_engine.get_function(x);
311 fn_decl.generate_abi_function(
312 handler,
313 ctx,
314 engines,
315 metadata_types,
316 concrete_types,
317 )
318 })
319 .collect::<Vec<_>>();
320 let logged_types =
321 generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?;
322 let messages_types =
323 generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?;
324 let configurables =
325 generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?;
326 let error_codes = generate_error_codes(ctx.panic_occurrences);
327 let panicking_calls = generate_panicking_calls(ctx.panicking_call_occurrences);
328 Ok(program_abi::ProgramABI {
329 program_type: "contract".to_string(),
330 spec_version,
331 encoding_version,
332 metadata_types: metadata_types.to_vec(),
333 concrete_types: concrete_types.to_vec(),
334 functions: functions.into_iter().collect::<Result<Vec<_>, _>>()?,
335 logged_types: Some(logged_types),
336 messages_types: Some(messages_types),
337 configurables: Some(configurables),
338 error_codes: Some(error_codes),
339 panicking_calls: Some(panicking_calls),
340 })
341 }
342 TyProgramKind::Script { main_function, .. } => {
343 let main_function = decl_engine.get_function(main_function);
344 let functions = vec![main_function.generate_abi_function(
345 handler,
346 ctx,
347 engines,
348 metadata_types,
349 concrete_types,
350 )?];
351 let logged_types =
352 generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?;
353 let messages_types =
354 generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?;
355 let configurables =
356 generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?;
357 let error_codes = generate_error_codes(ctx.panic_occurrences);
358 let panicking_calls = generate_panicking_calls(ctx.panicking_call_occurrences);
359 Ok(program_abi::ProgramABI {
360 program_type: "script".to_string(),
361 spec_version,
362 encoding_version,
363 metadata_types: metadata_types.to_vec(),
364 concrete_types: concrete_types.to_vec(),
365 functions,
366 logged_types: Some(logged_types),
367 messages_types: Some(messages_types),
368 configurables: Some(configurables),
369 error_codes: Some(error_codes),
370 panicking_calls: Some(panicking_calls),
371 })
372 }
373 TyProgramKind::Predicate { main_function, .. } => {
374 let main_function = decl_engine.get_function(main_function);
375 let functions = vec![main_function.generate_abi_function(
376 handler,
377 ctx,
378 engines,
379 metadata_types,
380 concrete_types,
381 )?];
382 let logged_types =
383 generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?;
384 let messages_types =
385 generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?;
386 let configurables =
387 generate_configurables(handler, ctx, engines, metadata_types, concrete_types)?;
388 let error_codes = generate_error_codes(ctx.panic_occurrences);
389 let panicking_calls = generate_panicking_calls(ctx.panicking_call_occurrences);
390 Ok(program_abi::ProgramABI {
391 program_type: "predicate".to_string(),
392 spec_version,
393 encoding_version,
394 metadata_types: metadata_types.to_vec(),
395 concrete_types: concrete_types.to_vec(),
396 functions,
397 logged_types: Some(logged_types),
398 messages_types: Some(messages_types),
399 configurables: Some(configurables),
400 error_codes: Some(error_codes),
401 panicking_calls: Some(panicking_calls),
402 })
403 }
404 TyProgramKind::Library { .. } => {
405 let logged_types =
406 generate_logged_types(handler, ctx, engines, metadata_types, concrete_types)?;
407 let messages_types =
408 generate_messages_types(handler, ctx, engines, metadata_types, concrete_types)?;
409 let error_codes = generate_error_codes(ctx.panic_occurrences);
410 let panicking_calls = generate_panicking_calls(ctx.panicking_call_occurrences);
411 Ok(program_abi::ProgramABI {
412 program_type: "library".to_string(),
413 spec_version,
414 encoding_version,
415 metadata_types: metadata_types.to_vec(),
416 concrete_types: concrete_types.to_vec(),
417 functions: vec![],
418 logged_types: Some(logged_types),
419 messages_types: Some(messages_types),
420 configurables: None,
421 error_codes: Some(error_codes),
422 panicking_calls: Some(panicking_calls),
423 })
424 }
425 })?;
426
427 standardize_json_abi_types(&mut program_abi);
428
429 Ok(program_abi)
430}
431
432fn standardize_json_abi_types(json_abi_program: &mut program_abi::ProgramABI) {
435 loop {
437 let mut old_to_new_id: HashMap<MetadataTypeId, program_abi::TypeId> = HashMap::new();
440
441 let mut deduped_types: Vec<program_abi::TypeMetadataDeclaration> = Vec::new();
447
448 for decl in &json_abi_program.metadata_types {
451 if let Some(ty) = json_abi_program.concrete_types.iter().find(|d| {
453 d.type_field == decl.type_field
454 && decl.components.is_none()
455 && decl.type_parameters.is_none()
456 }) {
457 old_to_new_id.insert(
458 decl.metadata_type_id.clone(),
459 program_abi::TypeId::Concrete(ty.concrete_type_id.clone()),
460 );
461 } else {
462 if let Some(ty) = deduped_types.iter().find(|d| {
464 d.type_field == decl.type_field
465 && d.components == decl.components
466 && d.type_parameters == decl.type_parameters
467 }) {
468 old_to_new_id.insert(
469 decl.metadata_type_id.clone(),
470 program_abi::TypeId::Metadata(ty.metadata_type_id.clone()),
471 );
472 } else {
473 deduped_types.push(decl.clone());
474 }
475 }
476 }
477
478 if old_to_new_id.is_empty() {
481 break;
482 }
483
484 json_abi_program.metadata_types = deduped_types;
485
486 update_all_types(json_abi_program, &old_to_new_id);
487 }
488
489 let mut concrete_declarations_map: HashMap<ConcreteTypeId, TypeConcreteDeclaration> =
491 HashMap::new();
492 for decl in &json_abi_program.concrete_types {
493 concrete_declarations_map.insert(decl.concrete_type_id.clone(), decl.clone());
494 }
495 json_abi_program.concrete_types = concrete_declarations_map.values().cloned().collect();
496
497 json_abi_program
499 .metadata_types
500 .sort_by(|t1, t2| t1.type_field.cmp(&t2.type_field));
501
502 json_abi_program
504 .concrete_types
505 .sort_by(|t1, t2| t1.type_field.cmp(&t2.type_field));
506
507 let mut old_to_new_id: HashMap<MetadataTypeId, program_abi::TypeId> = HashMap::new();
509 for (ix, decl) in json_abi_program.metadata_types.iter_mut().enumerate() {
510 old_to_new_id.insert(
511 decl.metadata_type_id.clone(),
512 program_abi::TypeId::Metadata(MetadataTypeId(ix)),
513 );
514 decl.metadata_type_id = MetadataTypeId(ix);
515 }
516
517 update_all_types(json_abi_program, &old_to_new_id);
518}
519
520fn update_all_types(
522 json_abi_program: &mut program_abi::ProgramABI,
523 old_to_new_id: &HashMap<MetadataTypeId, program_abi::TypeId>,
524) {
525 for decl in &mut json_abi_program.metadata_types {
527 update_json_type_metadata_declaration(decl, old_to_new_id);
528 }
529
530 for decl in &mut json_abi_program.concrete_types {
532 update_json_type_concrete_declaration(decl, old_to_new_id);
533 }
534}
535
536fn update_json_type_application(
539 type_application: &mut program_abi::TypeApplication,
540 old_to_new_id: &HashMap<MetadataTypeId, program_abi::TypeId>,
541) {
542 if let fuel_abi_types::abi::program::TypeId::Metadata(metadata_type_id) =
543 &type_application.type_id
544 {
545 if let Some(new_id) = old_to_new_id.get(metadata_type_id) {
546 type_application.type_id = new_id.clone();
547 }
548 }
549
550 if let Some(args) = &mut type_application.type_arguments {
551 for arg in args.iter_mut() {
552 update_json_type_application(arg, old_to_new_id);
553 }
554 }
555}
556
557fn update_json_type_metadata_declaration(
560 type_declaration: &mut program_abi::TypeMetadataDeclaration,
561 old_to_new_id: &HashMap<MetadataTypeId, program_abi::TypeId>,
562) {
563 if let Some(params) = &mut type_declaration.type_parameters {
564 for param in params.iter_mut() {
565 if let Some(fuel_abi_types::abi::program::TypeId::Metadata(new_id)) =
566 old_to_new_id.get(param)
567 {
568 *param = new_id.clone();
569 }
570 }
571 }
572
573 if let Some(components) = &mut type_declaration.components {
574 for component in components.iter_mut() {
575 update_json_type_application(component, old_to_new_id);
576 }
577 }
578}
579
580fn update_json_type_concrete_declaration(
583 type_declaration: &mut program_abi::TypeConcreteDeclaration,
584 old_to_new_id: &HashMap<MetadataTypeId, program_abi::TypeId>,
585) {
586 if let Some(metadata_type_id) = &mut type_declaration.metadata_type_id {
587 if let Some(fuel_abi_types::abi::program::TypeId::Metadata(new_id)) =
588 old_to_new_id.get(metadata_type_id)
589 {
590 *metadata_type_id = new_id.clone();
591 }
592 }
593}
594
595fn generate_concrete_type_declaration(
596 handler: &Handler,
597 ctx: &mut AbiContext,
598 engines: &Engines,
599 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
600 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
601 type_id: TypeId,
602 resolved_type_id: TypeId,
603) -> Result<ConcreteTypeId, ErrorEmitted> {
604 let mut new_metadata_types_to_add = Vec::<program_abi::TypeMetadataDeclaration>::new();
605 let type_metadata_decl = program_abi::TypeMetadataDeclaration {
606 metadata_type_id: MetadataTypeId(type_id.index()),
607 type_field: type_id.get_abi_type_str(
608 handler,
609 &ctx.to_str_context(),
610 engines,
611 resolved_type_id,
612 )?,
613 components: type_id.get_abi_type_components(
614 handler,
615 ctx,
616 engines,
617 metadata_types,
618 concrete_types,
619 resolved_type_id,
620 &mut new_metadata_types_to_add,
621 )?,
622 type_parameters: type_id.get_abi_type_parameters(
623 handler,
624 ctx,
625 engines,
626 metadata_types,
627 concrete_types,
628 resolved_type_id,
629 &mut new_metadata_types_to_add,
630 )?,
631 };
632
633 let metadata_type_id = if type_metadata_decl.type_parameters.is_some()
634 || type_metadata_decl.components.is_some()
635 {
636 Some(type_metadata_decl.metadata_type_id.clone())
637 } else {
638 None
639 };
640 let type_arguments = handler.scope(|handler| {
641 let type_arguments = if type_metadata_decl.type_parameters.is_some() {
642 type_id.get_abi_type_arguments_as_concrete_type_ids(
643 handler,
644 ctx,
645 engines,
646 metadata_types,
647 concrete_types,
648 resolved_type_id,
649 )?
650 } else {
651 None
652 };
653 Ok(type_arguments)
654 })?;
655
656 metadata_types.push(type_metadata_decl);
657 metadata_types.extend(new_metadata_types_to_add);
658
659 let (type_field, concrete_type_id) =
660 type_id.get_abi_type_field_and_concrete_id(handler, ctx, engines, resolved_type_id)?;
661 let concrete_type_decl = TypeConcreteDeclaration {
662 type_field,
663 concrete_type_id: concrete_type_id.clone(),
664 metadata_type_id,
665 type_arguments,
666 alias_of: None,
667 };
668
669 concrete_types.push(concrete_type_decl);
670
671 Ok(concrete_type_id)
672}
673
674#[allow(clippy::too_many_arguments)]
675fn generate_type_metadata_declaration(
676 handler: &Handler,
677 ctx: &mut AbiContext,
678 engines: &Engines,
679 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
680 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
681 type_id: TypeId,
682 resolved_type_id: TypeId,
683 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
684) -> Result<(), ErrorEmitted> {
685 let mut new_metadata_types_to_add = Vec::<program_abi::TypeMetadataDeclaration>::new();
686 let components = type_id.get_abi_type_components(
687 handler,
688 ctx,
689 engines,
690 metadata_types,
691 concrete_types,
692 resolved_type_id,
693 &mut new_metadata_types_to_add,
694 )?;
695 let type_parameters = type_id.get_abi_type_parameters(
696 handler,
697 ctx,
698 engines,
699 metadata_types,
700 concrete_types,
701 resolved_type_id,
702 &mut new_metadata_types_to_add,
703 )?;
704 let type_metadata_decl = program_abi::TypeMetadataDeclaration {
705 metadata_type_id: MetadataTypeId(type_id.index()),
706 type_field: type_id.get_abi_type_str(
707 handler,
708 &ctx.to_str_context(),
709 engines,
710 resolved_type_id,
711 )?,
712 components,
713 type_parameters,
714 };
715
716 metadata_types_to_add.push(type_metadata_decl.clone());
717 metadata_types_to_add.extend(new_metadata_types_to_add);
718
719 Ok(())
720}
721
722fn generate_logged_types(
723 handler: &Handler,
724 ctx: &mut AbiContext,
725 engines: &Engines,
726 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
727 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
728) -> Result<Vec<program_abi::LoggedType>, ErrorEmitted> {
729 let mut log_ids: HashSet<u64> = HashSet::default();
731 Ok(ctx
732 .program
733 .logged_types
734 .iter()
735 .map(|(log_id, type_id)| {
736 let log_id = log_id.hash_id;
737 if log_ids.contains(&log_id) {
738 Ok(None)
739 } else {
740 log_ids.insert(log_id);
741 Ok(Some(program_abi::LoggedType {
742 log_id: log_id.to_string(),
743 concrete_type_id: generate_concrete_type_declaration(
744 handler,
745 ctx,
746 engines,
747 metadata_types,
748 concrete_types,
749 *type_id,
750 *type_id,
751 )?,
752 }))
753 }
754 })
755 .collect::<Result<Vec<_>, _>>()?
756 .into_iter()
757 .flatten()
758 .collect())
759}
760
761fn generate_messages_types(
762 handler: &Handler,
763 ctx: &mut AbiContext,
764 engines: &Engines,
765 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
766 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
767) -> Result<Vec<program_abi::MessageType>, ErrorEmitted> {
768 ctx.program
770 .messages_types
771 .iter()
772 .map(|(message_id, type_id)| {
773 Ok(program_abi::MessageType {
774 message_id: (**message_id as u64).to_string(),
775 concrete_type_id: generate_concrete_type_declaration(
776 handler,
777 ctx,
778 engines,
779 metadata_types,
780 concrete_types,
781 *type_id,
782 *type_id,
783 )?,
784 })
785 })
786 .collect::<Result<Vec<_>, _>>()
787}
788
789fn generate_configurables(
790 handler: &Handler,
791 ctx: &mut AbiContext,
792 engines: &Engines,
793 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
794 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
795) -> Result<Vec<program_abi::Configurable>, ErrorEmitted> {
796 ctx.program
798 .configurables
799 .iter()
800 .map(|decl| {
801 Ok(program_abi::Configurable {
802 name: decl.call_path.suffix.to_string(),
803 concrete_type_id: generate_concrete_type_declaration(
804 handler,
805 ctx,
806 engines,
807 metadata_types,
808 concrete_types,
809 decl.type_ascription.type_id,
810 decl.type_ascription.type_id,
811 )?,
812 offset: 0,
813 indirect: false,
814 })
815 })
816 .collect::<Result<Vec<_>, _>>()
817}
818
819fn generate_error_codes(panic_occurrences: &PanicOccurrences) -> BTreeMap<u64, ErrorDetails> {
820 panic_occurrences
821 .iter()
822 .map(|(panic_occurrence, &panic_error_code)| {
823 (
824 panic_error_code,
825 ErrorDetails {
826 pos: ErrorPosition {
827 function: panic_occurrence.function.clone(),
828 pkg: panic_occurrence.loc.pkg.clone(),
829 file: panic_occurrence.loc.file.clone(),
830 line: panic_occurrence.loc.loc.line as u64,
831 column: panic_occurrence.loc.loc.col as u64,
832 },
833 log_id: panic_occurrence
834 .log_id
835 .map(|log_id| log_id.hash_id.to_string()),
836 msg: panic_occurrence.msg.clone(),
837 },
838 )
839 })
840 .collect()
841}
842
843fn generate_panicking_calls(
844 panicking_call_occurrences: &PanickingCallOccurrences,
845) -> BTreeMap<u64, PanickingCall> {
846 panicking_call_occurrences
847 .iter()
848 .map(|(panicking_call_occurrence, panicking_call_id)| {
849 (
850 *panicking_call_id,
851 PanickingCall {
852 pos: ErrorPosition {
853 function: panicking_call_occurrence.caller_function.clone(),
854 pkg: panicking_call_occurrence.loc.pkg.clone(),
855 file: panicking_call_occurrence.loc.file.clone(),
856 line: panicking_call_occurrence.loc.loc.line as u64,
857 column: panicking_call_occurrence.loc.loc.col as u64,
858 },
859 function: panicking_call_occurrence.function.clone(),
860 },
861 )
862 })
863 .collect()
864}
865
866impl TypeId {
867 #[allow(clippy::too_many_arguments)]
873 pub(self) fn get_abi_type_parameters(
874 &self,
875 handler: &Handler,
876 ctx: &mut AbiContext,
877 engines: &Engines,
878 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
879 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
880 resolved_type_id: TypeId,
881 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
882 ) -> Result<Option<Vec<MetadataTypeId>>, ErrorEmitted> {
883 match self.is_generic_parameter(engines, resolved_type_id) {
884 true => Ok(None),
885 false => resolved_type_id
886 .get_type_parameters(engines)
887 .map(|v| {
888 v.iter()
889 .map(|p| {
890 let p = p
891 .as_type_parameter()
892 .expect("only works with type parameters");
893 p.get_abi_type_parameter(
894 handler,
895 ctx,
896 engines,
897 metadata_types,
898 concrete_types,
899 metadata_types_to_add,
900 )
901 })
902 .collect::<Result<Vec<_>, _>>()
903 })
904 .map_or(Ok(None), |v| v.map(Some)),
905 }
906 }
907
908 fn update_indexed_field_offset(
910 handler: &Handler,
911 running_offset: &mut usize,
912 field_name: BaseIdent,
913 field_size: usize,
914 is_indexed: bool,
915 ) -> Result<Option<u16>, ErrorEmitted> {
916 if !is_indexed {
917 return Ok(None);
918 }
919
920 let current_offset = *running_offset;
921 *running_offset = match current_offset.checked_add(field_size) {
922 Some(offset) => offset,
923 None => {
924 return Err(handler.emit_err(CompileError::IndexedFieldOffsetTooLarge {
925 field_name: sway_types::IdentUnique::from(field_name.clone()),
926 }));
927 }
928 };
929
930 if *running_offset > (u16::MAX as usize + 1) {
931 return Err(handler.emit_err(CompileError::IndexedFieldOffsetTooLarge {
932 field_name: sway_types::IdentUnique::from(field_name.clone()),
933 }));
934 }
935
936 if current_offset > u16::MAX as usize {
937 return Err(handler.emit_err(CompileError::IndexedFieldOffsetTooLarge {
938 field_name: sway_types::IdentUnique::from(field_name),
939 }));
940 }
941
942 Ok(Some(current_offset as u16))
943 }
944
945 #[allow(clippy::too_many_arguments)]
950 pub(self) fn get_abi_type_components(
951 &self,
952 handler: &Handler,
953 ctx: &mut AbiContext,
954 engines: &Engines,
955 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
956 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
957 resolved_type_id: TypeId,
958 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
959 ) -> Result<Option<Vec<program_abi::TypeApplication>>, ErrorEmitted> {
960 let type_engine = engines.te();
961 let decl_engine = engines.de();
962 Ok(match &*type_engine.get(*self) {
963 TypeInfo::Enum(decl_ref) => {
964 let decl = decl_engine.get_enum(decl_ref);
965
966 let mut new_metadata_types_to_add =
967 Vec::<program_abi::TypeMetadataDeclaration>::new();
968 for variant in decl.variants.iter() {
969 generate_type_metadata_declaration(
970 handler,
971 ctx,
972 engines,
973 metadata_types,
974 concrete_types,
975 variant.type_argument.initial_type_id,
976 variant.type_argument.type_id,
977 &mut new_metadata_types_to_add,
978 )?;
979 }
980
981 let components = decl
984 .variants
985 .iter()
986 .map(|variant| {
987 Ok(program_abi::TypeApplication {
988 name: variant.name.to_string(),
989 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
990 variant.type_argument.initial_type_id.index(),
991 )),
992 error_message: variant.attributes.error_message().cloned(),
993 type_arguments: variant
994 .type_argument
995 .initial_type_id
996 .get_abi_type_arguments(
997 handler,
998 ctx,
999 engines,
1000 metadata_types,
1001 concrete_types,
1002 variant.type_argument.type_id,
1003 &mut new_metadata_types_to_add,
1004 )?,
1005 offset: None,
1006 })
1007 })
1008 .collect::<Result<Vec<_>, _>>()?;
1009
1010 if components.is_empty() {
1011 None
1012 } else {
1013 metadata_types_to_add.extend(new_metadata_types_to_add);
1014 Some(components)
1015 }
1016 }
1017 TypeInfo::Struct(decl_ref) => {
1018 let decl = decl_engine.get_struct(decl_ref);
1019
1020 let mut new_metadata_types_to_add =
1021 Vec::<program_abi::TypeMetadataDeclaration>::new();
1022 for field in decl.fields.iter() {
1023 generate_type_metadata_declaration(
1024 handler,
1025 ctx,
1026 engines,
1027 metadata_types,
1028 concrete_types,
1029 field.type_argument.initial_type_id,
1030 field.type_argument.type_id,
1031 &mut new_metadata_types_to_add,
1032 )?;
1033 }
1034
1035 let mut running_offset = 0usize;
1038 let components = decl
1039 .fields
1040 .iter()
1041 .map(|field| {
1042 let hint = engines
1043 .te()
1044 .get(field.type_argument.type_id)
1045 .abi_encode_size_hint(engines);
1046 let is_indexed = field.attributes.indexed().is_some();
1047
1048 let field_size = if is_indexed {
1049 match hint {
1050 AbiEncodeSizeHint::Exact(sz) => sz,
1051 _ => unreachable!("expected exact size hint for indexed field"),
1052 }
1053 } else {
1054 0
1055 };
1056
1057 let offset = TypeId::update_indexed_field_offset(
1058 handler,
1059 &mut running_offset,
1060 field.name.clone(),
1061 field_size,
1062 is_indexed,
1063 )?;
1064
1065 Ok(program_abi::TypeApplication {
1066 name: field.name.to_string(),
1067 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1068 field.type_argument.initial_type_id.index(),
1069 )),
1070 error_message: None,
1071 type_arguments: field
1072 .type_argument
1073 .initial_type_id
1074 .get_abi_type_arguments(
1075 handler,
1076 ctx,
1077 engines,
1078 metadata_types,
1079 concrete_types,
1080 field.type_argument.type_id,
1081 &mut new_metadata_types_to_add,
1082 )?,
1083 offset,
1084 })
1085 })
1086 .collect::<Result<Vec<_>, _>>()?;
1087
1088 if components.is_empty() {
1089 None
1090 } else {
1091 metadata_types_to_add.extend(new_metadata_types_to_add);
1092 Some(components)
1093 }
1094 }
1095 TypeInfo::Array(..) => {
1096 if let TypeInfo::Array(elem_ty, _) = &*type_engine.get(resolved_type_id) {
1097 generate_type_metadata_declaration(
1098 handler,
1099 ctx,
1100 engines,
1101 metadata_types,
1102 concrete_types,
1103 elem_ty.initial_type_id,
1104 elem_ty.type_id,
1105 metadata_types_to_add,
1106 )?;
1107
1108 Some(vec![program_abi::TypeApplication {
1111 name: "__array_element".to_string(),
1112 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1113 elem_ty.initial_type_id.index(),
1114 )),
1115 error_message: None,
1116 type_arguments: elem_ty.initial_type_id.get_abi_type_arguments(
1117 handler,
1118 ctx,
1119 engines,
1120 metadata_types,
1121 concrete_types,
1122 elem_ty.type_id,
1123 metadata_types_to_add,
1124 )?,
1125 offset: None,
1126 }])
1127 } else {
1128 unreachable!();
1129 }
1130 }
1131 TypeInfo::Slice(..) => {
1132 if let TypeInfo::Slice(elem_ty) = &*type_engine.get(resolved_type_id) {
1133 generate_type_metadata_declaration(
1134 handler,
1135 ctx,
1136 engines,
1137 metadata_types,
1138 concrete_types,
1139 elem_ty.initial_type_id,
1140 elem_ty.type_id,
1141 metadata_types_to_add,
1142 )?;
1143
1144 Some(vec![program_abi::TypeApplication {
1147 name: "__slice_element".to_string(),
1148 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1149 elem_ty.initial_type_id.index(),
1150 )),
1151 error_message: None,
1152 type_arguments: elem_ty.initial_type_id.get_abi_type_arguments(
1153 handler,
1154 ctx,
1155 engines,
1156 metadata_types,
1157 concrete_types,
1158 elem_ty.type_id,
1159 metadata_types_to_add,
1160 )?,
1161 offset: None,
1162 }])
1163 } else {
1164 unreachable!();
1165 }
1166 }
1167 TypeInfo::Tuple(_) => {
1168 if let TypeInfo::Tuple(fields) = &*type_engine.get(resolved_type_id) {
1169 let mut new_metadata_types_to_add =
1170 Vec::<program_abi::TypeMetadataDeclaration>::new();
1171 for x in fields.iter() {
1172 generate_type_metadata_declaration(
1173 handler,
1174 ctx,
1175 engines,
1176 metadata_types,
1177 concrete_types,
1178 x.initial_type_id,
1179 x.type_id,
1180 &mut new_metadata_types_to_add,
1181 )?;
1182 }
1183
1184 let components = fields
1187 .iter()
1188 .map(|x| {
1189 Ok(program_abi::TypeApplication {
1190 name: "__tuple_element".to_string(),
1191 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1192 x.initial_type_id.index(),
1193 )),
1194 error_message: None,
1195 type_arguments: x.initial_type_id.get_abi_type_arguments(
1196 handler,
1197 ctx,
1198 engines,
1199 metadata_types,
1200 concrete_types,
1201 x.type_id,
1202 metadata_types_to_add,
1203 )?,
1204 offset: None,
1205 })
1206 })
1207 .collect::<Result<Vec<_>, _>>()?;
1208 if components.is_empty() {
1209 None
1210 } else {
1211 metadata_types_to_add.extend(new_metadata_types_to_add);
1212 Some(components)
1213 }
1214 } else {
1215 unreachable!()
1216 }
1217 }
1218 TypeInfo::Custom { type_arguments, .. } => {
1219 if !self.is_generic_parameter(engines, resolved_type_id) {
1220 for (v, p) in type_arguments.clone().unwrap_or_default().iter().zip(
1221 resolved_type_id
1222 .get_type_parameters(engines)
1223 .unwrap_or_default()
1224 .iter(),
1225 ) {
1226 let p = p
1227 .as_type_parameter()
1228 .expect("only works with type parameters");
1229 generate_type_metadata_declaration(
1230 handler,
1231 ctx,
1232 engines,
1233 metadata_types,
1234 concrete_types,
1235 v.initial_type_id(),
1236 p.type_id,
1237 metadata_types_to_add,
1238 )?;
1239 }
1240 resolved_type_id.get_abi_type_components(
1241 handler,
1242 ctx,
1243 engines,
1244 metadata_types,
1245 concrete_types,
1246 resolved_type_id,
1247 metadata_types_to_add,
1248 )?
1249 } else {
1250 None
1251 }
1252 }
1253 TypeInfo::Alias { .. } => {
1254 if let TypeInfo::Alias { ty, .. } = &*type_engine.get(resolved_type_id) {
1255 ty.initial_type_id.get_abi_type_components(
1256 handler,
1257 ctx,
1258 engines,
1259 metadata_types,
1260 concrete_types,
1261 ty.type_id,
1262 metadata_types_to_add,
1263 )?
1264 } else {
1265 None
1266 }
1267 }
1268 TypeInfo::UnknownGeneric { .. } => {
1269 if *self == resolved_type_id {
1271 None
1272 } else {
1273 resolved_type_id.get_abi_type_components(
1274 handler,
1275 ctx,
1276 engines,
1277 metadata_types,
1278 concrete_types,
1279 resolved_type_id,
1280 metadata_types_to_add,
1281 )?
1282 }
1283 }
1284 _ => None,
1285 })
1286 }
1287
1288 #[allow(clippy::too_many_arguments)]
1293 pub(self) fn get_abi_type_arguments(
1294 &self,
1295 handler: &Handler,
1296 ctx: &mut AbiContext,
1297 engines: &Engines,
1298 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
1299 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
1300 resolved_type_id: TypeId,
1301 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
1302 ) -> Result<Option<Vec<program_abi::TypeApplication>>, ErrorEmitted> {
1303 let type_engine = engines.te();
1304 let decl_engine = engines.de();
1305 let resolved_params = resolved_type_id.get_type_parameters(engines);
1306 handler.scope(|handler| {
1307 Ok(match &*type_engine.get(*self) {
1308 TypeInfo::Custom {
1309 type_arguments: Some(type_arguments),
1310 ..
1311 } => (!type_arguments.is_empty()).then_some({
1312 let resolved_params = resolved_params.unwrap_or_default();
1313 for (v, p) in type_arguments.iter().zip(resolved_params.iter()) {
1314 let p = p
1315 .as_type_parameter()
1316 .expect("only works with type parameters");
1317 let _ = generate_type_metadata_declaration(
1318 handler,
1319 ctx,
1320 engines,
1321 metadata_types,
1322 concrete_types,
1323 v.type_id(),
1324 p.type_id,
1325 metadata_types_to_add,
1326 );
1327 }
1328
1329 type_arguments
1330 .iter()
1331 .zip(resolved_params.iter())
1332 .map(|(arg, p)| {
1333 let p = p
1334 .as_type_parameter()
1335 .expect("only works with type parameters");
1336 Ok(program_abi::TypeApplication {
1337 name: "".to_string(),
1338 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1339 arg.initial_type_id().index(),
1340 )),
1341 error_message: None,
1342 type_arguments: arg.initial_type_id().get_abi_type_arguments(
1343 handler,
1344 ctx,
1345 engines,
1346 metadata_types,
1347 concrete_types,
1348 p.type_id,
1349 metadata_types_to_add,
1350 )?,
1351 offset: None,
1352 })
1353 })
1354 .collect::<Result<Vec<_>, _>>()?
1355 }),
1356 TypeInfo::Enum(decl_ref) => {
1357 let decl = decl_engine.get_enum(decl_ref);
1358
1359 let mut new_metadata_types_to_add =
1360 Vec::<program_abi::TypeMetadataDeclaration>::new();
1361 for p in decl.generic_parameters.iter() {
1362 let p = p
1363 .as_type_parameter()
1364 .expect("only works with type parameters");
1365 generate_type_metadata_declaration(
1366 handler,
1367 ctx,
1368 engines,
1369 metadata_types,
1370 concrete_types,
1371 p.type_id,
1372 p.type_id,
1373 &mut new_metadata_types_to_add,
1374 )?;
1375 }
1376
1377 let type_arguments = decl
1378 .generic_parameters
1379 .iter()
1380 .map(|p| {
1381 let p = p
1382 .as_type_parameter()
1383 .expect("only works with type parameters");
1384 Ok(program_abi::TypeApplication {
1385 name: "".to_string(),
1386 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1387 p.type_id.index(),
1388 )),
1389 error_message: None,
1390 type_arguments: p.type_id.get_abi_type_arguments(
1391 handler,
1392 ctx,
1393 engines,
1394 metadata_types,
1395 concrete_types,
1396 p.type_id,
1397 &mut new_metadata_types_to_add,
1398 )?,
1399 offset: None,
1400 })
1401 })
1402 .collect::<Result<Vec<_>, _>>()?;
1403
1404 if type_arguments.is_empty() {
1405 None
1406 } else {
1407 metadata_types_to_add.extend(new_metadata_types_to_add);
1408 Some(type_arguments)
1409 }
1410 }
1411
1412 TypeInfo::Struct(decl_ref) => {
1413 let decl = decl_engine.get_struct(decl_ref);
1414
1415 let mut new_metadata_types_to_add =
1416 Vec::<program_abi::TypeMetadataDeclaration>::new();
1417 for p in decl.generic_parameters.iter() {
1418 let p = p
1419 .as_type_parameter()
1420 .expect("only works with type parameters");
1421 generate_type_metadata_declaration(
1422 handler,
1423 ctx,
1424 engines,
1425 metadata_types,
1426 concrete_types,
1427 p.type_id,
1428 p.type_id,
1429 &mut new_metadata_types_to_add,
1430 )?;
1431 }
1432
1433 let type_arguments = decl
1434 .generic_parameters
1435 .iter()
1436 .map(|p| {
1437 let p = p
1438 .as_type_parameter()
1439 .expect("only works with type parameters");
1440 Ok(program_abi::TypeApplication {
1441 name: "".to_string(),
1442 type_id: program_abi::TypeId::Metadata(MetadataTypeId(
1443 p.type_id.index(),
1444 )),
1445 error_message: None,
1446 type_arguments: p.type_id.get_abi_type_arguments(
1447 handler,
1448 ctx,
1449 engines,
1450 metadata_types,
1451 concrete_types,
1452 p.type_id,
1453 &mut new_metadata_types_to_add,
1454 )?,
1455 offset: None,
1456 })
1457 })
1458 .collect::<Result<Vec<_>, _>>()?;
1459
1460 if type_arguments.is_empty() {
1461 None
1462 } else {
1463 metadata_types_to_add.extend(new_metadata_types_to_add);
1464 Some(type_arguments)
1465 }
1466 }
1467 _ => None,
1468 })
1469 })
1470 }
1471
1472 pub(self) fn get_abi_type_arguments_as_concrete_type_ids(
1477 &self,
1478 handler: &Handler,
1479 ctx: &mut AbiContext,
1480 engines: &Engines,
1481 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
1482 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
1483 resolved_type_id: TypeId,
1484 ) -> Result<Option<Vec<program_abi::ConcreteTypeId>>, ErrorEmitted> {
1485 let type_engine = engines.te();
1486 let decl_engine = engines.de();
1487 let resolved_params = resolved_type_id.get_type_parameters(engines);
1488 Ok(match &*type_engine.get(*self) {
1489 TypeInfo::Custom {
1490 type_arguments: Some(type_arguments),
1491 ..
1492 } => (!type_arguments.is_empty()).then_some({
1493 let resolved_params = resolved_params.unwrap_or_default();
1494 type_arguments
1495 .iter()
1496 .zip(resolved_params.iter())
1497 .map(|(arg, p)| {
1498 let p = p
1499 .as_type_parameter()
1500 .expect("only works with type parameters");
1501 generate_concrete_type_declaration(
1502 handler,
1503 ctx,
1504 engines,
1505 metadata_types,
1506 concrete_types,
1507 arg.initial_type_id(),
1508 p.type_id,
1509 )
1510 })
1511 .collect::<Result<Vec<_>, _>>()?
1512 }),
1513 TypeInfo::Enum(decl_ref) => {
1514 let decl = decl_engine.get_enum(decl_ref);
1515 Some(
1516 decl.generic_parameters
1517 .iter()
1518 .map(|p| {
1519 let p = p
1520 .as_type_parameter()
1521 .expect("only works with type parameters");
1522 generate_concrete_type_declaration(
1523 handler,
1524 ctx,
1525 engines,
1526 metadata_types,
1527 concrete_types,
1528 p.type_id,
1529 p.type_id,
1530 )
1531 })
1532 .collect::<Result<Vec<_>, _>>()?,
1533 )
1534 }
1535 TypeInfo::Struct(decl_ref) => {
1536 let decl = decl_engine.get_struct(decl_ref);
1537 Some(
1538 decl.generic_parameters
1539 .iter()
1540 .map(|p| {
1541 let p = p
1542 .as_type_parameter()
1543 .expect("only works with type parameters");
1544 generate_concrete_type_declaration(
1545 handler,
1546 ctx,
1547 engines,
1548 metadata_types,
1549 concrete_types,
1550 p.type_id,
1551 p.type_id,
1552 )
1553 })
1554 .collect::<Result<Vec<_>, _>>()?,
1555 )
1556 }
1557 _ => None,
1558 })
1559 }
1560}
1561
1562impl TyFunctionDecl {
1563 pub(self) fn generate_abi_function(
1564 &self,
1565 handler: &Handler,
1566 ctx: &mut AbiContext,
1567 engines: &Engines,
1568 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
1569 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
1570 ) -> Result<program_abi::ABIFunction, ErrorEmitted> {
1571 let inputs = handler.scope(|handler| {
1572 self.parameters
1573 .iter()
1574 .map(|param| {
1575 generate_concrete_type_declaration(
1576 handler,
1577 ctx,
1578 engines,
1579 metadata_types,
1580 concrete_types,
1581 param.type_argument.initial_type_id,
1582 param.type_argument.type_id,
1583 )
1584 .map(|concrete_type_id| {
1585 program_abi::TypeConcreteParameter {
1586 name: param.name.to_string(),
1587 concrete_type_id,
1588 }
1589 })
1590 })
1591 .collect::<Result<Vec<_>, ErrorEmitted>>()
1592 })?;
1593
1594 Ok(program_abi::ABIFunction {
1596 name: self.name.as_str().to_string(),
1597 inputs,
1598 output: generate_concrete_type_declaration(
1599 handler,
1600 ctx,
1601 engines,
1602 metadata_types,
1603 concrete_types,
1604 self.return_type.initial_type_id,
1605 self.return_type.type_id,
1606 )?,
1607 attributes: generate_attributes(&self.attributes),
1608 })
1609 }
1610}
1611
1612fn generate_attributes(attributes: &Attributes) -> Option<Vec<program_abi::Attribute>> {
1613 if attributes.is_empty() {
1614 None
1615 } else {
1616 Some(
1617 attributes
1618 .all()
1619 .map(|attr| program_abi::Attribute {
1620 name: attr.name.to_string(),
1621 arguments: attr.args.iter().map(|arg| arg.name.to_string()).collect(),
1622 })
1623 .collect(),
1624 )
1625 }
1626}
1627
1628impl GenericTypeParameter {
1629 pub(self) fn get_abi_type_parameter(
1632 &self,
1633 handler: &Handler,
1634 ctx: &mut AbiContext,
1635 engines: &Engines,
1636 metadata_types: &mut Vec<program_abi::TypeMetadataDeclaration>,
1637 concrete_types: &mut Vec<program_abi::TypeConcreteDeclaration>,
1638 metadata_types_to_add: &mut Vec<program_abi::TypeMetadataDeclaration>,
1639 ) -> Result<MetadataTypeId, ErrorEmitted> {
1640 let type_id = MetadataTypeId(self.initial_type_id.index());
1641 let type_parameter = program_abi::TypeMetadataDeclaration {
1642 metadata_type_id: type_id.clone(),
1643 type_field: self.initial_type_id.get_abi_type_str(
1644 handler,
1645 &ctx.to_str_context(),
1646 engines,
1647 self.type_id,
1648 )?,
1649 components: self.initial_type_id.get_abi_type_components(
1650 handler,
1651 ctx,
1652 engines,
1653 metadata_types,
1654 concrete_types,
1655 self.type_id,
1656 metadata_types_to_add,
1657 )?,
1658 type_parameters: None,
1659 };
1660 metadata_types_to_add.push(type_parameter);
1661 Ok(type_id)
1662 }
1663}