Repository navigation
fix(postconditions)!: Copy and compare arrays and the value types of System.Collections.Frozen - #63
Merged
Merged
Conversation
…ing dimensions Refs #57
…irst dimension's length Refs #57
… without reading its namespace Refs #57
…pointers and rank 2 Refs #57
…Collections.Frozen Refs #57
…s and the frozen namespace Refs #57
…ray of function pointers on both sides Refs #57
… are copied and compared Refs #57
… for copied dictionaries Refs #57
…ace are copied and compared Refs #57
…ith its measurement Refs #57
… an array compared as a whole Refs #57
…ared as a whole Refs #57
… copied object holds Refs #57
This was referenced Oct 11, 2026
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.
Old<T>()shared every type whose namespace isSystem.Collections.Frozen. The runtime reportsthe namespace of an array type as that of its element type, so
Old<T>()returned the originalFrozenSet<T>[]and, with it, the storage of aList<FrozenSet<T>>, aStack, aQueue, anImmutableArrayor aCollectionof them: replacing an element afterOld<T>()was not seen.Measuring the fix found four more defects next to it, which are taken into this change.
What changes
Old<T>()copies an array whose element type is declared inSystem.Collections.Frozen. Itselements keep their own rule: a
FrozenSet<T>element is still shared.System.Collections.Frozen(the two public enumerators, astruct or enum of yours declared there) is copied and compared like any other value type. Before,
it was compared by reference to its box and always reported as changed.
TofEnsureAssignable<T>()is an array type orSystem.Array, the twovalues are compared as a whole, element by element. Assignable patterns do not apply and are not
examined. Before, the members of
Arraywere compared, so two arrays of equal length anddifferent content passed.
every dimension. Before, a 1 by 2 and a 2 by 1 array of the same elements were equal.
Old<T>()and a comparisonno longer throw for an object that holds one (
NotSupportedExceptionfor pointers;BadImageFormatExceptionfor function pointers, also inside another array or aList).FrozenSet<T>,FrozenDictionary<TKey, TValue>and every other class declared in the namespacestay shared.
Limits, stated in the API reference with the ways out:
Tselects the comparison as a whole: two arrays passed asobjector as aninterface are compared by the members that
Tshows (ICollectionshowsCountonly).int[]equalsobject[]of the samenumbers, not
long[]).Tdoes not preserve the members of the element type of anarray as
T.Tis compared element by element, where such a call read no element before. Onemeasurement, Debug build: two
byte[]of 1,000,000 equal elements allocated about 81 MB.looked up by key.
FrozenSet<T>and an enumerator of it: measured on .NET 8, a changeinside an element of the set is reported at the enumerator member. The result depends on the
runtime.
Verification
win-x64: 84 checks in the default publish and 83 with the hidden dictionary entry,with postconditions on and with
DBC_POST=off; no failure.do (30, 45, 38 and 65).
ubuntu-latestand the Linux Native AOT smoke run. Not measured: NativeAOT for arrays of pointers and of function pointers.
Records: ADR-0022, ADR-0012, ADR-0021 and ADR-0007 carry amendments. CHANGELOG
[Unreleased]gains one BREAKING entry (rank, lengths and lower bounds) and one Fixed entry (arrays of
pointers); the entries on values compared as a whole and on the frozen collections are extended.
The version does not change.
Merge: squash. The 21 commits are seven changes with their review corrections; the first
commit alone changes an array passed as
Tand the second repairs it.Follow-ups: #61 (
EnsureImmutableCollection<T>()and arrays of function pointers), #62(statements of the user documents and ADRs, older than this change, that the code does not bear
out). #40 keeps the declared types that are not array types.
Closes #57.