Skip to content

Commit 5436f6b

Browse files
Remove warnings from mutable function arguments (#1606)
### What Add test coverage for contract functions that use mutable function arguments. Create new test_mutability contract with a calc function that accepts a mutable parameter, demonstrating that the SDK macros correctly handle mut keywords in contract implementations. Remove warnings that the test coverage surfaced. ### Why The SDK's contract macros already support mutable function parameters, which are is a Rust pattern. This test ensures the macro expansion correctly preserves mutability modifiers and validates the generated code compiles and executes correctly. The test surfaced that warnings are generated in this case, and the warnings shouldn't be as the user is writing valid code and the warnings are coming from the generated code. Close #1605
1 parent 0a1c1c0 commit 5436f6b

File tree

10 files changed

+772
-4
lines changed

10 files changed

+772
-4
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

soroban-sdk-macros/src/syn_ext.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use syn::{
1010
};
1111
use syn::{
1212
spanned::Spanned, token::And, Error, FnArg, Ident, ImplItem, ImplItemFn, ItemImpl, ItemTrait,
13-
Lifetime, Pat, PatType, TraitItem, TraitItemFn, Type, TypeReference, Visibility,
13+
Lifetime, Pat, PatIdent, PatType, TraitItem, TraitItemFn, Type, TypeReference, Visibility,
1414
};
1515

1616
/// Gets methods from the implementation that have public visibility. For
@@ -48,6 +48,26 @@ pub fn fn_arg_ident(arg: &FnArg) -> Result<Ident, Error> {
4848
))
4949
}
5050

51+
/// Modifies a Pat removing any 'mut' on an Ident.
52+
pub fn pat_unwrap_mut(p: Pat) -> Pat {
53+
match p {
54+
Pat::Ident(PatIdent {
55+
attrs,
56+
by_ref,
57+
mutability: Some(_),
58+
ident,
59+
subpat,
60+
}) => Pat::Ident(PatIdent {
61+
attrs,
62+
by_ref,
63+
mutability: None,
64+
ident,
65+
subpat,
66+
}),
67+
_ => p,
68+
}
69+
}
70+
5171
/// Returns a clone of the type from the FnArg.
5272
pub fn fn_arg_ref_type(arg: &FnArg, lifetime: Option<&Lifetime>) -> Result<Type, Error> {
5373
if let FnArg::Typed(pat_type) = arg {
@@ -70,13 +90,13 @@ pub fn fn_arg_ref_type(arg: &FnArg, lifetime: Option<&Lifetime>) -> Result<Type,
7090
}
7191

7292
/// Returns a clone of FnArg with the type as a reference if the arg is a typed
73-
/// arg and its type is not already a reference.
93+
/// arg and its type is not already a reference. Mutability from the ident is stripped.
7494
pub fn fn_arg_make_ref(arg: &FnArg, lifetime: Option<&Lifetime>) -> FnArg {
7595
if let FnArg::Typed(pat_type) = arg {
7696
if !matches!(*pat_type.ty, Type::Reference(_)) {
7797
return FnArg::Typed(PatType {
7898
attrs: pat_type.attrs.clone(),
79-
pat: pat_type.pat.clone(),
99+
pat: Box::new(pat_unwrap_mut(*pat_type.pat.clone())),
80100
colon_token: pat_type.colon_token,
81101
ty: Box::new(Type::Reference(TypeReference {
82102
and_token: And::default(),
@@ -90,12 +110,14 @@ pub fn fn_arg_make_ref(arg: &FnArg, lifetime: Option<&Lifetime>) -> FnArg {
90110
arg.clone()
91111
}
92112

113+
/// Returns a clone of FnArg with the type as an Into if the arg is a typed
114+
/// arg. Mutability from the ident is stripped.
93115
pub fn fn_arg_make_into(arg: &FnArg) -> FnArg {
94116
if let FnArg::Typed(pat_type) = arg {
95117
let ty = &pat_type.ty;
96118
return FnArg::Typed(PatType {
97119
attrs: pat_type.attrs.clone(),
98-
pat: pat_type.pat.clone(),
120+
pat: Box::new(pat_unwrap_mut(*pat_type.pat.clone())),
99121
colon_token: pat_type.colon_token,
100122
ty: Box::new(syn::parse_quote! { impl Into<#ty> }),
101123
});

soroban-sdk/src/tests/contract_fn.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ impl Contract {
1717
pub fn add_with_unused_arg(_e: &Env, a: i32, _b: i32) -> i32 {
1818
a + 2
1919
}
20+
21+
pub fn add_with_mut_arg(_e: &Env, a: i32, mut b: i32) -> i32 {
22+
b *= 1;
23+
a + b
24+
}
2025
}
2126

2227
#[contract]
@@ -38,6 +43,9 @@ fn test_functional() {
3843
let b = 12i32;
3944
let c = ContractClient::new(&e, &contract_id).add(&a, &b);
4045
assert_eq!(c, 22);
46+
47+
let c = ContractClient::new(&e, &contract_id).add_with_mut_arg(&a, &b);
48+
assert_eq!(c, 22);
4149
}
4250

4351
#[test]

soroban-sdk/test_snapshots/tests/contract_fn/test_functional.1.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"mux_id": 0
66
},
77
"auth": [
8+
[],
89
[],
910
[]
1011
],

0 commit comments

Comments
 (0)