Skip to content

Commit e45048c

Browse files
committed
Add #[abi_name(name = "foo") attribute to rename ABI items.
Add `#[abi_name(name = "foo")` attribute to rename enum and struct ABI items. Here is example of how it can be used: ```sway contract; #[abi_name(name = "RenamedMyScript")] struct MyStruct {} #[abi_name(name = "RenamedMyEnum")] enum MyEnum { A: () } abi MyAbi { fn my_struct() -> MyStruct; fn my_enum() -> MyEnum; } impl MyAbi for Contract { fn my_struct() -> MyStruct { MyStruct{} } fn my_enum() -> MyEnum { MyEnum::A } } ``` Closes #5955.
1 parent df50ca8 commit e45048c

File tree

26 files changed

+426
-107
lines changed

26 files changed

+426
-107
lines changed

sway-ast/src/attribute.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ pub const CFG_PROGRAM_TYPE_ARG_NAME: &str = "program_type";
4747
pub const DEPRECATED_ATTRIBUTE_NAME: &str = "deprecated";
4848
pub const DEPRECATED_NOTE_ARG_NAME: &str = "note";
4949

50+
// Abi names.
51+
pub const ABI_NAME_ATTRIBUTE_NAME: &str = "abi_name";
52+
pub const ABI_NAME_NAME_ARG_NAME: &str = "name";
53+
5054
pub const KNOWN_ATTRIBUTE_NAMES: &[&str] = &[
5155
STORAGE_ATTRIBUTE_NAME,
5256
DOC_COMMENT_ATTRIBUTE_NAME,
@@ -57,6 +61,7 @@ pub const KNOWN_ATTRIBUTE_NAMES: &[&str] = &[
5761
CFG_ATTRIBUTE_NAME,
5862
DEPRECATED_ATTRIBUTE_NAME,
5963
FALLBACK_ATTRIBUTE_NAME,
64+
ABI_NAME_ATTRIBUTE_NAME,
6065
];
6166

6267
/// An attribute declaration. Attribute declaration
Lines changed: 114 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use sway_types::{integer_bits::IntegerBits, Named};
1+
use sway_error::handler::{ErrorEmitted, Handler};
2+
use sway_types::{integer_bits::IntegerBits, BaseIdent, Named};
23

3-
use crate::{language::CallPath, Engines, GenericArgument, TypeId, TypeInfo};
4+
use crate::{language::CallPath, transform, Engines, GenericArgument, TypeId, TypeInfo};
45

56
#[derive(Clone)]
67
pub struct AbiStrContext {
@@ -14,14 +15,17 @@ impl TypeId {
1415
/// Gives back a string that represents the type, considering what it resolves to
1516
pub fn get_abi_type_str(
1617
&self,
18+
handler: &Handler,
1719
ctx: &AbiStrContext,
1820
engines: &Engines,
1921
resolved_type_id: TypeId,
20-
) -> String {
22+
) -> Result<String, ErrorEmitted> {
2123
let type_engine = engines.te();
22-
let self_abi_str = type_engine.get(*self).abi_str(ctx, engines, true);
24+
let self_abi_str = type_engine
25+
.get(*self)
26+
.abi_str(handler, ctx, engines, true)?;
2327
if self.is_generic_parameter(engines, resolved_type_id) {
24-
format!("generic {}", self_abi_str)
28+
Ok(format!("generic {}", self_abi_str))
2529
} else {
2630
match (
2731
&*type_engine.get(*self),
@@ -30,23 +34,26 @@ impl TypeId {
3034
(TypeInfo::Custom { .. }, TypeInfo::Struct { .. })
3135
| (TypeInfo::Custom { .. }, TypeInfo::Enum { .. }) => type_engine
3236
.get(resolved_type_id)
33-
.abi_str(ctx, engines, true),
37+
.abi_str(handler, ctx, engines, true),
3438
(_, TypeInfo::Alias { ty, .. }) => {
35-
ty.type_id().get_abi_type_str(ctx, engines, ty.type_id())
39+
ty.type_id()
40+
.get_abi_type_str(handler, ctx, engines, ty.type_id())
3641
}
3742
(TypeInfo::Tuple(fields), TypeInfo::Tuple(resolved_fields)) => {
3843
assert_eq!(fields.len(), resolved_fields.len());
3944
let field_strs = resolved_fields
4045
.iter()
4146
.map(|f| {
4247
if ctx.abi_with_fully_specified_types {
43-
type_engine.get(f.type_id()).abi_str(ctx, engines, false)
48+
type_engine
49+
.get(f.type_id())
50+
.abi_str(handler, ctx, engines, false)
4451
} else {
45-
"_".to_string()
52+
Ok("_".to_string())
4653
}
4754
})
48-
.collect::<Vec<String>>();
49-
format!("({})", field_strs.join(", "))
55+
.collect::<Result<Vec<String>, _>>()?;
56+
Ok(format!("({})", field_strs.join(", ")))
5057
}
5158
(TypeInfo::Array(_, length), TypeInfo::Array(type_arg, resolved_length)) => {
5259
assert_eq!(
@@ -56,76 +63,80 @@ impl TypeId {
5663
let inner_type = if ctx.abi_with_fully_specified_types {
5764
type_engine
5865
.get(type_arg.type_id())
59-
.abi_str(ctx, engines, false)
66+
.abi_str(handler, ctx, engines, false)?
6067
} else {
6168
"_".to_string()
6269
};
63-
format!("[{}; {:?}]", inner_type, engines.help_out(length))
70+
Ok(format!("[{}; {:?}]", inner_type, engines.help_out(length)))
6471
}
6572
(TypeInfo::Slice(type_arg), TypeInfo::Slice(_)) => {
6673
let inner_type = if ctx.abi_with_fully_specified_types {
6774
type_engine
6875
.get(type_arg.type_id())
69-
.abi_str(ctx, engines, false)
76+
.abi_str(handler, ctx, engines, false)?
7077
} else {
7178
"_".to_string()
7279
};
73-
format!("[{}]", inner_type)
74-
}
75-
(TypeInfo::Custom { .. }, _) => {
76-
format!("generic {}", self_abi_str)
80+
Ok(format!("[{}]", inner_type))
7781
}
82+
(TypeInfo::Custom { .. }, _) => Ok(format!("generic {}", self_abi_str)),
7883
_ => type_engine
7984
.get(resolved_type_id)
80-
.abi_str(ctx, engines, true),
85+
.abi_str(handler, ctx, engines, true),
8186
}
8287
}
8388
}
8489
}
8590

8691
impl TypeInfo {
87-
pub fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines, is_root: bool) -> String {
92+
pub fn abi_str(
93+
&self,
94+
handler: &Handler,
95+
ctx: &AbiStrContext,
96+
engines: &Engines,
97+
is_root: bool,
98+
) -> Result<String, ErrorEmitted> {
8899
use TypeInfo::*;
89100
let decl_engine = engines.de();
90101
match self {
91-
Unknown => "unknown".into(),
92-
Never => "never".into(),
93-
UnknownGeneric { name, .. } => name.to_string(),
94-
Placeholder(_) => "_".to_string(),
95-
TypeParam(param) => format!("typeparam({})", param.name()),
96-
StringSlice => "str".into(),
97-
StringArray(length) => format!("str[{}]", length.val()),
98-
UnsignedInteger(x) => match x {
102+
Unknown => Ok("unknown".into()),
103+
Never => Ok("never".into()),
104+
UnknownGeneric { name, .. } => Ok(name.to_string()),
105+
Placeholder(_) => Ok("_".to_string()),
106+
TypeParam(param) => Ok(format!("typeparam({})", param.name())),
107+
StringSlice => Ok("str".into()),
108+
StringArray(length) => Ok(format!("str[{}]", length.val())),
109+
UnsignedInteger(x) => Ok(match x {
99110
IntegerBits::Eight => "u8",
100111
IntegerBits::Sixteen => "u16",
101112
IntegerBits::ThirtyTwo => "u32",
102113
IntegerBits::SixtyFour => "u64",
103114
IntegerBits::V256 => "u256",
104115
}
105-
.into(),
106-
Boolean => "bool".into(),
116+
.into()),
117+
Boolean => Ok("bool".into()),
107118
Custom {
108119
qualified_call_path: call_path,
109120
..
110-
} => call_path.call_path.suffix.to_string(),
121+
} => Ok(call_path.call_path.suffix.to_string()),
111122
Tuple(fields) => {
112123
let field_strs = fields
113124
.iter()
114-
.map(|field| field.abi_str(ctx, engines, false))
115-
.collect::<Vec<String>>();
116-
format!("({})", field_strs.join(", "))
125+
.map(|field| field.abi_str(handler, ctx, engines, false))
126+
.collect::<Result<Vec<String>, ErrorEmitted>>()?;
127+
Ok(format!("({})", field_strs.join(", ")))
117128
}
118-
B256 => "b256".into(),
119-
Numeric => "u64".into(), // u64 is the default
120-
Contract => "contract".into(),
121-
ErrorRecovery(_) => "unknown due to error".into(),
129+
B256 => Ok("b256".into()),
130+
Numeric => Ok("u64".into()), // u64 is the default
131+
Contract => Ok("contract".into()),
132+
ErrorRecovery(_) => Ok("unknown due to error".into()),
122133
UntypedEnum(decl_id) => {
123134
let decl = engines.pe().get_enum(decl_id);
124-
format!("untyped enum {}", decl.name)
135+
Ok(format!("untyped enum {}", decl.name))
125136
}
126137
UntypedStruct(decl_id) => {
127138
let decl = engines.pe().get_struct(decl_id);
128-
format!("untyped struct {}", decl.name)
139+
Ok(format!("untyped struct {}", decl.name))
129140
}
130141
Enum(decl_ref) => {
131142
let decl = decl_engine.get_enum(decl_ref);
@@ -134,20 +145,19 @@ impl TypeInfo {
134145
{
135146
"".into()
136147
} else {
137-
format!(
138-
"<{}>",
139-
decl.type_parameters
140-
.iter()
141-
.map(|p| p.abi_str(engines, ctx, false))
142-
.collect::<Vec<_>>()
143-
.join(",")
144-
)
148+
let params = decl
149+
.type_parameters
150+
.iter()
151+
.map(|p| p.abi_str(handler, engines, ctx, false))
152+
.collect::<Result<Vec<_>, _>>()?;
153+
format!("<{}>", params.join(","))
145154
};
146-
format!(
155+
let abi_call_path = get_abi_call_path(handler, &decl.call_path, &decl.attributes)?;
156+
Ok(format!(
147157
"enum {}{}",
148-
call_path_display(ctx, &decl.call_path),
158+
call_path_display(ctx, &abi_call_path),
149159
type_params
150-
)
160+
))
151161
}
152162
Struct(decl_ref) => {
153163
let decl = decl_engine.get_struct(decl_ref);
@@ -156,58 +166,69 @@ impl TypeInfo {
156166
{
157167
"".into()
158168
} else {
159-
format!(
160-
"<{}>",
161-
decl.type_parameters
162-
.iter()
163-
.map(|p| p.abi_str(engines, ctx, false))
164-
.collect::<Vec<_>>()
165-
.join(",")
166-
)
169+
let params = decl
170+
.type_parameters
171+
.iter()
172+
.map(|p| p.abi_str(handler, engines, ctx, false))
173+
.collect::<Result<Vec<_>, _>>()?;
174+
format!("<{}>", params.join(","))
167175
};
168-
format!(
176+
let abi_call_path = get_abi_call_path(handler, &decl.call_path, &decl.attributes)?;
177+
Ok(format!(
169178
"struct {}{}",
170-
call_path_display(ctx, &decl.call_path),
179+
call_path_display(ctx, &abi_call_path),
171180
type_params
172-
)
173-
}
174-
ContractCaller { abi_name, .. } => {
175-
format!("contract caller {abi_name}")
176-
}
177-
Array(elem_ty, length) => {
178-
format!(
179-
"[{}; {:?}]",
180-
elem_ty.abi_str(ctx, engines, false),
181-
engines.help_out(length)
182-
)
181+
))
183182
}
184-
RawUntypedPtr => "raw untyped ptr".into(),
185-
RawUntypedSlice => "raw untyped slice".into(),
186-
Ptr(ty) => {
187-
format!("__ptr {}", ty.abi_str(ctx, engines, false))
188-
}
189-
Slice(ty) => {
190-
format!("__slice {}", ty.abi_str(ctx, engines, false))
191-
}
192-
Alias { ty, .. } => ty.abi_str(ctx, engines, false),
183+
ContractCaller { abi_name, .. } => Ok(format!("contract caller {abi_name}")),
184+
Array(elem_ty, length) => Ok(format!(
185+
"[{}; {:?}]",
186+
elem_ty.abi_str(handler, ctx, engines, false)?,
187+
engines.help_out(length)
188+
)),
189+
RawUntypedPtr => Ok("raw untyped ptr".into()),
190+
RawUntypedSlice => Ok("raw untyped slice".into()),
191+
Ptr(ty) => Ok(format!(
192+
"__ptr {}",
193+
ty.abi_str(handler, ctx, engines, false)?
194+
)),
195+
Slice(ty) => Ok(format!(
196+
"__slice {}",
197+
ty.abi_str(handler, ctx, engines, false)?
198+
)),
199+
Alias { ty, .. } => Ok(ty.abi_str(handler, ctx, engines, false)?),
193200
TraitType {
194201
name,
195202
trait_type_id: _,
196-
} => format!("trait type {}", name),
203+
} => Ok(format!("trait type {}", name)),
197204
Ref {
198205
to_mutable_value,
199206
referenced_type,
200207
} => {
201-
format!(
208+
Ok(format!(
202209
"__ref {}{}", // TODO-IG: No references in ABIs according to the RFC. Or we want to have them?
203210
if *to_mutable_value { "mut " } else { "" },
204-
referenced_type.abi_str(ctx, engines, false)
205-
)
211+
referenced_type.abi_str(handler, ctx, engines, false)?
212+
))
206213
}
207214
}
208215
}
209216
}
210217

218+
fn get_abi_call_path(
219+
handler: &Handler,
220+
call_path: &CallPath,
221+
attributes: &transform::Attributes,
222+
) -> Result<CallPath, ErrorEmitted> {
223+
let mut abi_call_path = call_path.clone();
224+
if let Some(abi_name_attr) = attributes.abi_name() {
225+
let name = abi_name_attr.args.first().unwrap();
226+
let span = name.get_string_span(handler, abi_name_attr)?;
227+
abi_call_path.suffix = BaseIdent::new(span);
228+
}
229+
Ok(abi_call_path)
230+
}
231+
211232
/// `call_path_display` returns the provided `call_path` without the first prefix in case it is equal to the program name.
212233
/// If the program name is `my_program` and the `call_path` is `my_program::MyStruct` then this function returns only `MyStruct`.
213234
fn call_path_display(ctx: &AbiStrContext, call_path: &CallPath) -> String {
@@ -228,10 +249,16 @@ fn call_path_display(ctx: &AbiStrContext, call_path: &CallPath) -> String {
228249
}
229250

230251
impl GenericArgument {
231-
pub(self) fn abi_str(&self, ctx: &AbiStrContext, engines: &Engines, is_root: bool) -> String {
252+
pub(self) fn abi_str(
253+
&self,
254+
handler: &Handler,
255+
ctx: &AbiStrContext,
256+
engines: &Engines,
257+
is_root: bool,
258+
) -> Result<String, ErrorEmitted> {
232259
engines
233260
.te()
234261
.get(self.type_id())
235-
.abi_str(ctx, engines, is_root)
262+
.abi_str(handler, ctx, engines, is_root)
236263
}
237264
}

0 commit comments

Comments
 (0)