Repository navigation
feat(array): const-transport laws, dataclass fields and operator== for std::array - #237
Draft
jhaag-skylabs-ai wants to merge 2 commits into
Draft
jhaag-skylabs-ai wants to merge 2 commits into
jhaag-skylabs-ai wants to merge 2 commits into
Conversation
CI summary (Details)Active Repos
|
| Repo | Job Branch | Job Commit |
|---|---|---|
| ./ | main | 781c507 |
| fmdeps/BRiCk/ | main | cb506b7 |
| fmdeps/auto/ | main | 4cba1bf |
| fmdeps/auto-docs/ | main | 918aa33 |
| bluerock/NOVA/ | skylabs-proof | 9587b7c |
| bluerock/bhv/ | skylabs-main | 42f282b |
| fmdeps/brick-libgtest/ | main | 495b855 |
| fmdeps/ci/ | main | b480641 |
| vendored/elpi/ | skylabs-master | c0b9653 |
| vendored/flocq/ | skylabs-master | cf9cc84 |
| vendored/rocq/ | skylabs-master | 7c6eef8 |
| fmdeps/rocq-agent-toolkit/ | main | 21eb550 |
| vendored/rocq-elpi/ | skylabs-master | 7dee592 |
| vendored/rocq-equations/ | skylabs-main | 9cf8471 |
| vendored/rocq-iris/ | skylabs-master | a7af9f7 |
| vendored/rocq-stdlib/ | skylabs-master | 00897b3 |
| vendored/rocq-stdpp/ | skylabs-master | 0c5e505 |
| fmdeps/skylabs-fm/ | main | 4cd041a |
| vendored/vsrocq/ | skylabs-main | 03db19e |
Changes in Warnings or Errors
| Before | New | Fixed | After | |
|---|---|---|---|---|
| Errors | 0 | 0 | 0 | 0 |
| Warnings | 77 | 0 | 78 |
Performance
| Relative | Master | MR | Change | Filename |
|---|---|---|---|---|
| +0.11% | 197274.4 | 197496.5 | +222.1 | total |
| +0.10% | - | 205.3 | +205.3 | ├ newly appeared files (2) |
| +0.01% | 197274.4 | 197291.2 | +16.8 | └ common files |
| -0.00% | 49381.4 | 49381.4 | -0.0 | ├ translation units |
| +0.01% | 147893.0 | 147909.8 | +16.8 | └ proofs and tests |
Full Results
| Relative | Master | MR | Change | Filename |
|---|---|---|---|---|
| -0.18% | 752.4 | 751.1 | -1.3 | fmdeps/brick-libcpp/rocq-brick-libstdcpp/test/array/test_cpp_proof.v |
| +174.47% | 10.2 | 28.0 | +17.8 | fmdeps/brick-libcpp/rocq-brick-libstdcpp/proof/array/pred.v |
| +0.11% | 197274.4 | 197496.5 | +222.1 | total |
| +0.10% | - | 205.3 | +205.3 | ├ newly appeared files (2) |
| +0.01% | 197274.4 | 197291.2 | +16.8 | └ common files |
| -0.00% | 49381.4 | 49381.4 | -0.0 | ├ translation units |
| +0.01% | 147893.0 | 147909.8 | +16.8 | └ proofs and tests |
jhaag-skylabs-ai
marked this pull request as draft
October 27, 2026 17:31
CI summary (Details)Active Repos
|
| Repo | Job Branch | Job Commit |
|---|---|---|
| ./ | main | 781c507 |
| fmdeps/BRiCk/ | main | 2ce8ed0 |
| fmdeps/auto/ | main | a24e391 |
| fmdeps/auto-docs/ | main | 918aa33 |
| bluerock/NOVA/ | skylabs-proof | 02f6828 |
| bluerock/bhv/ | skylabs-main | e235791 |
| fmdeps/brick-libgtest/ | main | 495b855 |
| fmdeps/ci/ | main | b480641 |
| vendored/elpi/ | skylabs-master | c0b9653 |
| vendored/flocq/ | skylabs-master | cf9cc84 |
| vendored/rocq/ | skylabs-master | 7c6eef8 |
| fmdeps/rocq-agent-toolkit/ | main | 53fde9a |
| vendored/rocq-elpi/ | skylabs-master | 7dee592 |
| vendored/rocq-equations/ | skylabs-main | 9cf8471 |
| vendored/rocq-iris/ | skylabs-master | 285745a |
| vendored/rocq-stdlib/ | skylabs-master | 00897b3 |
| vendored/rocq-stdpp/ | skylabs-master | ba29dba |
| fmdeps/skylabs-fm/ | main | ffa586f |
| vendored/vsrocq/ | skylabs-main | 03db19e |
Changes in Warnings or Errors
| Before | New | Fixed | After | |
|---|---|---|---|---|
| Errors | 0 | 0 | 0 | 0 |
| Warnings | 76 | 0 | 77 |
Performance
| Relative | Master | MR | Change | Filename |
|---|---|---|---|---|
| +0.11% | 199093.8 | 199317.9 | +224.1 | total |
| +0.10% | - | 208.8 | +208.8 | ├ newly appeared files (2) |
| +0.01% | 199093.8 | 199109.1 | +15.3 | └ common files |
| +0.00% | 49396.3 | 49396.3 | +0.0 | ├ translation units |
| +0.01% | 149697.5 | 149712.8 | +15.3 | └ proofs and tests |
Full Results
| Relative | Master | MR | Change | Filename |
|---|---|---|---|---|
| -0.17% | 760.7 | 759.4 | -1.3 | fmdeps/brick-libcpp/rocq-brick-libstdcpp/test/array/test_cpp_proof.v |
| +177.27% | 10.3 | 28.5 | +18.2 | fmdeps/brick-libcpp/rocq-brick-libstdcpp/proof/array/pred.v |
| +0.11% | 199093.8 | 199317.9 | +224.1 | total |
| +0.10% | - | 208.8 | +208.8 | ├ newly appeared files (2) |
| +0.01% | 199093.8 | 199109.1 | +15.3 | └ common files |
| +0.00% | 49396.3 | 49396.3 | +0.0 | ├ translation units |
| +0.01% | 149697.5 | 149712.8 | +15.3 | └ proofs and tests |
…r std::array `array/pred.v` connects `std.array.R` to the other shapes in which a `std::array` reaches a proof: - Const transport. `R_wp_const` proves `wp_const tu from to p (T ty n) Q` from `R_gen ty n from (primR ty from ∘ f)` for the `tu` that `wp_const` is evaluated in, given that `tu` lays out `std::array<ty, n>` as libstdc++ does (`struct_ok`: no bases, no vtable, one non-mutable field `_M_elems : ty[n]`, `0 < n`, `ty` an unqualified value type). It reads the layout from that `tu`, so it has no `type_table_le` premise and applies in every client. `array_sliceR_wp_const` is the same for the bare `ty[sz]` field. Both are registered as hints (`[CANCEL]` for the slice, `[BWD]` over `Vint` elements for `R`). - Element-wise ownership. Value or aggregate initialization leaves a `val`-indexed `array_sliceR ty i j (primR ty q) vs`; the forward hint `array_sliceR_fold_Vint` rewrites it to the `Z`-indexed slice that `std.array.R` wants when `vs` is a concrete list of `Vint`s. - Dataclass fields. `cpp.class … dataclass` now models a `std::array<ty, n>` field as `list M` with representation `std.array.fieldR`, which unfolds to `std.array.R_gen`. - `spineR` is `Timeless`, needed for `R` as a dataclass field. `array/spec.v` adds an (assumed) `operator==` specification, stated as equality of the element models and excluding floating-point elements, and makes `repfor` a `Hint Extern` instead of an instance: as an instance it elaborated `list ?M` before `?M` was known and failed on a universe constraint, so `cpp.spec … default` found no `Rep` for `std::array`. Motivation: ProveCode test proofs on `const std::array<unsigned char, 16>` locals had to restate these laws by hand in each proof (about 80 lines), and those proofs reached 13 GiB. `test/array/laws.cpp` and `laws_cpp_proof.v` exercise each law with plain `go`: a dataclass with an array field, a `const` array local, value initialization followed by `fill`, `==`, and `!=` (rewritten to `!(a == b)` in C++20). `test/dune.inc` is regenerated by `dune-gen.sh`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fold hint - operator_eq now requires eq_is_model_eq ty = true: integral, character and bool elements only. Pointer elements (== needs ptr_comparable), enumerations and classes (overloadable ==) and floating point are excluded, since for them == is not equality of the model. - Drop array_sliceR_Vint, a duplicate of auto's array_sliceR_fmap. - Derive Timeless for spineR instead of proving it by hand. - array_sliceR_fold_Vint_F only fires on a slice at a std::array's _M_elems field, not on every Vint slice; add a negative test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jhaag-skylabs-ai
force-pushed
the
jhaag/std-array-laws
branch
from
October 27, 2026 19:31
f831190 to
84eb992
Compare
CI summary (Details)Active Repos
|
| Repo | Job Branch | Job Commit |
|---|---|---|
| ./ | main | 781c507 |
| fmdeps/BRiCk/ | main | 2ce8ed0 |
| fmdeps/auto/ | main | ff6306c |
| fmdeps/auto-docs/ | main | 918aa33 |
| bluerock/NOVA/ | skylabs-proof | 02f6828 |
| bluerock/bhv/ | skylabs-main | e235791 |
| fmdeps/brick-libgtest/ | main | 495b855 |
| fmdeps/ci/ | main | b480641 |
| vendored/elpi/ | skylabs-master | c0b9653 |
| vendored/flocq/ | skylabs-master | cf9cc84 |
| vendored/rocq/ | skylabs-master | 7c6eef8 |
| fmdeps/rocq-agent-toolkit/ | main | 53fde9a |
| vendored/rocq-elpi/ | skylabs-master | 7dee592 |
| vendored/rocq-equations/ | skylabs-main | 9cf8471 |
| vendored/rocq-iris/ | skylabs-master | 285745a |
| vendored/rocq-stdlib/ | skylabs-master | 00897b3 |
| vendored/rocq-stdpp/ | skylabs-master | ba29dba |
| fmdeps/skylabs-fm/ | main | ffa586f |
| vendored/vsrocq/ | skylabs-main | 03db19e |
Changes in Warnings or Errors
| Before | New | Fixed | After | |
|---|---|---|---|---|
| Errors | 0 | 0 | 0 | 0 |
| Warnings | 76 | 0 | 77 |
Performance
| Relative | Master | MR | Change | Filename |
|---|---|---|---|---|
| +0.11% | 199110.0 | 199337.8 | +227.7 | total |
| +0.10% | - | 208.8 | +208.8 | ├ newly appeared files (2) |
| +0.01% | 199110.0 | 199129.0 | +18.9 | └ common files |
| -0.00% | 49396.3 | 49396.3 | -0.0 | ├ translation units |
| +0.01% | 149713.8 | 149732.7 | +18.9 | └ proofs and tests |
Full Results
| Relative | Master | MR | Change | Filename |
|---|---|---|---|---|
| +177.32% | 10.3 | 28.5 | +18.2 | fmdeps/brick-libcpp/rocq-brick-libstdcpp/proof/array/pred.v |
| +0.11% | 199110.0 | 199337.8 | +227.7 | total |
| +0.10% | - | 208.8 | +208.8 | ├ newly appeared files (2) |
| +0.01% | 199110.0 | 199129.0 | +18.9 | └ common files |
| -0.00% | 49396.3 | 49396.3 | -0.0 | ├ translation units |
| +0.01% | 149713.8 | 149732.7 | +18.9 | └ proofs and tests |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Laws that connect
std.array.Rto the shapes in which astd::arrayreaches a proof: const transport, element-wise ownership after initialization, andcpp.class … dataclassfields. Also anoperator==spec. ProveCode test proofs onconst std::array<unsigned char, 16>locals currently restate the const-transport part by hand in each proof (about 80 lines), and those proofs reached 13 GiB.Laws (
proof/array/pred.v):array_sliceR_wp_const(registered as[CANCEL]): forprim_const_ok ty(an unqualified value type),p |-> array_sliceR ty 0 n (primR ty from ∘ f) xsand a continuation from thetoslice givewp_const tu from to p (Tarray ty sz) Q, withn = sz.array_sliceR_wp_const_foldis the per-element induction behind it.R_wp_const:p |-> R_gen ty n from (primR ty from ∘ f) xsand a continuation fromR_gen ty n to …givewp_const tu from to p (T ty n) Q, providedtu.(types) !! N ty n = Some (Gstruct st)andstruct_ok ty n st: no bases, no vtable, exactly one non-mutable field_M_elems : ty[n],0 < n,prim_const_ok ty.R_wp_const_Vint(registered as[BWD]):R_wp_constforVintelements, with the layout premises as=[Vm?]=>side conditions, looked up the same way as BRiCk'swp_const_named_struct.array_sliceR_fold_Vint(registered as[FWD]): at astd::array's element storagep ,, elems ty n,array_sliceR ty i j (primR ty q) vsbecomesarray_sliceR ty i j (fun x => primR ty q (Vint x)) xswhenints_of_vals vscomputes toSome xs. This covers value or aggregate initialization (a{},a{1,2,3,4}). Slices elsewhere, such as builtin arrays, are left alone. The equivalence behind it is auto'sarray_sliceR_fmap.TimelessforspineR(derived inspec.v), andstd.array.fieldRwith two Elpi rules forskylabs.synth.db: astd::array<ty, n>field of a dataclass gets modellist Mand representationfieldR ty n Relem, which unfolds toR_gen ty n q (Relem q).proof/array/spec.v:operator_eq:a == breturnsbool_decide (xs = ys), with\require eq_is_model_eq ty = true: integral (Tnum), character (Tchar_) andboolelements only (see below). This is an assumed specification, like the rest of the file; it is not checked against libstdc++'sstd::equal/__builtin_memcmpbody.!=needs no spec of its own because C++20 rewrites it to!(a == b).repforis now aHint Externinstead of an instance. As an instance it elaboratedlist ?Mbefore?Mwas known and failed with a universe error, socpp.spec … defaultfound noRepforstd::array.Why
R_wp_consthas notype_table_lepremise:const.CONSTrelates the library's translation unit to the client's bytype_table_le, and that relation is false between real units. brick-libgtest's TODO.md (U3) measured a library table of 8,389 entries against a client table of 11,525: 0 incompatible entries and 1 missing one (std::align_val_t), sotype_table_lewasfalse. Which declarations a unit keeps depends on what it references, so the premise can fail because of unrelated client code. These laws instead read the class layout from thetuin whichwp_constis evaluated (tu.(types) !! N ty n) and check it withstruct_ok. They are proved, not assumed, so they hold for every client whose unit has the libstdc++ layout.Tests (
test/array/laws.cpp,laws_cpp_proof.v), each proved with plainverify_spec; goand no proof-specific hints:HolderByte: a dataclassHolderwith anarray<unsigned char, 16>field.ConstLocal: aconst array<unsigned char, 4>local, which goes throughwp_make_constandwp_make_mutable.ZeroThenFill:a{}followed bya.fill(v).EqandNe:==onarray<unsigned char, 16>and!=onarray<int, 3>.cpp.spec … defaultforEq, which checks theRepForfix.fold_Vint_ex: the fold hint under an existential, and aFailcheck that it does not fire on a slice outside astd::array.Built after rebasing on main, with BRiCk and auto at their
main:proof/array/{spec,pred}.vo,test/array/laws_cpp_proof.vo, andtest/array/test_cpp_proof.vo, the only other file that imports the array specs.test/dune.incis regenerated bydune-gen.sh.Revision (f831190)
array_sliceR_Vintis gone: it duplicated auto'sarray_sliceR_fmap, which the fold law now uses.spineR_timelessis gone:Timelessis derived with the otherspineRinstances (#[only(…,timeless)] derive spineR).operator_eqis restricted to element types whose==is equality of the model (next section).[FWD]fold hint only fires on a slice atp ,, elems ty n, not on every concrete list ofVints in anyarray_sliceR. All tests pass unchanged.operator==scopeThe spec states the result as
bool_decide (xs = ys), so it is only sound when the element==is equality of the element model.eq_is_model_eq tyaccepts the integral, character andbooltypes (aftererase_qualifiers). Their==is builtin and cannot be overloaded, and theirprim_BundledRepmodel is injective. Everything else is excluded:NaN != NaN,-0.0 == 0.0;==needsptr_comparable, and distinct pointers (one past the end of one object, the start of the next) can compare equal;==can be overloaded. Enumerations also have noBundledRepin auto.A version for element types with a proved
==spec (anElemEq ty eqbpremise) is a separate follow-up.Known gaps
char,bool, pointers or enumerations get no const hints.R_wp_const_Vintand the fold law are forVintonly. The fold law has to read the model back fromvals (ints_of_vals), which needs a decoder, and auto only has encoders (prim_BundledRep Vint/Vchar/Vbool/Vptr).R_wp_constitself is generic in the element encoding, but nothing registers it as a hint for other encodings.Overlap with auto#592 and auto#537
auto#592 (open,
wp_constsupport forarray_sliceR) addswp_const_array_sliceR_C, a general[CANCEL]hint forwp_constatTarray ty noverarray_sliceR ty 0 n R xs, for anyAsCFractionalelement representation. Each element goes to the existing per-typewp_consthints. This is the hint auto#537 (nowp_consthint for array-typed members) asks for. Once #592 lands:array_sliceR_wp_const,array_sliceR_wp_const_foldandarray_sliceR_wp_const_Cbecome redundant. #592 covers the same goal for every element type, not onlyprimRelements.R_wp_constandR_wp_const_Vint_Bare probably redundant: withspineRunfolded, BRiCk'swp_const_named_struct_Creaches the_M_elemsfield and #592 handles the array. This has not been tested.R_wp_const_Vintis[BWD]because ownership is often split by the time the array is made mutable again, and it is not checked whether the cancellation route copes with that.array_sliceR_fold_Vint,fieldRand the dataclass rules, andoperator_eqare unaffected.This PR does not depend on #592. #592 also comments out
VcRwDefs.wp_init_initlist_prim_array_implicit_B, which could change the shapea{}leaves behind.ZeroThenFillis the test to rerun against it.Revision build (pointed targets, from the workspace root, 10 GiB cap):
proof/array/pred.vo,test/array/laws_cpp_proof.voandtest/array/test_cpp_proof.voall pass.🤖 Generated with Claude Code