Skip to content

Commit 04f5114

Browse files
committed
Add #[abi_name() attribute to rename ABI items.
Add `#[abi_name()` 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 04f5114

File tree

10 files changed

+192
-5
lines changed

10 files changed

+192
-5
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

sway-core/src/abi_generation/abi_str.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use sway_types::{integer_bits::IntegerBits, Named};
1+
use sway_ast::Literal;
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 {
@@ -143,9 +144,10 @@ impl TypeInfo {
143144
.join(",")
144145
)
145146
};
147+
let abi_call_path = handle_abi_name_attribute(&decl.call_path, &decl.attributes);
146148
format!(
147149
"enum {}{}",
148-
call_path_display(ctx, &decl.call_path),
150+
call_path_display(ctx, &abi_call_path),
149151
type_params
150152
)
151153
}
@@ -165,9 +167,10 @@ impl TypeInfo {
165167
.join(",")
166168
)
167169
};
170+
let abi_call_path = handle_abi_name_attribute(&decl.call_path, &decl.attributes);
168171
format!(
169172
"struct {}{}",
170-
call_path_display(ctx, &decl.call_path),
173+
call_path_display(ctx, &abi_call_path),
171174
type_params
172175
)
173176
}
@@ -208,6 +211,19 @@ impl TypeInfo {
208211
}
209212
}
210213

214+
fn handle_abi_name_attribute(call_path: &CallPath, attributes: &transform::Attributes) -> CallPath {
215+
let mut abi_call_path = call_path.clone();
216+
if let Some(abi_name_attr) = attributes.abi_name() {
217+
let name = abi_name_attr.args.first().unwrap();
218+
let literal = match name.value.as_ref().unwrap() {
219+
Literal::String(lit_string) => lit_string,
220+
_ => unreachable!()
221+
};
222+
abi_call_path.suffix = BaseIdent::new(literal.span.clone());
223+
}
224+
abi_call_path
225+
}
226+
211227
/// `call_path_display` returns the provided `call_path` without the first prefix in case it is equal to the program name.
212228
/// If the program name is `my_program` and the `call_path` is `my_program::MyStruct` then this function returns only `MyStruct`.
213229
fn call_path_display(ctx: &AbiStrContext, call_path: &CallPath) -> String {

sway-core/src/transform/attribute.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ pub enum ArgsExpectValues {
317317
///
318318
/// E.g.: `#[cfg(target = "fuel", experimental_new_encoding = false)]`.
319319
Yes,
320-
/// None of the arguments can never have values specified, or the
320+
/// None of the arguments can have values specified, or the
321321
/// [Attribute] does not expect any arguments.
322322
///
323323
/// E.g.: `#[storage(read, write)]`, `#[fallback]`.
@@ -348,6 +348,7 @@ pub enum AttributeKind {
348348
Cfg,
349349
Deprecated,
350350
Fallback,
351+
AbiName,
351352
}
352353

353354
/// Denotes if an [ItemTraitItem] belongs to an ABI or to a trait.
@@ -376,6 +377,7 @@ impl AttributeKind {
376377
CFG_ATTRIBUTE_NAME => AttributeKind::Cfg,
377378
DEPRECATED_ATTRIBUTE_NAME => AttributeKind::Deprecated,
378379
FALLBACK_ATTRIBUTE_NAME => AttributeKind::Fallback,
380+
ABI_NAME_ATTRIBUTE_NAME => AttributeKind::AbiName,
379381
_ => AttributeKind::Unknown,
380382
}
381383
}
@@ -402,6 +404,7 @@ impl AttributeKind {
402404
Cfg => true,
403405
Deprecated => false,
404406
Fallback => false,
407+
AbiName => false,
405408
}
406409
}
407410
}
@@ -440,6 +443,7 @@ impl Attribute {
440443
// `deprecated`, `deprecated(note = "note")`.
441444
Deprecated => Multiplicity::at_most(1),
442445
Fallback => Multiplicity::zero(),
446+
AbiName => Multiplicity::exactly(1),
443447
}
444448
}
445449

@@ -493,6 +497,7 @@ impl Attribute {
493497
}
494498
Deprecated => MustBeIn(vec![DEPRECATED_NOTE_ARG_NAME]),
495499
Fallback => None,
500+
AbiName => MustBeIn(vec![ABI_NAME_NAME_ARG_NAME]),
496501
}
497502
}
498503

@@ -513,6 +518,7 @@ impl Attribute {
513518
// `deprecated(note = "note")`.
514519
Deprecated => Yes,
515520
Fallback => No,
521+
AbiName => Yes,
516522
}
517523
}
518524

@@ -531,6 +537,7 @@ impl Attribute {
531537
// Deprecating the module kind will mean deprecating all its items.
532538
Deprecated => false,
533539
Fallback => false,
540+
AbiName => false,
534541
}
535542
}
536543

@@ -582,6 +589,11 @@ impl Attribute {
582589
ItemKind::Error(_, _) => true,
583590
},
584591
Fallback => matches!(item_kind, ItemKind::Fn(_)),
592+
AbiName => match item_kind {
593+
ItemKind::Struct(_) => true,
594+
ItemKind::Enum(_) => true,
595+
_ => true,
596+
}
585597
}
586598
}
587599

@@ -605,6 +617,7 @@ impl Attribute {
605617
Cfg => true,
606618
Deprecated => true,
607619
Fallback => false,
620+
AbiName => true,
608621
}
609622
}
610623

@@ -628,6 +641,7 @@ impl Attribute {
628641
// TODO: Change to true once https://github.com/FuelLabs/sway/issues/6942 is implemented.
629642
Deprecated => false,
630643
Fallback => false,
644+
AbiName => false,
631645
}
632646
}
633647

@@ -648,6 +662,7 @@ impl Attribute {
648662
Cfg => true,
649663
Deprecated => !matches!(item, ItemImplItem::Type(_)),
650664
Fallback => false,
665+
AbiName => false,
651666
}
652667
}
653668

@@ -667,6 +682,7 @@ impl Attribute {
667682
Cfg => true,
668683
Deprecated => true,
669684
Fallback => false,
685+
AbiName => false,
670686
}
671687
}
672688

@@ -684,6 +700,7 @@ impl Attribute {
684700
// TODO: Change to true once https://github.com/FuelLabs/sway/issues/6942 is implemented.
685701
Deprecated => false,
686702
Fallback => false,
703+
AbiName => false,
687704
}
688705
}
689706

@@ -700,6 +717,7 @@ impl Attribute {
700717
Cfg => true,
701718
Deprecated => true,
702719
Fallback => false,
720+
AbiName => false,
703721
}
704722
}
705723

@@ -749,6 +767,9 @@ impl Attribute {
749767
"\"deprecated\" attribute is currently not implemented for all elements that could be deprecated.",
750768
],
751769
Fallback => vec!["\"fallback\" attribute can only annotate module functions in a contract module."],
770+
AbiName => vec![
771+
"\"abi_name\" attribute is currently not implemented for all elements that could renamed in ABIs.",
772+
],
752773
};
753774

754775
if help.is_empty() && target_friendly_name.starts_with("module kind") {
@@ -949,6 +970,12 @@ impl Attributes {
949970
.map(|index| &self.attributes[index])
950971
}
951972

973+
/// Returns the `#[abi_name]` [Attribute], or `None` if the
974+
/// [Attributes] does not contain any `#[abi_name]` attributes.
975+
pub fn abi_name(&self) -> Option<&Attribute> {
976+
self.of_kind(AttributeKind::AbiName).last()
977+
}
978+
952979
/// Returns the `#[test]` [Attribute], or `None` if the
953980
/// [Attributes] does not contain any `#[test]` attributes.
954981
pub fn test(&self) -> Option<&Attribute> {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
out
2+
target
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[[package]]
2+
name = "abi_name_attribute"
3+
source = "member"
4+
dependencies = ["std"]
5+
6+
[[package]]
7+
name = "std"
8+
source = "path+from-root-ADA3C90E7ED94315"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[project]
2+
authors = ["Fuel Labs <[email protected]>"]
3+
entry = "lib.sw"
4+
license = "Apache-2.0"
5+
name = "abi_name_attribute"
6+
7+
[dependencies]
8+
std = { path = "../../../../../../../sway-lib-std" }
9+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"concreteTypes": [
3+
{
4+
"concreteTypeId": "ae12f4febfb972911e17d7d6cef8cb1d27073b2909d02360bd10827626bfae2b",
5+
"metadataTypeId": 1,
6+
"type": "enum \"RenamedMyEnum\""
7+
},
8+
{
9+
"concreteTypeId": "b4d23182b68c23897a0f62a99d0fbea374f31183cc4072740c90c76d27582032",
10+
"type": "struct \"RenamedMyScript\""
11+
}
12+
],
13+
"configurables": [],
14+
"encodingVersion": "1",
15+
"functions": [
16+
{
17+
"attributes": null,
18+
"inputs": [],
19+
"name": "my_enum",
20+
"output": "ae12f4febfb972911e17d7d6cef8cb1d27073b2909d02360bd10827626bfae2b"
21+
},
22+
{
23+
"attributes": null,
24+
"inputs": [],
25+
"name": "my_struct",
26+
"output": "b4d23182b68c23897a0f62a99d0fbea374f31183cc4072740c90c76d27582032"
27+
}
28+
],
29+
"loggedTypes": [],
30+
"messagesTypes": [],
31+
"metadataTypes": [
32+
{
33+
"metadataTypeId": 0,
34+
"type": "()"
35+
},
36+
{
37+
"components": [
38+
{
39+
"name": "A",
40+
"typeId": 0
41+
}
42+
],
43+
"metadataTypeId": 1,
44+
"type": "enum \"RenamedMyEnum\""
45+
}
46+
],
47+
"programType": "contract",
48+
"specVersion": "1"
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"concreteTypes": [
3+
{
4+
"concreteTypeId": "ae12f4febfb972911e17d7d6cef8cb1d27073b2909d02360bd10827626bfae2b",
5+
"metadataTypeId": 1,
6+
"type": "enum \"RenamedMyEnum\""
7+
},
8+
{
9+
"concreteTypeId": "b4d23182b68c23897a0f62a99d0fbea374f31183cc4072740c90c76d27582032",
10+
"type": "struct \"RenamedMyScript\""
11+
}
12+
],
13+
"configurables": [],
14+
"encodingVersion": "1",
15+
"functions": [
16+
{
17+
"attributes": null,
18+
"inputs": [],
19+
"name": "my_enum",
20+
"output": "ae12f4febfb972911e17d7d6cef8cb1d27073b2909d02360bd10827626bfae2b"
21+
},
22+
{
23+
"attributes": null,
24+
"inputs": [],
25+
"name": "my_struct",
26+
"output": "b4d23182b68c23897a0f62a99d0fbea374f31183cc4072740c90c76d27582032"
27+
}
28+
],
29+
"loggedTypes": [],
30+
"messagesTypes": [],
31+
"metadataTypes": [
32+
{
33+
"metadataTypeId": 0,
34+
"type": "()"
35+
},
36+
{
37+
"components": [
38+
{
39+
"name": "A",
40+
"typeId": 0
41+
}
42+
],
43+
"metadataTypeId": 1,
44+
"type": "enum \"RenamedMyEnum\""
45+
}
46+
],
47+
"programType": "contract",
48+
"specVersion": "1"
49+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
contract;
2+
3+
#[abi_name(name = "RenamedMyScript")]
4+
struct MyStruct {}
5+
6+
#[abi_name(name = "RenamedMyEnum")]
7+
enum MyEnum {
8+
A: ()
9+
}
10+
11+
abi MyAbi {
12+
fn my_struct() -> MyStruct;
13+
fn my_enum() -> MyEnum;
14+
}
15+
16+
impl MyAbi for Contract {
17+
fn my_struct() -> MyStruct { MyStruct{} }
18+
fn my_enum() -> MyEnum { MyEnum::A }
19+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
category = "compile"
2+
expected_warnings = 0
3+
validate_abi = true

0 commit comments

Comments
 (0)