Skip to content

Guard reduceTableDefinitionAccessor against ambiguous table literals - #152

Merged
Unisay merged 1 commit into
mainfrom
issue-140/table-accessor-guard
Jul 4, 2026
Merged

Guard reduceTableDefinitionAccessor against ambiguous table literals#152
Unisay merged 1 commit into
mainfrom
issue-140/table-accessor-guard

Conversation

@Unisay

@Unisay Unisay commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Closes #140.

Summary

The Lua optimizer rule reduceTableDefinitionAccessor folds a field access into a table literal, rewriting { foo = 1, bar = 2 }.foo to 1. It searched only name-value rows (TableRowNV) and took the first match, falling back to Nil.

Two shapes broke that:

  • A string-keyed row (["foo"] = 1, a TableRowKV) for the accessed field is invisible to the name lookup, so the rule folded the access to Nil and dropped the real value.
  • On a duplicate field name, Lua's constructor keeps the last assignment while the first-match lookup returns the earliest, so the rule could fold to the wrong value.

Neither shape is produced by the current codegen, so this is a latent miscompile rather than a live one. The rule now fires only when the constructor is unambiguous: every row is a name-value row and no field name repeats. Otherwise it leaves the expression untouched.

Changes

  • lib/Language/PureScript/Backend/Lua/Optimizer.hs: guard the rewrite with an all-name-value check and a duplicate-name check; the Haddock explains both hazards.
  • test/Language/PureScript/Backend/Lua/Optimizer/Spec.hs: the rule had no test before. Three cases now pin it: the fold still fires on an unambiguous literal, and it declines on a key-value row and on duplicate names (both were red against the old rule).

Test plan

  • cabal test all --test-show-details=direct passes
  • The two decline tests fail against the pre-fix rule (confirmed red) and pass after
  • fourmolu and hlint clean on the touched files, warning-free build

reduceTableDefinitionAccessor rewrote `{ foo = 1 }.foo` to `1` by scanning
name-value rows and taking the first match, falling back to Nil. Two shapes
broke that: a string-keyed row (`["foo"] = 1`) for the accessed field is
invisible to the name lookup, so the access folded to Nil and dropped the
real value; and on a duplicate field name Lua keeps the last assignment
while the first-match lookup returns the earliest. Neither is emitted by the
current codegen, so this is a latent miscompile, not a live one.

The rule now fires only when the constructor is unambiguous (every row is a
name-value row and no field name repeats) and otherwise leaves the
expression untouched. The rule had no test before; three cases pin it now,
two of them red against the old rule (#140).

Claude-Session: https://claude.ai/code/session_01Bfeu6sp2zVhvuQTnEzYpNG
@Unisay
Unisay requested a review from Copilot July 4, 2026 08:05
@Unisay Unisay self-assigned this Jul 4, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the Lua AST optimizer by making reduceTableDefinitionAccessor refuse to fold table-literal field accesses when the table constructor could be ambiguous, preventing latent miscompiles if such shapes ever appear in generated Lua.

Changes:

  • Guard reduceTableDefinitionAccessor so it only fires when all rows are TableRowNV and there are no duplicate field names.
  • Add an Hspec test group covering: (1) successful fold on an unambiguous literal, (2) decline when a TableRowKV row is present, and (3) decline on duplicate names.
  • Add a changelog fragment documenting the fix and the two hazard cases (KV rows and duplicates).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
lib/Language/PureScript/Backend/Lua/Optimizer.hs Adds explicit guards and Haddock rationale so the fold only happens for unambiguous name-value-only constructors without duplicate keys.
test/Language/PureScript/Backend/Lua/Optimizer/Spec.hs Introduces focused tests that lock in the intended “fold vs decline” behavior for the rule.
changelog.d/20260704_120000_unisay_table_accessor_guard.md Records the behavior change and why it matters (avoids folding to nil or the wrong value).

@Unisay
Unisay marked this pull request as ready for review July 4, 2026 08:09
@Unisay
Unisay merged commit b14de98 into main Jul 4, 2026
3 checks passed
@Unisay
Unisay deleted the issue-140/table-accessor-guard branch July 4, 2026 08:11
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.

reduceTableDefinitionAccessor ignores TableRowKV rows and duplicate fields (folds to Nil)

2 participants