Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>` + `IRangeFactory<TRange, T>` 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
Expand Down
6 changes: 6 additions & 0 deletions src/CodoMetis.ValueRanges.EFCore.PostgreSQL/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions src/CodoMetis.ValueRanges/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading