Skip to content

Commit

Permalink
Fixes generic enums and structs type ids.
Browse files Browse the repository at this point in the history
  • Loading branch information
esdrubal committed Jul 15, 2024
1 parent 8308dea commit 05c8052
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 55 deletions.
119 changes: 70 additions & 49 deletions sway-core/src/abi_generation/abi_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
pub abi_with_callpaths: bool,
pub abi_with_fully_specified_types: bool,
pub abi_root_type_without_generic_type_parameters: bool,
}

impl TypeId {
Expand All @@ -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()
}
Expand All @@ -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();
Expand Down Expand Up @@ -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::<Vec<String>>();
format!("({})", field_strs.join(", "))
}
Expand All @@ -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::<Vec<_>>()
.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::<Vec<_>>()
.join(",")
)
};
format!(
"enum {}{}",
call_path_display(ctx, &decl.call_path),
Expand All @@ -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::<Vec<_>>()
.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::<Vec<_>>()
.join(",")
)
};
format!(
"struct {}{}",
call_path_display(ctx, &decl.call_path),
Expand All @@ -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: _,
Expand All @@ -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)
)
}
}
Expand Down Expand Up @@ -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)
}
}
10 changes: 4 additions & 6 deletions sway-core/src/abi_generation/fuel_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
}
}
}
Expand All @@ -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,
Expand Down
1 change: 1 addition & 0 deletions sway-core/src/language/ty/expression/intrinsic_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 05c8052

Please sign in to comment.