Skip to content

support struct field assignment obj.field = x#202

Merged
kacy merged 1 commit into
mainfrom
feat/struct-field-assign
May 24, 2026
Merged

support struct field assignment obj.field = x#202
kacy merged 1 commit into
mainfrom
feat/struct-field-assign

Conversation

@kacy
Copy link
Copy Markdown
Owner

@kacy kacy commented May 24, 2026

summary

assigning to a struct field silently did the wrong thing: ir_emit_compound_assignment
handled index targets (m[k] = v) and then fell back to treating the assignment target as a
bare identifier, so obj.field = x (and self.field = x inside a method) wrote a local named
after the field instead of the field itself.

now a field-access target lowers to the existing sstore op — the same one struct construction
already emits — for both plain and compound (+=, -=, …) forms:

p.x = 42
c.value += 3
# inside a method (implicit self):
fn step():
    self.value = self.value + 1

because structs are shared heap handles, mutations made through a function parameter or a
method's self are visible to the caller (matching test_shared_collection_aliasing).

this is the missing peer to the struct features that already exist (named-positional
construction and field defaults), and it's the prerequisite for stateful iterators in the
upcoming iterator-protocol work.

how

  • ir_emitter_core.pith: new ir_emit_field_assignment and ir_emit_field_compound_assignment,
    invoked from ir_emit_compound_assignment before the identifier fallback (mirroring the
    existing ir_emit_index_assignment). they resolve the field index via
    ir_struct_field_index_lookup and emit sstore.
  • no checker change: check_assignment already type-checks a field-access target (the field's
    type vs the value).

what was tested

  • new regression tests/cases/test_struct_field_assign.pith: assign a field on a local, compound
    +=, a string field, mutation through a function (reference semantics), mutation through
    methods via implicit self, and p.y = p.x + 1
  • regressions (95), examples via native + self-hosted compilers (83 each) — all 0 failures
  • lint clean on the changed source

(bootstrap fixed-point left to CI.)

assigning to a struct field silently wrote a local instead of the field:
ir_emit_compound_assignment handled index targets (m[k]=v) then fell back to
treating the target as a bare identifier, so obj.field = x and self.field = x
were lost.

now a field-access target lowers to the existing sstore op (the same one
struct construction emits), for plain and compound (+=, -=, ...) forms.
because structs are shared heap handles, mutations through a function or a
method's implicit self are visible to the caller.

the checker already type-checked field-access targets, so no checker change
was needed.
@kacy kacy merged commit 46095a0 into main May 24, 2026
2 checks passed
@kacy kacy deleted the feat/struct-field-assign branch May 24, 2026 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant