Files
ILSpy/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CachedReadOnlySpanInitialization.cs
T
Sebastien Lebreton b0e446618f Fix #3850: recover ReadOnlySpan<T> array literals from the legacy lazy cache
Roslyn caches a ReadOnlySpan<T> created from an array literal in a
<PrivateImplementationDetails> field on target frameworks without
RuntimeHelpers.CreateSpan (e.g. .NET Framework / netstandard2.0 + System.Memory):

    object obj = <PrivateImplementationDetails>.cache;
    if (obj == null) {
        obj = new char[] { '\r', '\n' };
        <PrivateImplementationDetails>.cache = (char[])obj;
    }
    ... new ReadOnlySpan<char>((char[])obj) ...

The decompiled output referenced the compiler-synthesized
<PrivateImplementationDetails> type, whose escaped name is not expressible in C#
and is never declared, so the output failed to recompile (CS0400).

The modern RuntimeHelpers.CreateSpan form was already handled
(TransformRuntimeHelpersCreateSpanInitialization); this adds the analogous
handling for the legacy lazy-cache form, mirroring CachedDelegateInitialization
(which collapses the same lazy-static-field cache for anonymous-method delegates).
Once the cache is collapsed, the existing array-initializer transforms recover
the array literal, so the <PrivateImplementationDetails> reference disappears.

Test: ILPretty/CachedReadOnlySpanInitialization.
2026-07-13 11:12:10 +02:00

18 lines
681 B
C#

using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public static class CachedReadOnlySpanInitialization
{
// On target frameworks without RuntimeHelpers.CreateSpan (before .NET 7) Roslyn emits a
// compiler-generated lazy cache in <PrivateImplementationDetails> for a ReadOnlySpan<char>
// created from a multi-byte array literal. The CachedReadOnlySpanInitialization transform
// collapses that cache back to the explicit ReadOnlySpan constructor.
#if NET70
public static ReadOnlySpan<char> NewLine => new char[2] { '\r', '\n' };
#else
public static ReadOnlySpan<char> NewLine => new ReadOnlySpan<char>(new char[2] { '\r', '\n' });
#endif
}
}