Skip to content

Gecode 7 breaking changes - #274

Draft
zayenz wants to merge 61 commits into
mainfrom
feature/breaking-7
Draft

zayenz wants to merge 61 commits into
mainfrom
feature/breaking-7

Conversation

@zayenz

@zayenz zayenz commented Nov 4, 2026

Copy link
Copy Markdown
Member

Gecode 7 breaking changes, opened as a draft so CI can run. More work is coming on this branch: scoped enums, constant renames, and source cleanup.

What is here

  • CMake is the only build system; Autoconf and the maintained Makefiles are gone.
  • C++23, LLVM 22 formatting, snake_case naming, and clang-tidy checks. See docs/code-style.md and docs/breaking-7.md.
  • A Gecode-native float interval library, Float::Interval, replaces the vendored Boost copy. Bounds match the old code bit for bit, and Gecode has no external dependency for interval arithmetic. changelog.in lists the user-visible changes under 7.0.0.
  • The .zdev records are pull-request-only development records; they are removed before merging.

Validation so far

Local and on x86-64 Linux, not yet in CI:

  • The full float suite including sweeps passes in Release and Debug, with and without MPFR, on arm64 macOS. Debug without MPFR also passes on x86-64 with GCC 15.
  • The rounding probe is exact with AppleClang, LLVM 22, and GCC 14 at -O0, -O2, and -O3.
  • The four float examples give the same solutions and search statistics as before the switch.
  • ctest and uv run misc/check.py all pass.

What CI needs to cover

MSVC cannot be built locally, so CI is the first place this rounding code runs:

  • gecode/float.hh 79-88 (the GECODE_FLOAT_MODE_CONTROL87 and GECODE_FLOAT_DIRECTED_PER_OPERATION predicates) and 184-190 (Mode).
  • gecode/float/rounding.hpp 40-83 (the _control87 mode control and the Control87 fields), 110-135 and 169-222 (the per-operation style), and 162-165 (the volatile barrier used by cl.exe).

build-cmake-windows (cl.exe x64, MPFR off) and build-cmake-windows-vcpkg (cl.exe x64, MPFR on) run them through the check-tagged float tests (DirectedRounding, RoundingScope, MedianRoundingMode, Interval::OutwardRounding, and others). build-cmake-windows-msys2 compiles the MinGW <cfenv> path but runs no tests. cl.exe x86, MSVC ARM64, and clang-cl are not built in CI.

zayenz added 30 commits November 4, 2026 23:17
Zdev-Change-Id: Zb8fefba5e7a09b42d0e065beadd861a00753a972869ec7acfb2afe43b470ec48
Zdev-Change-Id: Z98a6d741c16a08b32d9ee476e47002e03f0e9e3c92a1f1f24728ad5045e0a40d
Zdev-Change-Id: Zd31dae216de3b897b48efca363cdde3dc9e1169a291c9b3d69df0ab05d5d7bdf
Zdev-Change-Id: Ze8474b4acc120d2bc1577f9bdef9ea06be3027629308f96092c1bfd7a26f78da
Zdev-Change-Id: Zb6ff89e9ae27985fdf3c6461cc363f96695cc88df8d607e533279ea8186c577d
Zdev-Change-Id: Z6c1d54a1013fcb118950463f6d78ffb7d4cf39724c457a676aa44bbdf48d06e6
Zdev-Change-Id: Zf903f6efbe2c981cca719755416475e3fbd7c69a5a588158e7f14b97aa3eab86
Zdev-Change-Id: Z43822b3ed57cc2bb7ce4e44e9bbff5df76f14777f613f2de9973d7180a1d263a
Zdev-Change-Id: Z9b51ce509fa929284b7d2b251a6e3566d0e592e27e8fecd6541788b5ea30c00a
Zdev-Change-Id: Zaf7a888eb914257e90f519223bfacc19df79b6e81c1f7fdcfb32ce9d12bda351
Zdev-Change-Id: Zff2d0e6ff1ca5650bb9fab0c1728ac3914074b51eeb8bebc42ffc047126cf906
Zdev-Change-Id: Z29f5a5de8dcaeb9c7e36ad57a6f0f8b6da3a7cbdb6796476784b9a4bfd45dd76
Zdev-Change-Id: Za38592943e829d0d5f0639f54bb56ed7b2929c5997714a009f9fb274ee681e37
Zdev-Change-Id: Z59edca85bfdb7c2701928e5f8262679749d118c3a98e03042baf26879102ba98
Zdev-Change-Id: Z0fbe6f16aff95c9a39ff5430e3bc4f73d4399ffde75421d1d68b5d450ff5b34b
Zdev-Change-Id: Z8d0205e00242e1d712a60c857607727e596c7bd6b3ccc4fc2364387902adf7f3
Zdev-Change-Id: Z2f16dcb32eaf668fab7f831f2cb1ce8bdafd7f6b7b30fa28158406da084ad476
Zdev-Change-Id: Z1b18cdeb9e1612dbc04fc22e901b19d940719bb2db0fa18fa22cfc611f6454e7
Zdev-Change-Id: Zf6a5788af4f4377c88afe00dea48d0affa568605375e155caa867901fc0194fa
Zdev-Change-Id: Zcc7415972bb86bd76ef8e9f9b584d467d0bc2ada68d15385be70b31f02188cb9
Zdev-Change-Id: Zcab7b04117e00a1fae0ceb57e7f08b8ef521927647e15241606b165f7a4eb00e
zayenz added 30 commits November 4, 2026 23:17
…and tracing

Zdev-Change-Id: Zf998dffd1006fff50b23b42adcc1fc221887df0830b7a06397c01341484cce7d
Zdev-Change-Id: Za9107647ee8a830efc792dd21dd7b38a4435f208b81cc6f685607cf606421094
Zdev-Change-Id: Z9c9aa854f95a78c2fbb7e6930e3b50733187129e78720bdcdb1a830d578321ad
Zdev-Change-Id: Ze46b57e15ce9a67e7efe485dea6d83daabcce390a518efec77546b15f77c25ba
… rule

Zdev-Change-Id: Z866642b8abb6de44b9e3b3ba31eea59a5ee562ec86fa93292ba9ce73ab1d698a
Zdev-Change-Id: Z56afa11bcb28b5d7d32224eba272a7b4286f2a418c029a29943d0308e524a4b7
Zdev-Change-Id: Zacee25381114121c984c138d0e6d4b5ea08d4f2a402df57b6bb8042fdd35efb7
Zdev-Change-Id: Z5c93bdc69344351025efb0691a336874ba0c83aa9d6f22ccd43c8899bdd6ce83
Zdev-Change-Id: Zb268ab61d4f33b602d33a4f93319f3c3be8a4b6e269a9423339abf5ba785b42d
Zdev-Change-Id: Z787c6828c0cfac48dcc90508beb51d3d7ae91c0c531da3d8d0f60e6093124d71
Import the approved tasks for modern-classes, empty-arrays (heap
contract), and boost (native float interval spike), and order them
against scoped-enums and source-cleanup.
A bounded static audit, a Debug check-standard run with a scratch zero-size heap check, a Linux UBSan check-standard run, and probes find 16 sites: zero-size heap requests in Action and CHB, TupleSet, Archive, FlatZinc, and the example dictionary; null pointers passed to memcpy by Archive and Space::rrealloc; and zero-byte Region requests. The record gives each site's input, evidence, and fix.

Zdev-Change-Id: Zb2331eac36b65bbb022189c5d2c76a4e6ba05faa4572159869b9f564bd397776
An Action or CHB over an empty array keeps its shared storage, so it stays initialized with size zero, copyable, and an empty Action still accepts a decay change. It no longer requests or frees a zero-size element buffer and no longer posts a recorder propagator.

Zdev-Change-Id: Zd4e6b819bd4f6bcd64b83d6fcd1a94d1bdf26ec1dc2e580c53e90ed98a16a1c9
TupleSet, Archive, Space::rrealloc, the FlatZinc set and regular builtins, the example dictionary, DFA and TupleSet construction from a DFA, and IntSet initializer lists no longer request zero bytes from the heap or a region and no longer pass null pointers to memcpy. Buffers that can now be null are freed only when non-null. An empty initializer list gives the empty IntSet, and a FlatZinc regular constraint with a reversed final-state range treats it as empty.

Zdev-Change-Id: Z739fba34334ff1732238cd5ef32e1903b009ce0fe1dcc1ec967ee3213b53009f
Heap requests now document that allocation sizes are positive, that realloc may grow from zero elements, and that copy needs non-null pointers even for zero elements. Debug builds assert a positive size in Heap::ralloc and rrealloc, and rrealloc no longer accepts zero. Two lint findings are fixed: an intentional copy in the branch tests gets a NOLINT, and an assert in TupleSet finalization documents a count that clang-analyzer cannot follow.

Zdev-Change-Id: Z56a1f083f220acb099fd0bc9a9ac161b74b110451fa021068f6b7b92b1e3acca
Group, PropagatorGroup, BrancherGroup, Pos, LocalHandle, AFC and its subclasses, the variables, VarArray and its subclasses, and ViewArray lose hand-written copy members and empty destructors that only copied members, so the compiler's trivial ones apply. Home keeps its Space& member, gets a defaulted copy constructor, and is no longer copy-assignable; Space is no longer copy-assignable either. VarArray and ViewArray assignment now returns a non-const reference. static_asserts in test/array.cpp keep the handles trivially copyable. AllowedTypes now lists only Float::ScaleView, whose FloatVal member is still non-trivial.

Zdev-Change-Id: Zf784ff784715e79585c52d1beeea68adf93a36f794a04944e8431bf8303b4bcf
The modern-classes record measures what clang-tidy 22's equals-default, equals-delete, default-member-init and special-member-functions checks report per module, with the commands that rerun each count, and lists the manual special-member candidates, every comparison class and const/non-const overload pair with its treatment, and the proposed check options for the following tasks. It also records an ODR violation in BlackBoxProcessSession for a user decision. No sources change.

Zdev-Change-Id: Z1e24d61537414cc8b6d42c9a8f2264dfe244efc2378bfabdeb1e0339de9272b5
Special members that only copy, move, or destroy members are now defaulted, and private undefined members are public = delete. modernize-use-equals-default and modernize-use-equals-delete are enabled in .clang-tidy, and docs/code-style.md states the rule. Cloning constructors, a configuration-dependent constructor, and default constructors of types that are value-initialized stay hand-written with NOLINTNEXTLINE (keep.tsv lists each with its reason). Out-of-line = default definitions move into their classes so the classes stay trivial. The changelog names the source breaks, including that const default-initialization stops compiling for the listed types.

Reproduce on the parent commit, from the source root, with a build/full configured and built like the inventory's (LLVM 22, uv, Homebrew Bison 3.8 and Flex 2.6 on PATH):

  sh .zdev/modern-classes/background/equals-default/reproduce.sh build/full 10

which runs, with D=.zdev/modern-classes/background/equals-default and B=build/full:

  git apply $D/genvarimp.patch
  cmake --build $B --target regenerate
  python3 $D/nolint.py $D/keep.tsv
  python3 $D/run.py $B $B/equals-default 10 equals
  mv $B/equals-default/fixes-*.yaml $B/equals-default/fixes/
  clang-apply-replacements $B/equals-default/fixes
  python3 $D/relocate.py $B 10
  uv run misc/check.py format
  git apply $D/manual.patch
  uv run misc/check.py format

Zdev-Change-Id: Z0f66c3beabdceb05bd6e94ff7f8e64632fe7174275a162647df20afc1f67a826
Support::BitSetData now has a defaulted operator==, and Int::LDSB::Literal replaces its operator< with a defaulted operator<=>. operator!= goes from PropagatorGroup, BrancherGroup, DFA, IntSet, Int::BinPacking::Item, space_allocator, region_allocator, and the integer, set, and float views, where it only negated operator== and C++20 rewrites a != b. TupleSet keeps its operator!=: without it, true != t is ambiguous between its int constructor and its bool conversion. The FloatVal interval comparisons, the minimodel expression builders, the kernel's heterogeneous view templates, and the classes whose order is not member order are unchanged. Int::CachedView::operator== called a nonexistent offset() and now compares base(). New tests compare each converted class, docs/code-style.md states the rule, and the changelog names the removed operators. These are reviewed hand edits per inventory row; build/zdev-impl/modern-classes-004/scripts/rgchecks.sh-style searches for explicit operator calls (rg 'operator\s*(==|!=|<)\s*\(' and '(\.|->)operator') found callers only in the excluded minimodel set relations.

Zdev-Change-Id: Zda6679a68a585cb61e38e90ad2b04ace5898e18e7cf9441b76d21246b9953071
docs/code-style.md now says when a const/non-const pair becomes one explicit-object member: when it removes a duplicated multi-statement body or a const_cast forwarding idiom, and only if every receiver keeps its return type and still compiles. Matrix::operator(), the inventory's one candidate, keeps its pair: the merged template would reach Matrix's members through the derived receiver, so a privately derived matrix that re-exports the operator with using would stop compiling. No code changes.

Zdev-Change-Id: Zc91a9af7d8acb308ae558783a8e4cdbc02beb31aab8135136c8ea1701ebf7986
A scratch prototype replaces gecode/third-party/boost with a double-only Float::Interval and rounding layer ported from Boost's algorithms. It matches HEAD bit for bit on every oracle on arm64 macOS and x86-64 Linux, installs 95 fewer headers, keeps the exported symbols, and runs at the same speed or faster. The study records the measurements with their commands, the wider impacts, the open MSVC and license questions, and a proposed four-part boost-005 split for the decision in boost-004. No tracked source changes.

Zdev-Change-Id: Z0de3a971a1a727a210eb339e51ec7a1ffcf800c751771ea0a17488cf00652899
The user chose the native spike: a Gecode-native Float::Interval and rounding layer with today's switched-mode rounding and no Boost code, keeping HEAD's bounds bit for bit. The interval code is Gecode code under the MIT license, written in Gecode style with Boost.Interval as a temporary bit-for-bit oracle. CI runs through a pull request once local validation is complete.

Zdev-Change-Id: Zd9cb42b240295a4191945c210b40834f1b8cbcabb8986d0c4e8d94a516db3501
Zdev-Change-Id: Zf349f95e671a5733e8aee7f5d0cbfe92fabb46a6ed242794c8d67474eadcb3bb
Float::Interval in gecode/float/interval.hpp provides every interval operation FloatVal uses, written in Gecode style from the mathematics of each operation and licensed like the rest of Gecode. Each public operation opens one Float::Rounding and rounds through RoundingBase, so boost-006's barriers still apply. FloatVal does not use it yet. Focused tests cover outward rounding, singleton and empty intervals, and the comparison truth table; a temporary differential test checks that every result matches the vendored Boost interval bit for bit until the copy is removed.

Zdev-Change-Id: Zf4ce2c26dcc990c3af6acc8d9e1ef911f4d24d5a52a56ec414b369a1284d1ec7
FloatVal now stores Float::Interval, and Float::RoundingBase and Float::Rounding are Gecode classes. The rounding mode is read and set with <cfenv>, or with _control87 for MSVC on x86 and x64. Rounding is a scope that saves the caller's mode and restores it, and it cannot be copied. FloatVal's public operations are unchanged, its comparisons call the native certainly-relations, and it is now trivially copyable. No float header includes Boost any more; the Boost copy stays only for the temporary differential test, which now checks FloatVal against it.

Zdev-Change-Id: Zb0421a288f748b79528fe4e547c738571dac5eb690ffaa00dc5b799f9c222a1c
gecode/third-party and the temporary differential test are gone, together with every reference in the build, checks, Doxygen configuration, and documentation. Gecode no longer installs Boost headers or LICENSE_1_0.txt. Float::ScaleView is now trivially copyable like FloatVal, so the value-parameter check needs no allowed types; FloatVal is still passed by const& by convention.

Zdev-Change-Id: Z93535760ded6e8a1ccd7d757347f7ece740feaa173116d8fc9850bde12deb770
The 7.0.0 entries describe Gecode's own Float::Interval and the removed Boost copy, the API changes of Float::RoundingBase, Float::Rounding, and FloatValImpType, and the trivially copyable FloatVal, whose by-value calling convention changes for the two exported functions that take it by value.

Zdev-Change-Id: Zfb4cd384cd9b0d57890f4ecef2c4ec0803d04137d6a43586a4990458f0cc0537
The full float suite including sweeps passes in Release and Debug, with
and without MPFR, and on x86-64 GCC 15. The rounding probe stays exact with
every compiler, and the float examples give the same solutions and search
statistics as before the switch. No code change was needed.

Zdev-Change-Id: Z713b1451be2f49d6ef218a89bd036d66c72a3f3be1f6c445e714ed48d6f19eb8
Each named enum in the installed headers was probed by scoping it and
recompiling every dependent translation unit. The inventory recommends
scoping 68 of 77 and keeping 9 bit-set enums, proposes the IntPropLevel
operators, and lists candidate constant renames for approval.

Zdev-Change-Id: Zca52d35c5e9251a358f43f108c42a6a6086aacd56e7a9a128b1e9ef5f42d3d5c

This branch has not been deployed

No deployments
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