Repository navigation
fix: make ContiguousSet/ContiguousMap.AsSpan read-only and add GetValueRefOrNullRef [major] - #109
Merged
Merged
Conversation
…ueRefOrNullRef [major] AsSpan() on ContiguousSet<T> and ContiguousMap<TKey,TValue> returned a writable span over the backing array, so writing through it changed elements or keys without updating uniquenessSet / keyToIndex. A set could hold duplicates and report removed items as present, and a map could answer lookups for a key it no longer stored. Both now return ReadOnlySpan<>. ContiguousMap gains GetValueRefOrNullRef(key), in the style of CollectionsMarshal, so values can still be updated in place without exposing keys. Entry stores its value in a field to make that possible; its public surface is unchanged. This is a breaking change to the return type of AsSpan(). Fixes #78 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J6q8NVYVFUeBVAH6tJCHnU
|
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 #78
What was wrong
ContiguousSet<T>.AsSpan()andContiguousMap<TKey,TValue>.AsSpan()returned a writableSpan<>over the backing array. A write through that span changed elements or keys but leftuniquenessSet/keyToIndexalone. The set could then hold duplicates and report removed items as present, and the map could return a value for a key it no longer stored.Change (as decided on the issue on 2026-09-28)
AsSpan()now returnsReadOnlySpan<…>.ContiguousMap.GetValueRefOrNullRef(TKey key), in the style ofCollectionsMarshal.GetValueRefOrNullRef. It returns a writableref TValueto the stored value, or a null ref when the key is missing (check withUnsafe.IsNullRef). Callers can update values in place but cannot touch keys. The null ref comes fromMemoryMarshal.GetReference(Span<T>.Empty), so the netstandard targets need no extra dependency.Entrykeeps its value in an internal field so the accessor can return a ref to it. Its public members are unchanged:KeyandValuestay get-only. The struct is no longer declaredreadonly struct, but each of its members is now markedreadonly.This breaks the public API (the return type of
AsSpan()), so the title is tagged[major].Tests
AsSpan_IsReadOnly_*on both types assert the return type. With the oldSpan<>return types restored, both fail and the other 444 tests pass.GetValueRefOrNullRef_*tests cover updating a value in place, keeping the key index consistent (a case-insensitive key keeps its original spelling, andRemovestill works), a null ref for a missing key, and a null key throwing. Without the change these tests do not compile.🤖 Generated with Claude Code
https://claude.ai/code/session_01J6q8NVYVFUeBVAH6tJCHnU
Generated by Claude Code