Skip to content

Commit

Permalink
Collection expressions - error when we can't emit good codegen for Im…
Browse files Browse the repository at this point in the history
…mutableArray (dotnet#70384)
  • Loading branch information
RikkiGibson committed Oct 17, 2023
1 parent 0cf3dfa commit b06244c
Show file tree
Hide file tree
Showing 18 changed files with 166 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,15 @@ private BoundExpression ConvertCollectionExpression(
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, collectionBuilderMethod, syntax, isDelegateConversion: false);
}
break;

case CollectionExpressionTypeKind.ImplementsIEnumerableT:
case CollectionExpressionTypeKind.ImplementsIEnumerable:
if (targetType.OriginalDefinition.Equals(Compilation.GetWellKnownType(WellKnownType.System_Collections_Immutable_ImmutableArray_T), TypeCompareKind.ConsiderEverything))
{
diagnostics.Add(ErrorCode.ERR_CollectionExpressionImmutableArray, syntax, targetType.OriginalDefinition);
return BindCollectionExpressionForErrorRecovery(node, targetType, diagnostics);
}
break;
}

var elements = node.Elements;
Expand Down
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -7809,4 +7809,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_ExpectedInterpolatedString" xml:space="preserve">
<value>Expected interpolated string</value>
</data>
<data name="ERR_CollectionExpressionImmutableArray" xml:space="preserve">
<value>This version of '{0}' cannot be used with collection expressions.</value>
</data>
</root>
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2275,6 +2275,7 @@ internal enum ErrorCode
ERR_InterceptorGlobalNamespace = 9206,
ERR_InterceptableMethodMustBeOrdinary = 9207,

ERR_CollectionExpressionImmutableArray = 9210,
#endregion

// Note: you will need to do the following after adding warnings:
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2404,6 +2404,7 @@ internal static bool IsBuildOnlyDiagnostic(ErrorCode code)
case ErrorCode.WRN_Experimental:
case ErrorCode.ERR_ExpectedInterpolatedString:
case ErrorCode.ERR_InterceptorGlobalNamespace:
case ErrorCode.ERR_CollectionExpressionImmutableArray:
return false;
default:
// NOTE: All error codes must be explicitly handled in this switch statement
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -21744,6 +21744,93 @@ .locals init (System.Collections.Generic.List<int> V_0,
""");
}

[Fact]
public void ImmutableArray_06()
{
string sourceA = """
using System.Collections.Immutable;

class Program
{
static void Main()
{
ImmutableArray<int> arr = [1, 2, 3];
arr.Report();
}
}
""";

var comp = CreateCompilation(new[] { sourceA, s_collectionExtensions }, targetFramework: TargetFramework.Net60);
comp.VerifyEmitDiagnostics(
// 0.cs(7,35): error CS9210: This version of 'ImmutableArray<T>' cannot be used with collection expressions.
// ImmutableArray<int> arr = [1, 2, 3];
Diagnostic(ErrorCode.ERR_CollectionExpressionImmutableArray, "[1, 2, 3]").WithArguments("System.Collections.Immutable.ImmutableArray<T>").WithLocation(7, 35));

// Can work around this error in downlevel scenarios by defining ImmutableCollectionsMarshal.AsImmutableArray
string sourceB = """
using System.Collections.Immutable;

namespace System.Runtime.InteropServices
{
public static class ImmutableCollectionsMarshal
{
// nb: the real implementation of this would use an unsafe cast
public static ImmutableArray<T> AsImmutableArray<T>(T[] array) => ImmutableArray.Create(array);
}
}
""";

var verifier = CompileAndVerify(new[] { sourceA, sourceB, s_collectionExtensions }, targetFramework: TargetFramework.Net60, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("[1, 2, 3],"));
verifier.VerifyDiagnostics();
verifier.VerifyIL("Program.Main", """
{
// Code size 34 (0x22)
.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: call "System.Collections.Immutable.ImmutableArray<int> System.Runtime.InteropServices.ImmutableCollectionsMarshal.AsImmutableArray<int>(int[])"
IL_0016: box "System.Collections.Immutable.ImmutableArray<int>"
IL_001b: ldc.i4.0
IL_001c: call "void CollectionExtensions.Report(object, bool)"
IL_0021: ret
}
""");
}

[Fact]
public void ImmutableArray_07()
{
// Test an ImmutableArray<T> which implements only non-generic IEnumerable.
string sourceA = """
using System.Collections.Immutable;

class Program
{
static void Main()
{
ImmutableArray<int> arr = [1, 2, 3];
}
}

namespace System.Collections.Immutable
{
struct ImmutableArray<T> : IEnumerable
{
public void Add(T t) { }
IEnumerator IEnumerable.GetEnumerator() => null;
}
}
""";

var comp = CreateCompilation(sourceA, targetFramework: TargetFramework.Mscorlib40);
comp.VerifyEmitDiagnostics(
// 0.cs(7,35): error CS9210: This version of 'ImmutableArray<T>' cannot be used with collection expressions.
// ImmutableArray<int> arr = [1, 2, 3];
Diagnostic(ErrorCode.ERR_CollectionExpressionImmutableArray, "[1, 2, 3]").WithArguments("System.Collections.Immutable.ImmutableArray<T>").WithLocation(7, 35));
}
[Fact]
public void ElementNullability_ArrayCollection()
{
Expand Down

0 comments on commit b06244c

Please sign in to comment.