diff --git a/CHANGELOG.md b/CHANGELOG.md index cca9b5a..9e49101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -308,6 +308,38 @@ arm in the codebase; those found four of the six corrections and are listed unde 5; a single round let the set registry through about one time in three, which is why there are four. +### Documentation + +No behaviour changed here, but one of these corrects a claim that shipped on a NuGet page, so it +ships in this release rather than after it. + +- **⚠️ The pattern-matching guidance was wrong, and the documented snippet did not compile.** Every + page showing a switch over the five range shapes said the compiler enforces the coverage. It does + not: the example warns `CS8509`, which is a build *error* under `TreatWarningsAsErrors` — as in + this repository — so a reader's first copy-paste failed to build while the prose beside it + promised a guarantee. + + Adding a `null` arm does not help, and that is the diagnostic worth recording: the complaint moves + from `'_'` to `'not null'`, which is C# declining to accept the five subtype patterns as covering + a non-null range at all. Exhaustiveness analysis does not reason about a closed class hierarchy, + so the private base constructor buys the runtime guarantee and none of the compile-time one. + + The narrower true statement — no external subtype can be declared, so the five arms are complete + in fact and the discard is unreachable — now appears alongside a discard arm that **throws**. That + is the same rule the library already imposes on its own shape dispatches, for the same reason: a + fallback returning a plausible value is how four of this release's family of bugs stayed hidden. + Corrected in the README, `docs/ranges.md`, `docs/architecture.md`, `CLAUDE.md` and the core + package's own README, which is where it reached NuGet. + +- **The value set table listed six families as having no wrapper arity.** 7.0.0 added all eleven and + completed the set; the table had not moved. The EF package's README also linked twice into + root-README anchors that have never existed there. + +- **A getting-started guide** (`docs/getting-started.md`) — in-memory first, then entity, migration + and a translated query — and the migration guide now covers v7 and v8, having stopped at v3.x + while the package shipped 8.0.0. The README leads with installation and code instead of + positioning, which moves to `docs/why.md`. + ## [7.0.0] — 2026-08-17 Two workstreams land together: the validated-wrapper arities now exist for every value set family diff --git a/CLAUDE.md b/CLAUDE.md index 9ba1c67..5bd3360 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -54,7 +54,7 @@ repo-wide. - `docs/testing.md` — Test organization, patterns, shape-combination matrix ## Critical Rules -- **NEVER** create external subtypes of range base records — the private constructor enforces exhaustive pattern matching; breaking this removes compiler guarantees +- **NEVER** create external subtypes of range base records — the private constructor is what makes the five variants the only ranges that can exist, so a switch over them is complete *in fact*. C# never proved it (exhaustiveness analysis ignores a closed class hierarchy, so a switch expression still warns CS8509 and needs a throwing discard — see `docs/ranges.md#pattern-matching`), which is exactly why breaking the rule is unrecoverable: the guarantee is entirely a runtime one, and nothing would fail at compile time - **ALWAYS** preserve RangeSet's invariant (sorted, disjoint, non-adjacent, no empties) on every code path that constructs or mutates a set - **Do NOT** add new range types without verifying the generic engines cover them — a new type must implement `IRange` + `IRangeFactory` with the five sealed variants; the engines in `Internals/` dispatch per shape through the structural interfaces - **Ranges — NEVER decide a binary operation by switching on the receiver's shape.** A binary relation is a function of the *pair* of shapes: read the bounds it actually compares, or switch on `(left, right)`. Switching on the receiver and handling the operand's shapes in an inner switch has now produced the same bug four times — `IsAdjacentTo` (fixed 6.2.1), `IsStrictlyLeftOf` and `Except` (both 7.0.0), and `RangeSet.Except(TRange)` with an infinity operand (8.0.0). The tell is an inner switch with a `_` fallback: it answers `false`, or returns the receiver unchanged, for exactly the operand shapes nobody wrote an arm for. **This applies to value-producing operations, not just predicates** — `Except` returned a well-formed range holding the wrong values, which is the harder one to notice. It hides well because the EF translation is correct, so the disagreement is between memory and the database rather than inside either. `ShapeMatrixParityTests` asks PostgreSQL for every ordered shape pair and is the check that catches it diff --git a/src/CodoMetis.ValueRanges.EFCore.PostgreSQL/CHANGELOG.md b/src/CodoMetis.ValueRanges.EFCore.PostgreSQL/CHANGELOG.md index e15977e..79cf87a 100644 --- a/src/CodoMetis.ValueRanges.EFCore.PostgreSQL/CHANGELOG.md +++ b/src/CodoMetis.ValueRanges.EFCore.PostgreSQL/CHANGELOG.md @@ -19,6 +19,12 @@ three bugs in 7.0.0, the disagreement was between the database and memory rather — so `RangeSet.Infinite.Except(range)` evaluated server-side has always answered the empty set. See `CodoMetis.ValueRanges` 8.0.0 for the in-memory fix that brings the two back into step. +### Documentation + +- **This README linked twice into root-README anchors that have never existed**, so both links landed + on the wrong page from the NuGet listing. They now point at `docs/efcore.md`, where the content + lives, and the package documentation gains a link to the new getting-started guide. + ## [7.0.0] — 2026-08-17 ### Added diff --git a/src/CodoMetis.ValueRanges/CHANGELOG.md b/src/CodoMetis.ValueRanges/CHANGELOG.md index 08be0ef..eea9793 100644 --- a/src/CodoMetis.ValueRanges/CHANGELOG.md +++ b/src/CodoMetis.ValueRanges/CHANGELOG.md @@ -36,6 +36,16 @@ covers all four packages, which share one version number and release together. These paths sit behind the callers' guards and are unreachable; if a change breaks a guard, the first test to reach it now names the missing pair. +### Documentation + +- **⚠️ This package's README claimed pattern matching over the five shapes has compiler-enforced + coverage. It does not.** A switch expression over the variants warns `CS8509` — a build error + under `TreatWarningsAsErrors` — and adding a `null` arm only moves the complaint to `'not null'`, + because C# exhaustiveness analysis does not reason about a closed class hierarchy. The private + base constructor still guarantees no external subtype exists, so the five arms are complete in + fact and a discard is unreachable; it now says that, and says to make the discard throw. See the + root changelog for the full note. + ## [7.0.0] — 2026-08-17 ### Added