Mutability in Effects
Effects distinguish between read-only and mutable access. This distinction is enforced at compile time, preventing accidental mutations.
Read-Only Effects
Section titled “Read-Only Effects”By default, effects are read-only:
fn get_value() -> u256 uses (config: Config) { config.value // Can read}Read-only effects:
- Allow reading data from the effect
- Prevent any modification
- Are the default when
mutis not specified
Attempting to modify a read-only effect is a compile error:
// This would be a compile error:fn try_modify() uses (config: Config) { config.value = 100 // Error: cannot modify immutable effect}Mutable Effects
Section titled “Mutable Effects”Add mut to allow modification:
fn set_value(new_value: u256) uses (mut config: Config) { config.value = new_value // Can modify}Mutable effects:
- Allow both reading and writing
- Must be explicitly declared with
mut - Require a mutable binding when provided
Mutability Matching Rules
Section titled “Mutability Matching Rules”When calling a function that requires an effect, the caller must provide a compatible effect:
Rule 1: Mutable Satisfies Immutable
Section titled “Rule 1: Mutable Satisfies Immutable”A mutable effect can satisfy an immutable requirement:
fn read_only() uses (data: Data) { // reads Data}
fn outer() uses (mut data: Data) { read_only() // OK: mut Data satisfies Data}Rule 2: Immutable Cannot Satisfy Mutable
Section titled “Rule 2: Immutable Cannot Satisfy Mutable”An immutable effect cannot satisfy a mutable requirement:
// This would be a compile error:fn needs_mut() uses (mut data: Data) { // modifies Data}
fn outer() uses (data: Data) { needs_mut() // Error: Data cannot satisfy mut Data}Rule 3: Binding Mutability
Section titled “Rule 3: Binding Mutability”When providing an effect with with, the binding’s mutability determines the effect’s mutability:
pub struct Counter { pub value: u256 }
fn needs_mut() uses (mut counter: Counter) { counter.value = counter.value + 1}
fn example() { // Immutable binding - would error if we tried to call needs_mut() let counter = Counter { value: 0 }
// Mutable binding - can satisfy mut effect let mut counter2 = Counter { value: 0 }
with (Counter = counter2) { needs_mut() // OK: counter2 is mutable }}When to Use Each
Section titled “When to Use Each”Use Read-Only When
Section titled “Use Read-Only When”- The function only reads data
- You want to prevent accidental modification
- You’re implementing a getter or query
fn total_supply() -> u256 uses (store: TokenStore) { store.supply}
fn is_valid(amount: u256) -> bool uses (config: Config) { amount <= config.max_amount}Use Mutable When
Section titled “Use Mutable When”- The function modifies data
- You’re implementing a setter or state change
- The operation has side effects
fn mint(amount: u256) uses (mut store: TokenStore) { store.supply = store.supply + amount}
fn update_config(new_max: u256) uses (mut config: Config) { config.max_amount = new_max}Named Effects and Mutability
Section titled “Named Effects and Mutability”Named effects follow the same rules:
fn process() uses (data: Data, mut cache: Cache) { // data is read-only // cache is mutable
let value = data.value // OK: reading cache.store(value) // OK: mutable operation
// data.value = 100 // Would error: data is not mutable}Mutability in Practice
Section titled “Mutability in Practice”A common pattern separates read and write operations:
pub struct Balances { pub data: Map<u256, u256>,}
// Read-only: safe to call anywherefn get_balance(account: u256) -> u256 uses (balances: Balances) { balances.data.get(account)}
// Mutable: changes statefn set_balance(account: u256, amount: u256) uses (mut balances: Balances) { balances.data.set(account, amount)}
// Mutable: combines read and writefn transfer(from: u256, to: u256, amount: u256) uses (mut balances: Balances) { let from_balance = get_balance(from) // Calls read-only function let to_balance = get_balance(to)
set_balance(from, from_balance - amount) set_balance(to, to_balance + amount)}Summary
Section titled “Summary”| Declaration | Can Read | Can Modify |
|---|---|---|
uses (e: Effect) | Yes | No |
uses (mut e: Effect) | Yes | Yes |
| Caller Has | Callee Needs | Result |
|---|---|---|
(e: Effect) | (e: Effect) | OK |
(mut e: Effect) | (e: Effect) | OK |
(e: Effect) | (mut e: Effect) | Error |
(mut e: Effect) | (mut e: Effect) | OK |