Skip to content

Commit

Permalink
Avoid problems with string to ReadOnlySpan<T>
Browse files Browse the repository at this point in the history
  • Loading branch information
jjonescz committed Jul 15, 2024
1 parent c9f6e1b commit 5b0ace4
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/Compilers/CSharp/Test/Emit3/FirstClassSpanTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1981,7 +1981,9 @@ public static void R(Expression<Action> e) { }
public static void M({{type}}<string> x) { }
}
""";
var comp = CreateCompilationWithSpanAndMemoryExtensions(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion));
var comp = CreateCompilationWithSpanAndMemoryExtensions(source,
parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion),
noStringToReadOnlySpanConversionInSource: true);
var verifier = CompileAndVerify(comp).VerifyDiagnostics();
verifier.VerifyIL("<top-level-statements-entry-point>", $$"""
{
Expand Down
5 changes: 3 additions & 2 deletions src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2575,15 +2575,16 @@ protected static CSharpCompilation CreateCompilationWithIndexAndRangeAndSpan(CSh
parseOptions: parseOptions);
}

protected static CSharpCompilation CreateCompilationWithSpanAndMemoryExtensions(CSharpTestSource text, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null, TargetFramework targetFramework = TargetFramework.NetCoreApp)
protected static CSharpCompilation CreateCompilationWithSpanAndMemoryExtensions(CSharpTestSource text, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null, TargetFramework targetFramework = TargetFramework.NetCoreApp, bool noStringToReadOnlySpanConversionInSource = false)
{
if (ExecutionConditionUtil.IsCoreClr)
{
return CreateCompilation(text, targetFramework: targetFramework, options: options, parseOptions: parseOptions);
}
else
{
var reference = CreateCompilation(new[] { TestSources.Span, TestSources.MemoryExtensions }, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics();
var spanSource = noStringToReadOnlySpanConversionInSource ? TestSources.SpanWithoutStringConversion : TestSources.Span;
var reference = CreateCompilation(new[] { spanSource, TestSources.MemoryExtensions }, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics();

return CreateCompilation(
text,
Expand Down
13 changes: 12 additions & 1 deletion src/Compilers/Test/Utilities/CSharp/TestSources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities
{
internal static class TestSources
{
private const string StringToReadOnlySpanConversion = """
// NOTE: This is defined on String in the BCL (and the target type is non-generic ReadOnlySpan<char>).
public static implicit operator ReadOnlySpan<T>(string stringValue) => string.IsNullOrEmpty(stringValue) ? default : new ReadOnlySpan<T>((T[])(object)stringValue.ToCharArray());
""";

internal const string Span = @"
namespace System
{
Expand Down Expand Up @@ -164,7 +169,7 @@ public ref readonly T Current
public static implicit operator ReadOnlySpan<T>(T[] array) => array == null ? default : new ReadOnlySpan<T>(array);
public static implicit operator ReadOnlySpan<T>(string stringValue) => string.IsNullOrEmpty(stringValue) ? default : new ReadOnlySpan<T>((T[])(object)stringValue.ToCharArray());
" + StringToReadOnlySpanConversion + @"
public ReadOnlySpan<T> Slice(int offset, int length) => new ReadOnlySpan<T>(this.arr, offset, length);
}
Expand Down Expand Up @@ -239,6 +244,12 @@ public static T[] ToArray<T>(void* ptr, int count)
}
}";

/// <summary>
/// Use if the non-standardly defined string-to-ReadOnlySpan conversion causes problems
/// (e.g., when converting from null to ReadOnlySpan you would get an ambiguity for the user-defined conversion).
/// </summary>
internal static readonly string SpanWithoutStringConversion = Span.Replace(StringToReadOnlySpanConversion, "");

internal const string Index = @"
namespace System
Expand Down

0 comments on commit 5b0ace4

Please sign in to comment.