# 0145 — method with `*self` called directly on an array-index expression operates on a COPY > **RESOLVED.** `fixupMethodReceiver` (src/ir/lower/expr.zig) now takes the > real address of `.index_expr` and `.deref_expr` receivers via > `lowerExprAsPtr` (normalizing to `*T`), mirroring the explicit-argument path > in `call.zig` — so `arr[i].method()` mutates the live slot instead of a > throwaway copy. A comptime-pack index (`xs[i]` where `xs` is a pack) is > explicitly excluded: a pack has no runtime storage to address, so it keeps > flowing through the general alloca+store-of-value path. Regression test: > `examples/0188-types-method-array-index-receiver.sx`. ## Summary Calling a method whose receiver is `*self` (mutating) directly on a fixed-array element expression — `arr[i].method(...)` — mutates a temporary COPY of the element, not the live array slot. The mutation is silently lost. Binding the element to a pointer first (`p := @arr[i]; p.method(...)`) works correctly. ## Repro ``` S :: struct { flag: bool; set :: (self: *S) { self.flag = true; } } A :: struct { items: [4]S; } main :: () -> i32 { a : A = .{}; a.items[1].set(); // BUG: mutates a copy print("direct = {}\n", a.items[1].flag); // prints false p := @a.items[1]; p.set(); // OK: mutates the live slot print("ptr = {}\n", a.items[1].flag); // prints true 0 } ``` Observed: ``` direct = false ptr = true ``` Expected: both print `true` — `a.items[1].set()` takes `*self` and should bind the receiver to the address of `a.items[1]`, exactly as the explicit-pointer form does. The same surfaced with a non-trivial method (`Slider.handle_event(self: *Slider, ...)`): the direct call returned `true` (so the method body ran) yet left the element's `pressed`/`value` fields unchanged, while `@arr[i]` bound to a local and called on that pointer mutated the element as expected. ## Impact Any struct that holds a fixed array of widgets/records and dispatches `*self` methods per element (a layers panel with one `Slider` per row, an entity table, etc.) silently no-ops the mutation. It is easy to miss because the method's return value is correct — only the in-place writes vanish. ## Workaround Bind the element to a pointer before the call: ``` p := @arr[i]; p.method(...); ``` Field stores through the index (`arr[i].field = v`) and value assignment (`arr[i] = v`) appear unaffected; only the implicit `&arr[i]` receiver of a `*self` method call is materialized as a copy. Found while implementing `ui/layers_panel.sx` in the photo editor (one opacity `Slider` per layer row).