diff --git a/sway-core/src/abi_generation/abi_str.rs b/sway-core/src/abi_generation/abi_str.rs index f7d0e9934ea..9cb23860008 100644 --- a/sway-core/src/abi_generation/abi_str.rs +++ b/sway-core/src/abi_generation/abi_str.rs @@ -2,10 +2,12 @@ use sway_types::integer_bits::IntegerBits; use crate::{language::CallPath, Engines, TypeArgument, TypeId, TypeInfo}; +#[derive(Clone)] pub struct AbiStrContext { pub program_name: Option, pub abi_with_callpaths: bool, pub abi_with_fully_specified_types: bool, + pub abi_root_type_without_generic_type_parameters: bool, } impl TypeId { @@ -18,28 +20,31 @@ impl TypeId { ) -> String { let type_engine = engines.te(); if self.is_generic_parameter(engines, resolved_type_id) { - format!("generic {}", type_engine.get(*self).abi_str(ctx, engines)) + format!( + "generic {}", + type_engine.get(*self).abi_str(ctx, engines, true) + ) } else { match ( &*type_engine.get(*self), &*type_engine.get(resolved_type_id), ) { - (TypeInfo::Custom { .. }, TypeInfo::Struct { .. }) => { - type_engine.get(resolved_type_id).abi_str(ctx, engines) - } - (TypeInfo::Custom { .. }, TypeInfo::Enum { .. }) => { - type_engine.get(resolved_type_id).abi_str(ctx, engines) - } - (TypeInfo::Custom { .. }, TypeInfo::Alias { .. }) => { - type_engine.get(resolved_type_id).abi_str(ctx, engines) - } + (TypeInfo::Custom { .. }, TypeInfo::Struct { .. }) => type_engine + .get(resolved_type_id) + .abi_str(ctx, engines, true), + (TypeInfo::Custom { .. }, TypeInfo::Enum { .. }) => type_engine + .get(resolved_type_id) + .abi_str(ctx, engines, true), + (TypeInfo::Custom { .. }, TypeInfo::Alias { .. }) => type_engine + .get(resolved_type_id) + .abi_str(ctx, engines, true), (TypeInfo::Tuple(fields), TypeInfo::Tuple(resolved_fields)) => { assert_eq!(fields.len(), resolved_fields.len()); let field_strs = resolved_fields .iter() .map(|f| { if ctx.abi_with_fully_specified_types { - type_engine.get(f.type_id).abi_str(ctx, engines) + type_engine.get(f.type_id).abi_str(ctx, engines, false) } else { "_".to_string() } @@ -50,23 +55,30 @@ impl TypeId { (TypeInfo::Array(_, count), TypeInfo::Array(type_arg, resolved_count)) => { assert_eq!(count.val(), resolved_count.val()); let inner_type = if ctx.abi_with_fully_specified_types { - type_engine.get(type_arg.type_id).abi_str(ctx, engines) + type_engine + .get(type_arg.type_id) + .abi_str(ctx, engines, false) } else { "_".to_string() }; format!("[{}; {}]", inner_type, count.val()) } (TypeInfo::Custom { .. }, _) => { - format!("generic {}", type_engine.get(*self).abi_str(ctx, engines)) + format!( + "generic {}", + type_engine.get(*self).abi_str(ctx, engines, true) + ) } - _ => type_engine.get(resolved_type_id).abi_str(ctx, engines), + _ => type_engine + .get(resolved_type_id) + .abi_str(ctx, engines, true), } } } } impl TypeInfo { - pub fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines) -> String { + pub fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines, is_root: bool) -> String { use TypeInfo::*; let decl_engine = engines.de(); let type_engine = engines.te(); @@ -94,7 +106,7 @@ impl TypeInfo { Tuple(fields) => { let field_strs = fields .iter() - .map(|field| field.abi_str(ctx, engines)) + .map(|field| field.abi_str(ctx, engines, false)) .collect::>(); format!("({})", field_strs.join(", ")) } @@ -104,19 +116,20 @@ impl TypeInfo { ErrorRecovery(_) => "unknown due to error".into(), Enum(decl_ref) => { let decl = decl_engine.get_enum(decl_ref); - let type_params = - if !ctx.abi_with_fully_specified_types || decl.type_parameters.is_empty() { - "".into() - } else { - format!( - "<{}>", - decl.type_parameters - .iter() - .map(|p| type_engine.get(p.type_id).abi_str(ctx, engines)) - .collect::>() - .join(",") - ) - }; + let type_params = if (ctx.abi_root_type_without_generic_type_parameters && is_root) + || decl.type_parameters.is_empty() + { + "".into() + } else { + format!( + "<{}>", + decl.type_parameters + .iter() + .map(|p| type_engine.get(p.type_id).abi_str(ctx, engines, false)) + .collect::>() + .join(",") + ) + }; format!( "enum {}{}", call_path_display(ctx, &decl.call_path), @@ -125,19 +138,20 @@ impl TypeInfo { } Struct(decl_ref) => { let decl = decl_engine.get_struct(decl_ref); - let type_params = - if !ctx.abi_with_fully_specified_types || decl.type_parameters.is_empty() { - "".into() - } else { - format!( - "<{}>", - decl.type_parameters - .iter() - .map(|p| type_engine.get(p.type_id).abi_str(ctx, engines)) - .collect::>() - .join(",") - ) - }; + let type_params = if (ctx.abi_root_type_without_generic_type_parameters && is_root) + || decl.type_parameters.is_empty() + { + "".into() + } else { + format!( + "<{}>", + decl.type_parameters + .iter() + .map(|p| type_engine.get(p.type_id).abi_str(ctx, engines, false)) + .collect::>() + .join(",") + ) + }; format!( "struct {}{}", call_path_display(ctx, &decl.call_path), @@ -148,18 +162,22 @@ impl TypeInfo { format!("contract caller {abi_name}") } Array(elem_ty, length) => { - format!("[{}; {}]", elem_ty.abi_str(ctx, engines), length.val()) + format!( + "[{}; {}]", + elem_ty.abi_str(ctx, engines, false), + length.val() + ) } Storage { .. } => "contract storage".into(), RawUntypedPtr => "raw untyped ptr".into(), RawUntypedSlice => "raw untyped slice".into(), Ptr(ty) => { - format!("__ptr {}", ty.abi_str(ctx, engines)) + format!("__ptr {}", ty.abi_str(ctx, engines, false)) } Slice(ty) => { - format!("__slice {}", ty.abi_str(ctx, engines)) + format!("__slice {}", ty.abi_str(ctx, engines, false)) } - Alias { ty, .. } => ty.abi_str(ctx, engines), + Alias { ty, .. } => ty.abi_str(ctx, engines, false), TraitType { name, trait_type_id: _, @@ -171,7 +189,7 @@ impl TypeInfo { format!( "__ref {}{}", // TODO-IG: No references in ABIs according to the RFC. Or we want to have them? if *to_mutable_value { "mut " } else { "" }, - referenced_type.abi_str(ctx, engines) + referenced_type.abi_str(ctx, engines, false) ) } } @@ -205,7 +223,10 @@ fn call_path_display(ctx: &AbiStrContext, call_path: &CallPath) -> String { } impl TypeArgument { - pub(self) fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines) -> String { - engines.te().get(self.type_id).abi_str(ctx, engines) + pub(self) fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines, is_root: bool) -> String { + engines + .te() + .get(self.type_id) + .abi_str(ctx, engines, is_root) } } diff --git a/sway-core/src/abi_generation/fuel_abi.rs b/sway-core/src/abi_generation/fuel_abi.rs index d9e5970aaf9..d5fcdd71096 100644 --- a/sway-core/src/abi_generation/fuel_abi.rs +++ b/sway-core/src/abi_generation/fuel_abi.rs @@ -19,11 +19,7 @@ pub struct AbiContext<'a> { } impl<'a> AbiContext<'a> { - fn to_str_context( - &self, - engines: &Engines, - abi_with_fully_specified_types: bool, - ) -> AbiStrContext { + fn to_str_context(&self, engines: &Engines, abi_full: bool) -> AbiStrContext { AbiStrContext { program_name: self .program @@ -32,7 +28,8 @@ impl<'a> AbiContext<'a> { .program_id(engines) .read(engines, |m| m.name.clone().map(|v| v.as_str().to_string())), abi_with_callpaths: self.abi_with_callpaths, - abi_with_fully_specified_types, + abi_with_fully_specified_types: abi_full, + abi_root_type_without_generic_type_parameters: !abi_full, } } } @@ -55,6 +52,7 @@ impl TypeId { .read(engines, |m| m.name.clone().map(|v| v.as_str().to_string())), abi_with_callpaths: true, abi_with_fully_specified_types: true, + abi_root_type_without_generic_type_parameters: true, }, engines, resolved_type_id, diff --git a/sway-core/src/language/ty/expression/intrinsic_function.rs b/sway-core/src/language/ty/expression/intrinsic_function.rs index a82ec310f9f..d71ff013031 100644 --- a/sway-core/src/language/ty/expression/intrinsic_function.rs +++ b/sway-core/src/language/ty/expression/intrinsic_function.rs @@ -121,6 +121,7 @@ impl CollectTypesMetadata for TyIntrinsicFunctionKind { program_name: Some(ctx.program_name.clone()), abi_with_callpaths: true, abi_with_fully_specified_types: true, + abi_root_type_without_generic_type_parameters: false, }, ctx.engines, logged_type,