Skip to content

Add 49 polyfills across System, System.Collections.Generic, System.IO, and System.Linq#91

Merged
Tyrrrz merged 27 commits intoprimefrom
copilot/identify-missing-polyfills
Mar 23, 2026
Merged

Add 49 polyfills across System, System.Collections.Generic, System.IO, and System.Linq#91
Tyrrrz merged 27 commits intoprimefrom
copilot/identify-missing-polyfills

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 22, 2026

Adds 49 missing polyfill APIs across four major namespaces, identified from analysis of the existing codebase. Each group adds related polyfills and corresponding tests.

Changes

SystemArgumentOutOfRangeException throw helpers (.NET 8.0)

  • ThrowIfNegative<T>, ThrowIfNegativeOrZero<T>, ThrowIfZero<T> (using IComparable<T> constraint)
  • ThrowIfGreaterThan<T>, ThrowIfGreaterThanOrEqual<T>, ThrowIfLessThan<T>, ThrowIfLessThanOrEqual<T>
  • ThrowIfEqual<T>, ThrowIfNotEqual<T>

SystemObjectDisposedException.ThrowIf (.NET 8.0)

  • ThrowIf(bool, object) and ThrowIf(bool, Type)

SystemRandom Span overloads (.NET 8.0)

  • GetItems<T>(ReadOnlySpan<T>, int), GetItems<T>(ReadOnlySpan<T>, Span<T>), Shuffle<T>(Span<T>)

SystemConvert Span overloads (.NET 5.0 / .NET 9.0)

  • FromHexString(ReadOnlySpan<char>), ToHexString(ReadOnlySpan<byte>) (.NET 5.0)
  • ToHexStringLower(ReadOnlySpan<byte>) (.NET 9.0)

SystemTimeSpan factory overloads (.NET 7.0 / .NET 9.0)

  • TimeSpan.FromMicroseconds(double) (.NET 7.0)
  • TimeSpan.FromSeconds(long, ...), FromMinutes(long, ...), FromHours(long, ...), FromDays(long, ...) (.NET 9.0)

Systemstring.IndexOf(char, StringComparison) (.NET 5.0)

  • Related to existing Contains(char, StringComparison) polyfill

System — Numeric TryParse(ReadOnlySpan<char>, IFormatProvider?, out T) (.NET 7.0)

  • Added for all 13 types that already have TryParse(string, IFormatProvider?, out T) polyfills: byte, short, int, long, sbyte, ushort, uint, ulong, float, double, decimal, IntPtr, UIntPtr
  • Also added for DateTime and DateTimeOffset

System.Collections.GenericStack<T>.TryPeek / TryPop (.NET Core 2.0)

  • Matches existing pattern from Queue<T>.TryDequeue / TryPeek polyfill

System.Collections.GenericEnsureCapacity (.NET 5.0 / .NET 6.0)

  • Dictionary<TKey,TValue>.EnsureCapacity(int) (.NET 5.0)
  • HashSet<T>.EnsureCapacity(int), Queue<T>.EnsureCapacity(int), Stack<T>.EnsureCapacity(int) (.NET 6.0)
  • Note: best-effort stub since these types don't expose writable Capacity on older frameworks

System.IOPath.Exists (.NET 7.0)

  • bool Path.Exists(string?) — implemented as File.Exists || Directory.Exists

System.IOFile.AppendAllBytes Span/Memory overloads (.NET 9.0)

  • AppendAllBytes(string, ReadOnlySpan<byte>) and AppendAllBytesAsync(string, ReadOnlyMemory<byte>, CancellationToken)

System.LinqEnumerable.Zip 3-sequence overload (.NET 6.0)

  • IEnumerable<(TFirst, TSecond, TThird)> Zip<TFirst, TSecond, TThird>(IEnumerable<TSecond>, IEnumerable<TThird>)

Security Summary

No security vulnerabilities were identified or introduced by these changes (confirmed by CodeQL scan).


⚡ Quickly spin up Copilot coding agent tasks from anywhere on your macOS or Windows machine with Raycast.

Copilot AI and others added 13 commits March 22, 2026 17:03
Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Tyrrrz/PolyShim/sessions/c66d552a-bdf5-404e-b0cc-b714a7a1e32a
…`Stack`

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Tyrrrz/PolyShim/sessions/c66d552a-bdf5-404e-b0cc-b714a7a1e32a
Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Tyrrrz/PolyShim/sessions/c66d552a-bdf5-404e-b0cc-b714a7a1e32a
… (.NET 7.0)

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Tyrrrz/PolyShim/sessions/c66d552a-bdf5-404e-b0cc-b714a7a1e32a
…prove EnsureCapacity docs

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Tyrrrz/PolyShim/sessions/c66d552a-bdf5-404e-b0cc-b714a7a1e32a
Copilot AI requested a review from Tyrrrz March 22, 2026 17:20
@Tyrrrz Tyrrrz added the enhancement New feature or request label Mar 22, 2026
@Tyrrrz Tyrrrz marked this pull request as ready for review March 22, 2026 18:08
Copilot AI review requested due to automatic review settings March 22, 2026 18:08
@Tyrrrz
Copy link
Copy Markdown
Owner

Tyrrrz commented Mar 22, 2026

@copilot rename the PR title, replace the number of sections with the number of new APIs, and also highlight major namespaces

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 22, 2026

@copilot rename the PR title, replace the number of sections with the number of new APIs, and also highlight major namespaces

Counted 49 new APIs total across four namespaces:

  • System (39): ArgumentOutOfRangeException ×9, ObjectDisposedException ×2, Random ×3, Convert ×3, TimeSpan ×6, string ×1, numeric TryParse(ReadOnlySpan<char>) ×15
  • System.Collections.Generic (6): Stack.TryPeek/TryPop ×2, EnsureCapacity ×4 types
  • System.IO (3): Path.Exists ×1, File.AppendAllBytes/AppendAllBytesAsync span overloads ×2
  • System.Linq (1): Enumerable.Zip 3-sequence overload

Suggested title: "Add 49 polyfills across System, System.Collections.Generic, System.IO, and System.Linq"

Unfortunately the GITHUB_TOKEN in this environment does not have PR write permissions (returns 403), and github.com is blocked from the browser, so I cannot update the title directly — you'll need to apply it manually.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh gh pr edit 91 --title Add 49 polyfills across System, System.Collections.Generic, System.IO, and System.Linq (http block)
    • Triggering command: /usr/bin/gh gh pr view 91 --json title,url (http block)
    • Triggering command: /usr/bin/gh gh auth status (http block)
  • https://api.github.com/repos/Tyrrrz/PolyShim/pulls/91
    • Triggering command: /usr/bin/curl curl -s -o /dev/null -w %{http_code} -X PATCH REDACTED -H Authorization: token ****** -H Accept: application/vnd.github.v3&#43;json -d {&#34;title&#34;:&#34;Add 49 polyfills across System, System.Collections.Generic, System.IO, and System.Linq&#34;} (http block)
    • Triggering command: /usr/bin/curl curl -s -X PATCH REDACTED -H Authorization: ****** -H Accept: application/vnd.github.v3&#43;json -H X-GitHub-Api-Version: 2022-11-28 -d {&#34;title&#34;:&#34;Add 49 polyfills across System, System.Collections.Generic, System.IO, and System.Linq&#34;} (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Add missing polyfills: 12 new sections Add 49 polyfills across System, System.Collections.Generic, System.IO, and System.Linq Mar 22, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new batch of PolyShim polyfills to backport newer BCL APIs (NET 5–9 era) onto older TFMs, along with corresponding unit tests in PolyShim.Tests.

Changes:

  • Added new polyfills across multiple TFMs (e.g., Stack<T>.TryPeek/TryPop, EnsureCapacity stubs, Path.Exists, new TimeSpan factories, span-based Random overloads, and span-based TryParse overloads).
  • Added/updated tests to validate the added polyfills across the test target frameworks.
  • Expanded Convert and File polyfills with span/memory overloads for hex and append operations.

Reviewed changes

Copilot reviewed 48 out of 48 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
PolyShim/NetCore20/Stack.cs Adds Stack<T>.TryPeek / TryPop polyfills for older TFMs.
PolyShim/Net90/TimeSpan.cs Adds .NET 9-style TimeSpan long-based factory overloads.
PolyShim/Net90/File.cs Adds File.AppendAllBytes span/memory overload polyfills.
PolyShim/Net90/Convert.cs Adds Convert.ToHexStringLower(ReadOnlySpan<byte>) polyfill.
PolyShim/Net80/Random.cs Adds Random.GetItems span overloads and Shuffle(Span<T>).
PolyShim/Net80/ObjectDisposedException.cs Adds ObjectDisposedException.ThrowIf polyfills.
PolyShim/Net80/ArgumentOutOfRangeException.cs Adds ArgumentOutOfRangeException.ThrowIf* helper polyfills.
PolyShim/Net70/Byte.cs Adds byte.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/Int16.cs Adds short.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/Int32.cs Adds int.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/Int64.cs Adds long.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/SByte.cs Adds sbyte.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/UInt16.cs Adds ushort.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/UInt32.cs Adds uint.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/UInt64.cs Adds ulong.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/Single.cs Adds float.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/Double.cs Adds double.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/Decimal.cs Adds decimal.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/IntPtr.cs Adds IntPtr.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/UIntPtr.cs Adds UIntPtr.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/DateTime.cs Adds DateTime.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/DateTimeOffset.cs Adds DateTimeOffset.TryParse(ReadOnlySpan<char>, ...) polyfill.
PolyShim/Net70/TimeSpan.cs Adds TimeSpan.FromMicroseconds(double) polyfill.
PolyShim/Net70/Path.cs Adds Path.Exists(string?) polyfill (file/dir existence).
PolyShim/Net60/Stack.cs Adds Stack<T>.EnsureCapacity(int) stub polyfill.
PolyShim/Net60/Queue.cs Adds Queue<T>.EnsureCapacity(int) stub polyfill.
PolyShim/Net60/HashSet.cs Adds HashSet<T>.EnsureCapacity(int) stub polyfill.
PolyShim/Net60/EnumerableExtensions.cs Adds 3-sequence Enumerable.Zip polyfill.
PolyShim/Net50/String.cs Adds string.IndexOf(char, StringComparison) polyfill.
PolyShim/Net50/Dictionary.cs Adds Dictionary<TKey,TValue>.EnsureCapacity(int) stub polyfill.
PolyShim/Net50/Convert.cs Adds span overloads for hex encode/decode polyfills.
PolyShim.Tests/NetCore20/StackTests.cs Tests Stack<T>.TryPeek / TryPop.
PolyShim.Tests/Net90/TimeSpanTests.cs Tests the new TimeSpan factory overloads.
PolyShim.Tests/Net90/FileTests.cs Tests AppendAllBytes array/span and async array/memory overloads.
PolyShim.Tests/Net90/ConvertTests.cs Tests ToHexStringLower array/span overloads.
PolyShim.Tests/Net80/RandomTests.cs Tests Random.GetItems span overloads and Shuffle(Span<T>).
PolyShim.Tests/Net80/ObjectDisposedExceptionTests.cs Tests ObjectDisposedException.ThrowIf overloads.
PolyShim.Tests/Net80/ArgumentOutOfRangeExceptionTests.cs Tests ArgumentOutOfRangeException.ThrowIf* helpers.
PolyShim.Tests/Net70/TimeSpanTests.cs Tests TimeSpan.FromMicroseconds.
PolyShim.Tests/Net70/PathTests.cs Tests Path.Exists behavior for file/dir/null/empty.
PolyShim.Tests/Net70/NumericTryParseSpanTests.cs Tests TryParse(ReadOnlySpan<char>, ...) polyfills across numeric/date pointer types.
PolyShim.Tests/Net60/StackTests.cs Tests Stack<T>.EnsureCapacity stub behavior.
PolyShim.Tests/Net60/QueueTests.cs Tests Queue<T>.EnsureCapacity stub behavior.
PolyShim.Tests/Net60/HashSetTests.cs Tests HashSet<T>.EnsureCapacity stub behavior.
PolyShim.Tests/Net60/EnumerableExtensionsTests.cs Tests 3-sequence Zip polyfill behavior.
PolyShim.Tests/Net50/StringTests.cs Tests string.IndexOf(char, StringComparison) polyfill.
PolyShim.Tests/Net50/DictionaryTests.cs Tests Dictionary<TKey,TValue>.EnsureCapacity stub behavior.
PolyShim.Tests/Net50/ConvertTests.cs Tests span/string overloads for hex encode/decode polyfills.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Owner

@Tyrrrz Tyrrrz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Tyrrrz
Copy link
Copy Markdown
Owner

Tyrrrz commented Mar 22, 2026

@copilot can you identify why the build is failing?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 22, 2026

@copilot can you identify why the build is failing?

The build fails on net462 because FEATURE_MEMORY is false (no System.Memory package reference in the test project). This means the TryParse(ReadOnlySpan<char>, ...) polyfills aren't compiled (they're guarded with #if FEATURE_MEMORY in source), but the test methods try to call them.

Fixed in c2abeb1 by adding System.Memory as a package reference to the test project. This makes FEATURE_MEMORY true on net462, so the span-based polyfills compile and the tests work without needing #if FEATURE_MEMORY guards.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /usr/share/dotnet/dotnet /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/PolyShim.Tests.runtimeconfig.json --depsfile /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/PolyShim.Tests.deps.json /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/testhost.dll --port 46013 --endpoint 127.0.0.1:046013 --role client --parentprocessid 4220 --datacollectionport 0 --telemetryoptedin false (dns block)
    • Triggering command: /usr/share/dotnet/dotnet /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/PolyShim.Tests.runtimeconfig.json --depsfile /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/PolyShim.Tests.deps.json /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/testhost.dll --port 38735 --endpoint 127.0.0.1:038735 --role client --parentprocessid 4328 --datacollectionport 0 --telemetryoptedin false (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@Tyrrrz
Copy link
Copy Markdown
Owner

Tyrrrz commented Mar 23, 2026

@copilot the new build is failing too

…ETFRAMEWORK guards for span tests

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Tyrrrz/PolyShim/sessions/c3af6596-645e-4ae2-96ea-6ab894a48b86
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 23, 2026

@copilot the new build is failing too

The build was crashing because commit c2abeb1 added System.Memory as a package reference to the test project. This triggered a Roslyn compiler bug — NullReferenceException in TryEmitOptimizedReadonlySpanCreation when compiling for net462. The compiler tries to optimize ReadOnlySpan<byte> creation from u8 string literals but crashes because the type comes from the System.Memory NuGet package rather than the runtime.

Fixed in 2b1651a by:

  1. Removing System.Memory from the test csproj
  2. Adding #if !NETFRAMEWORK guards around the 16 span-based test methods (TryParse_Span_Test and FromHexString_Span_Test) since the underlying polyfills are guarded with #if FEATURE_MEMORY and don't exist on net462

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /usr/share/dotnet/dotnet /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/PolyShim.Tests.runtimeconfig.json --depsfile /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/PolyShim.Tests.deps.json /home/REDACTED/work/PolyShim/PolyShim/PolyShim.Tests/bin/Debug/net10.0/testhost.dll --port 43355 --endpoint 127.0.0.1:043355 --role client --parentprocessid 4585 --datacollectionport 0 --telemetryoptedin false (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@Tyrrrz
Copy link
Copy Markdown
Owner

Tyrrrz commented Mar 23, 2026

@copilot build no longer crashing but the tests are failing

…iseconds(0.5) which rounds on net462

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/Tyrrrz/PolyShim/sessions/47c6c53b-a628-46cd-a630-feea931231e7
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 23, 2026

@copilot build no longer crashing but the tests are failing

Fixed in 617d1f3. The FromMicroseconds_Test was failing because TimeSpan.FromMilliseconds(0.5) rounds to 1ms on .NET Framework (it rounds to the nearest millisecond). Replaced with TimeSpan.FromTicks(5_000) which is exact on all platforms.

@copilot the new build is failing too

The test failure was in TimeSpan.FromMicroseconds_Test on net462TimeSpan.FromMilliseconds(0.5) rounds to 1ms on .NET Framework. Fixed in 617d1f3 by using TimeSpan.FromTicks(5_000) instead.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 99.21415% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.32%. Comparing base (c02cb80) to head (617d1f3).
⚠️ Report is 2 commits behind head on prime.

Files with missing lines Patch % Lines
PolyShim.Tests/Net90/FileTests.cs 84.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            prime      #91      +/-   ##
==========================================
+ Coverage   85.48%   87.32%   +1.84%     
==========================================
  Files         220      255      +35     
  Lines        3630     4135     +505     
  Branches      315      345      +30     
==========================================
+ Hits         3103     3611     +508     
+ Misses        456      455       -1     
+ Partials       71       69       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 63 out of 63 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants