Commit Graph
5 Commits
Author SHA1 Message Date
Chris Tate 82ba2ef6ed Merge main 2026-10-27 23:02:33 -05:00
Chris Tate c2ebd0d4a4 Check the elements a new Set takes from InlineArray field reads
`new Set([a, b])`, where `a` and `b` are reads of the same InlineArray
field, gave a Set of size 2 where Node gives size 1: each read may give
another array, and the source proof checked Set elements only when they
were added with `add`. It now reports SC7009 when the seed of a new Set,
or the values of a Map that become a Set (`new Set(map.values())`), may
hold a field's array.
2026-10-27 21:35:51 -05:00
Chris Tate 21fa3a8ec7 Merge main 2026-10-27 20:22:19 -05:00
Chris Tate 723975d01c Prove that the arrays InlineArray fields hold are never written
The constructor copies the array it is passed into the instance, and
other reads of the field give a new array over the elements, while under
Node.js the field holds that array itself. The contract check now proves
the two agree, and reports SC7009 where it cannot:

- The arrays fields hold are never written. A whole-program graph of the
  places arrays are held (locals, parameters, results, class and record
  fields, and the elements of arrays, Maps and Sets by where those are
  held) follows every array a field read may give, and reports a write to
  one, or one that reaches a dynamic value, a call through a function
  value or a library call other than printing and JSON.stringify without
  a replacer. Functions that return their argument give each caller its
  own argument back. The report names the field read.
- The array passed to the constructor is one nothing else keeps: a new
  array (a literal, a copy, or the result of a function that returns only
  such arrays or its argument), a local array at its last use (after calls
  that only read it or write it in place, or in a loop that then assigns
  the local a new array), a parameter whose every caller passes such an
  array, an array a field already holds, or a const array that is never
  written, which is then followed like a field's.

The review fixes from before stay: `new` evaluates its arguments into
locals unless they are all locals and constants, so that the allocation
reads the length after every argument has run; the constructor uses the
array parameter only to store it; and the dynamic view of an instance
reads the field as an array of its elements.
2026-10-27 02:38:15 -05:00
Chris Tate acf4c39f73 Keep the elements of InlineArray fields in their instances 2026-10-26 22:38:40 -05:00