Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cston committed Aug 6, 2023
1 parent e72459d commit 7a0d691
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private BoundExpression VisitArrayOrSpanCollectionExpression(BoundCollectionExpr

Debug.Assert(collectionTypeKind is CollectionExpressionTypeKind.Span or CollectionExpressionTypeKind.ReadOnlySpan);
Debug.Assert(spanType.OriginalDefinition.Equals(_compilation.GetWellKnownType(
collectionTypeKind == CollectionExpressionTypeKind.Span ? WellKnownType.System_Span_T : WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions));
collectionTypeKind == CollectionExpressionTypeKind.Span ? WellKnownType.System_Span_T : WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions));
Debug.Assert(elementType.Equals(spanType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0], TypeCompareKind.AllIgnoreOptions));

if (ShouldUseInlineArray(node) &&
Expand Down
172 changes: 172 additions & 0 deletions src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11052,6 +11052,178 @@ .locals init (R<object> V_0, //r
""");
}

[Fact]
public void SpanAssignment_FieldInitializer_01()
{
string source = """
using System;
ref struct R
{
public ReadOnlySpan<object> F = [1, 2, 3];
public R() { }
}
""";
var comp = CreateCompilation(source, targetFramework: TargetFramework.Net80);
comp.VerifyEmitDiagnostics(
// (4,37): error CS9202: A collection expression of type 'ReadOnlySpan<object>' cannot be used in this context because it may be exposed outside of the current scope.
// public ReadOnlySpan<object> F = [1, 2, 3];
Diagnostic(ErrorCode.ERR_CollectionExpressionEscape, "[1, 2, 3]").WithArguments("System.ReadOnlySpan<object>").WithLocation(4, 37));
}

[Fact]
public void SpanAssignment_FieldInitializer_02()
{
string source = """
using System;
class Program
{
static T[] FromSpan<T>(Span<T> s) => s.ToArray();
static int[] F = FromSpan([1, 2, 3]);
static void Main()
{
F.Report();
}
}
""";
var verifier = CompileAndVerify(
new[] { source, s_collectionExtensionsWithSpan },
targetFramework: TargetFramework.Net80,
verify: Verification.Skipped,
expectedOutput: IncludeExpectedOutput("[1, 2, 3], "));
// PROTOTYPE: Use inline array.
verifier.VerifyIL("Program..cctor", """
{
// Code size 33 (0x21)
.maxstack 3
IL_0000: ldc.i4.3
IL_0001: newarr "int"
IL_0006: dup
IL_0007: ldtoken "<PrivateImplementationDetails>.__StaticArrayInitTypeSize=12 <PrivateImplementationDetails>.4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D"
IL_000c: call "void System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray(System.Array, System.RuntimeFieldHandle)"
IL_0011: newobj "System.Span<int>..ctor(int[])"
IL_0016: call "int[] Program.FromSpan<int>(System.Span<int>)"
IL_001b: stsfld "int[] Program.F"
IL_0020: ret
}
""");
}

[Fact]
public void SpanAssignment_FieldInitializer_03()
{
string source = """
using System;
class C
{
static T[] FromSpan<T>(ReadOnlySpan<T> s) => s.ToArray();
public object[] F = FromSpan<object>([1, 2, 3]);
}
class Program
{
static void Main()
{
(new C()).F.Report();
}
}
""";
var verifier = CompileAndVerify(
new[] { source, s_collectionExtensionsWithSpan },
targetFramework: TargetFramework.Net80,
verify: Verification.Skipped,
expectedOutput: IncludeExpectedOutput("[1, 2, 3], "));
// PROTOTYPE: Use inline array.
verifier.VerifyIL("C..ctor", """
{
// Code size 56 (0x38)
.maxstack 5
IL_0000: ldarg.0
IL_0001: ldc.i4.3
IL_0002: newarr "object"
IL_0007: dup
IL_0008: ldc.i4.0
IL_0009: ldc.i4.1
IL_000a: box "int"
IL_000f: stelem.ref
IL_0010: dup
IL_0011: ldc.i4.1
IL_0012: ldc.i4.2
IL_0013: box "int"
IL_0018: stelem.ref
IL_0019: dup
IL_001a: ldc.i4.2
IL_001b: ldc.i4.3
IL_001c: box "int"
IL_0021: stelem.ref
IL_0022: newobj "System.ReadOnlySpan<object>..ctor(object[])"
IL_0027: call "object[] C.FromSpan<object>(System.ReadOnlySpan<object>)"
IL_002c: stfld "object[] C.F"
IL_0031: ldarg.0
IL_0032: call "object..ctor()"
IL_0037: ret
}
""");
}

[Fact]
public void SpanAssignment_FieldInitializer_04()
{
string source = """
using System;
struct S
{
static T[] FromSpan<T>(ReadOnlySpan<T> s) => s.ToArray();
public object[] F = FromSpan<object>([1, 2, 3]);
public S() { }
}
class Program
{
static void Main()
{
(new S()).F.Report();
}
}
""";
var verifier = CompileAndVerify(
new[] { source, s_collectionExtensionsWithSpan },
targetFramework: TargetFramework.Net80,
verify: Verification.Skipped,
expectedOutput: IncludeExpectedOutput("[1, 2, 3], "));
verifier.VerifyIL("S..ctor", """
{
// Code size 73 (0x49)
.maxstack 3
.locals init (<>y__InlineArray3<object> V_0)
IL_0000: ldarg.0
IL_0001: ldloca.s V_0
IL_0003: initobj "<>y__InlineArray3<object>"
IL_0009: ldloca.s V_0
IL_000b: ldc.i4.0
IL_000c: call "InlineArrayElementRef<<>y__InlineArray3<object>, object>(ref <>y__InlineArray3<object>, int)"
IL_0011: ldc.i4.1
IL_0012: box "int"
IL_0017: stind.ref
IL_0018: ldloca.s V_0
IL_001a: ldc.i4.1
IL_001b: call "InlineArrayElementRef<<>y__InlineArray3<object>, object>(ref <>y__InlineArray3<object>, int)"
IL_0020: ldc.i4.2
IL_0021: box "int"
IL_0026: stind.ref
IL_0027: ldloca.s V_0
IL_0029: ldc.i4.2
IL_002a: call "InlineArrayElementRef<<>y__InlineArray3<object>, object>(ref <>y__InlineArray3<object>, int)"
IL_002f: ldc.i4.3
IL_0030: box "int"
IL_0035: stind.ref
IL_0036: ldloca.s V_0
IL_0038: ldc.i4.3
IL_0039: call "InlineArrayAsReadOnlySpan<<>y__InlineArray3<object>, object>(in <>y__InlineArray3<object>, int)"
IL_003e: call "object[] S.FromSpan<object>(System.ReadOnlySpan<object>)"
IL_0043: stfld "object[] S.F"
IL_0048: ret
}
""");
}

[CombinatorialData]
[Theory]
public void SpanAssignment_RefLocal([CombinatorialValues(TargetFramework.Net70, TargetFramework.Net80)] TargetFramework targetFramework)
Expand Down

0 comments on commit 7a0d691

Please sign in to comment.