Give collections the same sorts as scalars - #90
Draft
HowardvanRooijen wants to merge 1 commit into
Draft
HowardvanRooijen wants to merge 1 commit into
HowardvanRooijen wants to merge 1 commit into
Conversation
Only an int collection could be solved. Every other element type declared a Z3 array whose domain or range contradicted how its elements were constrained and read back: bool and string were indexed by their own type while every element is read with an integer index; long, DateTime, float, double and decimal declared bit-vector or floating-point ranges while their constraints translated to integer and real terms. Only the int row was consistent with itself. The collection mapping is gone. There is now one function from CLR type to sort, and a collection is an array from Int to whatever that function says a scalar of the element type is. The two cannot disagree because there is nothing else to consult - reverting a single row of the shared mapping fails scalar and collection tests together. The array-element read for short gets the checked cast the scalar arm has had since #63; the arm was unreachable until now and is covered for the first time. Object collections - Holder[] with scalar properties - remain unusable in every shape, which is a different mechanism raised as #89; their per-property arrays are declared through the same mapping so that part is settled. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Fixes #64.
The defect
Collection symbols only worked with
intelements. Every other element type built a Z3 arraywhose domain or range contradicted how its elements were constrained and read back, and the
theorem threw a raw
Z3Exceptionabout sorts:The array sort mapping - which existed in two identical copies - paired a domain and a range per
element type:
intIntIntshortIntBitVec 16Intlong,DateTimeIntBitVec 64boolBoolBoolstringStringBitVec 16float,decimalRealFloatingPoint 8 24decimalcould never have fitteddoubleRealFloatingPoint 11 53Measured before the change, every non-
inttype failed in one of two places depending on theconstraint - during translation when it named a constant of the element type, or in the
marshalling loop when the elements were left free - which is why the tests cover both shapes.
boolandstringfailed in the same place either way, because the index is supplied by thelibrary rather than by the constraint.
The change
The collection mapping is deleted. There is one function from CLR type to sort, and a
collection is an array from
Intto whatever that function says a scalar of the element typeis.
The scalar path calls it for its constant; both collection paths call it for their range and use
Intfor their domain. That is the actual fix, not the corrected table: the defect was twomappings that could drift, and now there is nothing to drift. The mutation matrix below is the
evidence - reverting one row of the shared mapping fails scalar and collection tests together.
The rest is 54 net lines removed, three
NotSupportedExceptionmessages preserved exactly, andone more thing:
The array-element read for
shortgets the checked cast the scalar arm has had since #63.That arm was unreachable until this change - noted on #64 at the time, with the reason - and is
covered for the first time here, including the overflow pin.
Measured after the change
Every element type, both shapes, arrays and
List<T>:long[9000000000, -9000000000]exact[0, 0]bool[true, false][false, false]double[1.5, -2.25]; relational[3.5, 7][0, 0]float[1.5, 0.1]- the array half of #54, observable for the first time[0, 0]decimal[1.5, 0.1];decimal.MaxValueexact, 29 significant digits[0, 0]string["abc", ""]["", ""]DateTimeUtc1601-01-01Z, file time zero, kindUtcshort[4, 6]through arithmetic; out-of-range →OverflowException[0, 0]decimal.MaxValueis the load-bearing one. No floating-point sort Z3 offers could return itexactly, so it passing is direct evidence the range is an unbounded
Realrather than a widerfloat that would pass the ordinary values and lose precision quietly on large ones.
What is deliberately not changed
Object collections stay broken, and are now #89. A
Holder[]whose elements have scalarproperties fails in every shape - constraining
t.Items[0].Valuedies in the visitor(
Unknown parameter encountered: Value), and leaving the elements free dies in the marshaller(
requires subEnv.Expr to be non-null). Measured before and after this change; identical.It is a different mechanism from #64: the library builds one per-property array for these and
then neither end of the pipeline can use it, and
Environment.IsArray- the flag that wouldroute either end - is written and never read. The per-property arrays now go through the shared
mapping, so the sort side is settled for whoever finishes it. The library's own error message,
Only one level of object collections is currently supported, promises something that does notwork; #89 says so.
#87 applies to elements too. A
shortelement is an unboundedIntexactly as ashortscalar is, so Z3 can still pick a value the element cannot hold. The checked read makes that loud
rather than wrong, which is the same trade-off #63 made and for the same reason.
Tests
214 → 225, in
CollectionSymbolTests.cs. The nine characterisation pins that asserted the oldfailures are replaced by round-trips, and the three #55 tests - which until now could only
observe that fix in which type the failing cast named - become positive tests that reverting
#55 fails outright.
Solve_LongArraySymbol_RoundTripsEveryElement/..LongList../..LongArrayInAPublicField..Int32so a narrowing read cannot pass by accidentSolve_BoolArraySymbol../..BoolList..Solve_StringArraySymbol_RoundTripsEveryElement""so a constrained element is distinguishable from a free oneSolve_DoubleArraySymbol../..WithRelationalConstraints..inttests use, now available to every typeSolve_FloatArraySymbol_RoundTripsEveryElementSinglearmSolve_DecimalArraySymbol_RoundTripsEveryElement/..AtFullPrecision/..DecimalList..decimal.MaxValueproves it is not a floatSolve_DateTimeArraySymbol../..DateTimeList../..WithFreeElements_ReadsBackAsUtcSolve_ShortArraySymbol_RoundTripsEveryElementInt16caseSolve_ShortArrayElementConstrainedOutsideShortRange_ThrowsOverflowExceptionSolve_DecimalArrayWithFreeElements_ReturnsTheInitialisedLengthand siblingsMutation results
boolarray,boollist,stringarray - exactly the domain cases. Real-domained arrays tolerate an integer index, which is whydoubledid not fail on domain in the original table eitherFloatingPointdouble/float/decimalscalars and collections together, across five test fileslong/DateTimerow →BitVec 64long/DateTimescalars and collections togethershortreaduncheckedThe second and third rows are the point of the design. Before this change a wrong row in the
collection mapping failed only collections and the scalar suite stayed green; that is how #64
went unnoticed. Now there is no row that can be wrong for one and not the other.
Verification
dotnet build solutions/Z3.Linq.slnx -c Release- clean,TreatWarningsAsErrorson./build.ps1 -Configuration Release- 46 tasks, 0 errors, 0 warningsNew issue
#89 - object collections cannot be constrained or read back. Found by probing whether the
second copy of the mapping was reachable; it is not, by any theorem.
Release note
Releases remain on hold under #60 until Microsoft.Z3 5.x reaches nuget.org, so this reaches
mainbut not consumers. Nothing about the hold changes.