The type was a record struct whose ==/Equals/GetHashCode were
synthesized from all fields, including the _sets array, so two
ranges that parse to the same constraint sets compared as
unequal (reference-sensitive on the array). This also broke
using ranges as dictionary keys, where lookup relies on value
equality.
Change the type to a plain readonly struct implementing
IEquatable<SemanticVersionRange> with structural equality over
the constraint sets (operation + version per comparator). The
custom ToString already existed, so no display behaviour is lost.
Add a failing-then-passing test.
Previously SemanticVersion was a record struct whose ==/Equals/
GetHashCode were synthesized from all fields, so versions that
differ only in build metadata were not equal. Range matching
already used precedence (ignoring metadata), creating an
inconsistency.
Change the type to a plain readonly struct implementing
IEquatable<SemanticVersion> and define ==/Equals/GetHashCode
in terms of SemanticVersionComparer.Priority, so build
metadata is ignored. The custom ToString already existed, so no
display behaviour is lost.
Add a failing-then-passing test.
TryFormat for the "ns" format returned false for any set that can
not be expressed as a caret/tilde range. The public ToString
routes through DefaultInterpolatedStringHandler, whose buffer-full
fallback re-enters ToString, causing an infinite loop / stack overflow.
For "ns", fall back to the full comparator ("n") form when the
compact form cannot represent the set, so the call always succeeds
for a representable range. A genuine buffer overflow still returns
false as before.
Add failing-then-passing tests.
Build metadata does not affect precedence (SemVer 2.0.0 §10), so
the Eq and Neq constraints now use SemanticVersionComparer.Priority
instead of the structural == operator. This makes [1.2.3] match
1.2.3+build, consistent with precedence semantics.
Add a failing-then-passing test.
Per SemVer 2.0.0 the core version numbers and numeric prerelease
identifiers must not include leading zeroes, and prerelease/build-metadata
identifiers must be composed only of ASCII alphanumerics and hyphens.
Add IsValidIdentifiers using a vectorized SearchValues lookup for the
allowed character set and ulong.TryParse to detect numeric identifiers
for the leading-zero check. Add failing-then-passing tests for both
invalid and still-valid inputs.