Skip to content

Box unboxed-rep values reaching value targets at more use-sites#2943

Merged
mzagozen merged 2 commits into
mainfrom
fix-value-target-box
Jun 18, 2026
Merged

Box unboxed-rep values reaching value targets at more use-sites#2943
mzagozen merged 2 commits into
mainfrom
fix-value-target-box

Conversation

@mzagozen

Copy link
Copy Markdown
Collaborator

This closes #2942. The initial fix was only limited to the crash I found in one of the applications:

 fixassign env t e
   | Just t' <- unboxedRepType t    = forceUnbox env t' e
+  | Box{} <- e                     = e
+  | Just rt <- exprUnboxedRep env e = Box rt e
   | otherwise                      = e

But then my robot continued the search and came up with more edge cases

Unboxable primitives (u64/int/float) are now carried unboxed; each use-site that needs a boxed value must insert the Box. That insertion existed for fixarg/fixreturn/boxValueExpr but was missing elsewhere, so a raw int reached a boxed slot and the first virtual access dereferenced it, causing a runtime crash.

  • fixassign: box a raw unboxed-rep RHS into a value/?value target. Missing box when assigning fixed-size int to value #2942
  • Cond: box then/else branches when the join type is not unboxable.
  • IsInstance: box the operand ($ISINSTANCE derefs $class).
  • BinOp And/Or: box both operands ($AND/$OR call bool on them).
  • exprUnboxedRep: treat a processed And/Or as already boxed, else a fallback re-boxes it (toB_u64(B_u64), a compile error).

mzagozen added 2 commits June 17, 2026 21:22
Unboxable primitives (u64/int/float) are now carried unboxed; each
use-site that needs a boxed `value` must insert the `Box`. That
insertion existed for fixarg/fixreturn/boxValueExpr but was missing
elsewhere, so a raw int reached a boxed slot and the first virtual
access dereferenced it, causing a runtime crash.

Boxing.hs:
- fixassign: box a raw unboxed-rep RHS into a value/?value target.
- Cond: box then/else branches when the join type is not unboxable.
- IsInstance: box the operand ($ISINSTANCE derefs $class).
- BinOp And/Or: box both operands ($AND/$OR call __bool__ on them).
- exprUnboxedRep: treat a processed And/Or as already boxed, else a
  fallback re-boxes it (toB_u64(B_u64), a compile error).
One self-contained regression_auto program per fixed use-site; each exits 0
on success and crashes (misaligned address) on the unfixed compiler:

- 179 fixassign: unboxed local/global -> value/?value field
- 180 Cond: unboxed branch of a conditional with non-unboxable join
- 181 BinOp And/Or: unboxed operand (also the value-argument / no-double-box path)
- 182 IsInstance: unboxed operand of isinstance
@mzagozen mzagozen marked this pull request as ready for review June 18, 2026 05:18
@mzagozen

Copy link
Copy Markdown
Collaborator Author

@sydow can you please take a look? I also included regression programs that crash on main.

@sydow

sydow commented Jun 18, 2026 via email

Copy link
Copy Markdown
Collaborator

@mzagozen mzagozen merged commit c10f590 into main Jun 18, 2026
93 of 94 checks passed
@mzagozen mzagozen deleted the fix-value-target-box branch June 18, 2026 06:24
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.

Missing box when assigning fixed-size int to value

2 participants