Effect Propagation
Effects propagate through the call chain. When you call a function that requires effects, those effects must be available in your current scope.
How Propagation Works
Section titled “How Propagation Works”When function A calls function B, and B requires an effect, A must either:
- Have that effect in its own
usesclause - Provide the effect using a
withexpression
fn inner() uses (storage: Storage) { // Uses Storage}
fn outer() uses (storage: Storage) { inner() // OK: Storage is available from outer's uses clause}If an effect is missing, the compiler reports an error:
// This would be a compile error:fn inner() uses (storage: Storage) { // Uses Storage}
fn outer() { inner() // Error: missing effect Storage}The with Expression
Section titled “The with Expression”The with expression provides effects to a scope:
pub struct Storage { pub data: u256 }
fn needs_storage() uses (storage: Storage) { // ...}
fn main() { let storage = Storage { data: 0 }
with (Storage = storage) { needs_storage() // OK: Storage is provided }}Syntax
Section titled “Syntax”let value = EffectType { data: 0 }with (EffectType = value) { // Effect is available here}
// Multiple effectslet val1 = Effect1 { data: 0 }let val2 = Effect2 { data: 0 }with (Effect1 = val1, Effect2 = val2) { // Both effects available}Scoping
Section titled “Scoping”Effects from with are only available inside the block:
// This would be a compile error:fn example() { let data = Data { value: 0 }
with (Data = data) { use_data() // OK: Data is available }
use_data() // Error: Data is not available here}Propagation Chain
Section titled “Propagation Chain”Effects propagate through any depth of calls:
pub struct Config { pub max: u256 }
fn level3() uses (config: Config) { // Uses Config}
fn level2() uses (config: Config) { level3() // Config propagates}
fn level1() uses (config: Config) { level2() // Config propagates}
fn entry() { let config = Config { max: 100 }
with (Config = config) { level1() // Provides Config for entire chain }}Nested with Expressions
Section titled “Nested with Expressions”with expressions can be nested, creating layered scopes:
pub struct A { pub data: u256 }pub struct B { pub data: u256 }
fn needs_both() uses (a: A, b: B) { // ...}
fn example() { let a = A { data: 0 } let b = B { data: 0 }
with (A = a) { // A is available
with (B = b) { // Both A and B are available needs_both() }
// Only A is available here }}Or provide multiple effects at once:
with (A = a, B = b) { needs_both()}Effect Shadowing
Section titled “Effect Shadowing”Inner scopes can shadow outer effects:
pub struct Data { pub value: u256 }
fn read_value() -> u256 uses (data: Data) { data.value}
fn example() { let outer = Data { value: 10 } let inner = Data { value: 20 }
with (Data = outer) { let v1 = read_value() // Returns 10
with (Data = inner) { let v2 = read_value() // Returns 20 (shadowed) }
let v3 = read_value() // Returns 10 (back to outer) }}Combining uses and with
Section titled “Combining uses and with”Functions can have their own effects and also provide additional effects:
fn helper() uses (config: Config, mut logger: Logger) { // Needs both effects}
fn outer() uses (config: Config) { let mut logger = Logger { data: 0 }
// Config comes from uses clause // Logger is provided by with with (Logger = logger) { helper() }}Error Messages
Section titled “Error Messages”The compiler provides clear error messages for effect issues:
Missing Effect
Section titled “Missing Effect”// This would be a compile error:fn needs_data() uses (data: Data) { }
fn caller() { needs_data() // Error: function `needs_data` requires effect `Data` // which is not available in this scope}Mutability Mismatch
Section titled “Mutability Mismatch”// This would be a compile error:fn needs_mut() uses (mut data: Data) { }
fn caller() uses (data: Data) { needs_mut() // Error: function `needs_mut` requires mutable effect `Data` // but only immutable `Data` is available}Summary
Section titled “Summary”| Concept | Description |
|---|---|
| Propagation | Effects flow from caller to callee |
with | Provides effects to a scope |
| Scoping | Effects only available inside their scope |
| Nesting | with can be nested for layered effects |
| Shadowing | Inner effects shadow outer ones |