diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 32a8144dc8770..f940c8ea7b476 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -4172,6 +4172,9 @@ You should consider suppressing the warning only if you're sure that you don't w
An expression tree may not contain a named argument specification
+
+ An expression tree may not contain a named argument specification out of position
+
An expression tree may not contain a call or invocation that uses optional arguments
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index c312becca0b1e..e816b78cdc428 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -2397,6 +2397,7 @@ internal enum ErrorCode
ERR_InitInExtension = 9304,
ERR_ModifierOnUnnamedReceiverParameter = 9305,
ERR_ExtensionTypeNameDisallowed = 9306,
+ ERR_ExpressionTreeContainsNamedArgumentOutOfPosition = 9307,
// Note: you will need to do the following after adding errors:
// 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
index aeba59ca89bc7..487389d7fa908 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
@@ -2513,6 +2513,7 @@ or ErrorCode.ERR_InstanceMemberWithUnnamedExtensionsParameter
or ErrorCode.ERR_InitInExtension
or ErrorCode.ERR_ModifierOnUnnamedReceiverParameter
or ErrorCode.ERR_ExtensionTypeNameDisallowed
+ or ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition
=> false,
};
#pragma warning restore CS8524 // The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value.
diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
index f2a30c73742ed..cd06dbeed0fa1 100644
--- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs
+++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
@@ -301,6 +301,7 @@ internal enum MessageID
IDS_FeaturePartialEventsAndConstructors = MessageBase + 12852,
IDS_FeatureExtensions = MessageBase + 12853,
IDS_FeatureNullConditionalAssignment = MessageBase + 12854,
+ IDS_FeatureExpressionOptionalAndNamedArguments = MessageBase + 12855,
}
// Message IDs may refer to strings that need to be localized.
@@ -488,6 +489,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
case MessageID.IDS_FeaturePartialEventsAndConstructors:
case MessageID.IDS_FeatureExtensions:
case MessageID.IDS_FeatureNullConditionalAssignment:
+ case MessageID.IDS_FeatureExpressionOptionalAndNamedArguments:
return LanguageVersion.Preview;
// C# 13.0 features.
diff --git a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs
index 947a42ec2fe1f..7eb5688d29da3 100644
--- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs
@@ -307,6 +307,7 @@ private void VisitCall(
ImmutableArray arguments,
ImmutableArray argumentRefKindsOpt,
ImmutableArray argumentNamesOpt,
+ ImmutableArray argsToParamsOpt,
BitVector defaultArguments,
BoundNode node)
{
@@ -328,14 +329,22 @@ private void VisitCall(
{
Error(ErrorCode.ERR_ExpressionTreeContainsIndexedProperty, node);
}
- else if (hasDefaultArgument(arguments, defaultArguments))
+ else if (hasDefaultArgument(arguments, defaultArguments) &&
+ !_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments))
{
Error(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, node);
}
- else if (!argumentNamesOpt.IsDefaultOrEmpty)
+ else if (!argumentNamesOpt.IsDefaultOrEmpty &&
+ !_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments))
{
Error(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, node);
}
+ else if (!argumentNamesOpt.IsDefaultOrEmpty &&
+ hasNamedArgumentOutOfOrder(argsToParamsOpt))
+ {
+ Debug.Assert(_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments));
+ Error(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, node);
+ }
else if (IsComCallWithRefOmitted(method, arguments, argumentRefKindsOpt))
{
Error(ErrorCode.ERR_ComRefCallInExpressionTree, node);
@@ -366,6 +375,22 @@ static bool hasDefaultArgument(ImmutableArray arguments, BitVec
return false;
}
+
+ static bool hasNamedArgumentOutOfOrder(ImmutableArray argsToParamsOpt)
+ {
+ if (argsToParamsOpt.IsDefaultOrEmpty)
+ {
+ return false;
+ }
+ for (int i = 0; i < argsToParamsOpt.Length; i++)
+ {
+ if (argsToParamsOpt[i] != i)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
}
public override BoundNode Visit(BoundNode node)
@@ -474,7 +499,7 @@ public override BoundNode VisitCall(BoundCall node)
do
{
- VisitCall(node.Method, null, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.DefaultArguments, node);
+ visitCall(node);
CheckReferenceToMethodIfLocalFunction(node, node.Method);
this.VisitList(node.Arguments);
}
@@ -484,7 +509,7 @@ public override BoundNode VisitCall(BoundCall node)
}
else
{
- VisitCall(node.Method, null, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.DefaultArguments, node);
+ visitCall(node);
CheckReceiverIfField(node.ReceiverOpt);
CheckReferenceToMethodIfLocalFunction(node, node.Method);
this.Visit(node.ReceiverOpt);
@@ -492,6 +517,11 @@ public override BoundNode VisitCall(BoundCall node)
}
return null;
+
+ void visitCall(BoundCall node)
+ {
+ VisitCall(node.Method, null, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.ArgsToParamsOpt, node.DefaultArguments, node);
+ }
}
///
@@ -520,13 +550,13 @@ public override BoundNode VisitCollectionElementInitializer(BoundCollectionEleme
Error(ErrorCode.ERR_ExtensionCollectionElementInitializerInExpressionTree, node);
}
- VisitCall(node.AddMethod, null, node.Arguments, default(ImmutableArray), default(ImmutableArray), node.DefaultArguments, node);
+ VisitCall(node.AddMethod, null, node.Arguments, default(ImmutableArray), default(ImmutableArray), default(ImmutableArray), node.DefaultArguments, node);
return base.VisitCollectionElementInitializer(node);
}
public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
{
- VisitCall(node.Constructor, null, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.DefaultArguments, node);
+ VisitCall(node.Constructor, null, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.ArgsToParamsOpt, node.DefaultArguments, node);
return base.VisitObjectCreationExpression(node);
}
@@ -536,7 +566,7 @@ public override BoundNode VisitIndexerAccess(BoundIndexerAccess node)
var method = indexer.GetOwnOrInheritedGetMethod() ?? indexer.GetOwnOrInheritedSetMethod();
if ((object)method != null)
{
- VisitCall(method, indexer, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.DefaultArguments, node);
+ VisitCall(method, indexer, node.Arguments, node.ArgumentRefKindsOpt, node.ArgumentNamesOpt, node.ArgsToParamsOpt, node.DefaultArguments, node);
}
CheckReceiverIfField(node.ReceiverOpt);
return base.VisitIndexerAccess(node);
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index de5a096eb19b8..6795aa712ec1d 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -742,6 +742,11 @@
Strom výrazů nesmí obsahovat převod obslužné rutiny interpolovaného řetězce.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
Strom výrazů možná neobsahuje vzor přístupu indexeru System.Index nebo System.Range.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index 5f01e4ac14f17..fef82ba2dcc18 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -742,6 +742,11 @@
Eine Ausdrucksbaumstruktur darf keine Handler-Konvertierung einer interpolierten Zeichenfolge enthalten.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
Eine Ausdrucksbaumstruktur darf keinen System.Index- oder System.Range-Musterindexerzugriff enthalten.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index 00d1fde3305e3..d39de65e1f75c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -742,6 +742,11 @@
Un árbol de (la) expresión no puede contener una conversión de controlador de cadena interpolada.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
Un árbol de expresión no puede contener un patrón System.Index o un acceso a indizador System.Range.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index 08fec5ecba140..a7c0e82371b41 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -742,6 +742,11 @@
Une arborescence de l’expression ne peut pas contenir une conversion de gestionnaire de chaîne interpolée.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
Une arborescence de l'expression ne peut pas contenir de modèle d'accès à l'indexeur System.Index ou System.Range
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index 0fc4adbafaa8d..3c9c4b638996c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -742,6 +742,11 @@
Un albero delle espressioni non può contenere una conversione del gestore di stringhe interpolate.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
Un albero delle espressioni non può contenere un accesso a indicizzatore System.Index o System.Range di criterio
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index 48ea332b42990..89652d71d304c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -742,6 +742,11 @@
式ツリーには、補間された文字列ハンドラー変換を含めることはできません。
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
式ツリーに、System.Index または System.Range インデクサー アクセスのパターンを含めることはできません
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index 775bfea7ecee3..2931f97754d3c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -742,6 +742,11 @@
식 트리에는 보간된 문자열 처리기 변환이 포함될 수 없습니다.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
식 트리에는 System.Index 또는 System.Range 패턴의 인덱서 액세스를 포함할 수 없습니다.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index d8945a8b30892..9aa2a31cfa12c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -742,6 +742,11 @@
Drzewo wyrażenia nie może zawierać konwersji procedury obsługi ciągu interpolowanego.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
Drzewo wyrażenia nie może zawierać dostępu do indeksatora z wzorcem System.Index lub System.Range
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index 25e773f0f604c..327398efa7c86 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -742,6 +742,11 @@
Uma árvore de expressão pode não conter uma conversão de manipulador de cadeia de caracteres interpolada.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
Uma árvore de expressão não pode conter um padrão System.Index ou acesso do indexador System.Range
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index d65d0bd1b4e90..8e43ce0310444 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -742,6 +742,11 @@
Дерево выражения не может содержать преобразование обработчика интерполированных строк.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
Дерево выражения не может содержать доступ к индексатору System.Index или System.Range шаблона.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index 2761233d364d1..70a0bc99f2505 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -742,6 +742,11 @@
Bir ifade ağacı, düz metin arasına kod eklenmiş dize işleyicisi dönüşümü içeremez.
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
İfade ağacı, desen System.Index veya System.Range dizin oluşturucu erişimi içeremez
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index e5200e28058c4..741909a05e9bc 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -742,6 +742,11 @@
表达式树可能不包含内插字符串处理程序转换。
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
表达式树不能包含模式 System.Index 或 System.Range 索引器访问
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index f19961cb87432..72d9bb03d5892 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -742,6 +742,11 @@
運算式樹狀架構不可包含差補字串處理常式轉換。
+
+ An expression tree may not contain a named argument specification out of position
+ An expression tree may not contain a named argument specification out of position
+
+
An expression tree may not contain a pattern System.Index or System.Range indexer access
運算式樹狀架構不可包含 System.Index 或 System.Range 索引子存取模式
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
index 2a479263ed080..a79f04945d6b0 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
@@ -2595,8 +2595,9 @@ static void Main()
CompileAndVerifyUtil(text, expectedOutput: TrimExpectedOutput(expectedOutput));
}
- [Fact]
- public void MethodCallWithParams3()
+ [Theory]
+ [MemberData(nameof(LanguageVersions13AndNewer))]
+ public void MethodCallWithParams3(LanguageVersion languageVersion)
{
var text =
@"using System;
@@ -2612,12 +2613,20 @@ static void Main()
Console.WriteLine(testExpr);
}
}";
- CreateCompilationWithMscorlib40AndSystemCore(text)
- .VerifyDiagnostics(
- // (10,48): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
- // Expression> testExpr = () => ModAdd2();
- Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "ModAdd2()")
- );
+ var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13)
+ {
+ comp.VerifyDiagnostics(
+ // (10,48): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Expression> testExpr = () => ModAdd2();
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "ModAdd2()")
+ );
+ }
+ else
+ {
+ var verifier = CompileAndVerify(comp, expectedOutput: "() => ModAdd2(3, 4, new [] {})");
+ verifier.VerifyDiagnostics();
+ }
}
[WorkItem(544419, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544419")]
diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs
new file mode 100644
index 0000000000000..6cda4a6ea0db4
--- /dev/null
+++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs
@@ -0,0 +1,1991 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#nullable disable
+
+using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
+using Microsoft.CodeAnalysis.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.CSharp.UnitTests
+{
+ public class ExpressionOptionalAndNamedArgumentsTests : CSharpTestBase
+ {
+ private static string GetUtilities(bool useExpression)
+ {
+ return useExpression ?
+ """
+ using System;
+ using System.Linq.Expressions;
+ public static class Utils
+ {
+ public static void Report(Expression> f)
+ {
+ object value = Run(f);
+ Console.WriteLine("{0}: {1}", f, value is null ? "null" : value.ToString());
+ }
+ public static T Run(Expression> e)
+ {
+ var f = e.Compile();
+ return f();
+ }
+ }
+ """ :
+ """
+ using System;
+ public static class Utils
+ {
+ public static void Report(Func f)
+ {
+ object value = Run(f);
+ Console.WriteLine("--: {0}", value is null ? "null" : value.ToString());
+ }
+ public static T Run(Func f)
+ {
+ return f();
+ }
+ }
+ """;
+ }
+
+ private static string IncludeExpression(bool useExpression, string expectedOutput)
+ {
+ if (useExpression)
+ {
+ return expectedOutput;
+ }
+ var builder = new System.Text.StringBuilder();
+ using var reader = new System.IO.StringReader(expectedOutput);
+ while (reader.ReadLine() is { } line)
+ {
+ int index = line.IndexOf(':');
+ if (index >= 0)
+ {
+ builder.Append("--");
+ builder.AppendLine(line.Substring(index));
+ }
+ else
+ {
+ builder.AppendLine(line);
+ }
+ }
+ return builder.ToString();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_01(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ [CombinatorialValues("", "in", "ref readonly")] string refKind,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ #pragma warning disable 9200 // default value is specified for 'ref readonly' parameter
+ public static class A
+ {
+ public static T GetValue({{refKind}} T t = default) => t;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = $$"""
+ struct S
+ {
+ }
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetValue());
+ Utils.Report(() => A.GetValue());
+ Utils.Report(() => A.GetValue());
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (8,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetValue());
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(8, 28),
+ // (9,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetValue());
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(9, 28),
+ // (10,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetValue());
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(10, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetValue(0): 0
+ () => GetValue(null): null
+ () => GetValue(value(S)): S
+ """));
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_02(
+ [CombinatorialValues("", "in", "ref readonly")] string refKind,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ #pragma warning disable 9200 // default value is specified for 'ref readonly' parameter
+ public static class A
+ {
+ public static int GetIntValue({{refKind}} int i = 10) => i;
+ public static string GetStringValue({{refKind}} string s = "default") => s;
+ public static object GetObjectValue({{refKind}} object o = null) => o;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetIntValue());
+ Utils.Report(() => A.GetStringValue());
+ Utils.Report(() => A.GetObjectValue());
+ }
+ }
+ """;
+ var verifier = CompileAndVerify(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetIntValue(10): 10
+ () => GetStringValue("default"): default
+ () => GetObjectValue(null): null
+ """));
+ verifier.VerifyDiagnostics();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_AndParams(
+ [CombinatorialValues("", "in", "ref readonly")] string refKind,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ #pragma warning disable 9200 // default value is specified for 'ref readonly' parameter
+ public static class A
+ {
+ public static T GetValue({{refKind}} T x, {{refKind}} T y = default, params T[] args) => y;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = $$"""
+ struct S
+ {
+ }
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetValue(1));
+ Utils.Report(() => A.GetValue(2, 3, 4));
+ }
+ }
+ """;
+ var verifier = CompileAndVerify(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetValue(1, 0, new [] {}): 0
+ () => GetValue(2, 3, new [] {4}): 3
+ """));
+ if (refKind == "ref readonly")
+ {
+ verifier.VerifyDiagnostics(
+ // (8,44): warning CS9193: Argument 1 should be a variable because it is passed to a 'ref readonly' parameter
+ // Utils.Report(() => A.GetValue(1));
+ Diagnostic(ErrorCode.WRN_RefReadonlyNotVariable, "1").WithArguments("1").WithLocation(8, 44),
+ // (9,44): warning CS9193: Argument 1 should be a variable because it is passed to a 'ref readonly' parameter
+ // Utils.Report(() => A.GetValue(2, 3, 4));
+ Diagnostic(ErrorCode.WRN_RefReadonlyNotVariable, "2").WithArguments("1").WithLocation(9, 44),
+ // (9,47): warning CS9193: Argument 2 should be a variable because it is passed to a 'ref readonly' parameter
+ // Utils.Report(() => A.GetValue(2, 3, 4));
+ Diagnostic(ErrorCode.WRN_RefReadonlyNotVariable, "3").WithArguments("2").WithLocation(9, 47));
+ }
+ else
+ {
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_Overloads_01(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ public static class A
+ {
+ public static (int, int, int) GetArgs(int x, int y = -2, params int[] z) => (x, y, z.Length);
+ public static object GetArgs(object x) => x;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetArgs(10, 20));
+ Utils.Report(() => A.GetArgs(10));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetArgs(10));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetArgs(10)").WithLocation(6, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetArgs(10, 20, new [] {}): (10, 20, 0)
+ () => GetArgs(10, -2, new [] {}): (10, -2, 0)
+ """));
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_Overloads_02(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ public static class A
+ {
+ public static (int, int, int) GetArgs(int x, int y, int z = -3) => (x, y, z);
+ public static (int, int) GetArgs(int x, params int[] y) => (x, y.Length);
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetArgs(10, 20, 30));
+ Utils.Report(() => A.GetArgs(10, 20));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetArgs(10, 20));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetArgs(10, 20)").WithLocation(6, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetArgs(10, 20, 30): (10, 20, 30)
+ () => GetArgs(10, 20, -3): (10, 20, -3)
+ """));
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_Constructor(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression)
+ {
+ string sourceA = $$"""
+ public class A
+ {
+ public readonly string X;
+ public readonly int Y;
+ public A(string x = "default", in int y = 10) { X = x; Y = y; }
+ public override string ToString() => $"({X}, {Y})";
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = comp.EmitToImageReference();
+
+ string sourceB = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => new A("str"));
+ Utils.Report(() => new A());
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => new A("str"));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, @"new A(""str"")").WithLocation(5, 28),
+ // (6,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => new A());
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "new A()").WithLocation(6, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => new A("str", 10): (str, 10)
+ () => new A("default", 10): (default, 10)
+ """));
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_Indexer(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression)
+ {
+ string sourceA = $$"""
+ public class A
+ {
+ public int this[int x, int y = 10] => y;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = comp.EmitToImageReference();
+
+ string sourceB = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ var a = new A();
+ Utils.Report(() => a[1, 2]);
+ Utils.Report(() => a[3]);
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (7,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => a[3]);
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "a[3]").WithLocation(7, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => value(Program+<>c__DisplayClass0_0).a.get_Item(1, 2): 2
+ () => value(Program+<>c__DisplayClass0_0).a.get_Item(3, 10): 10
+ """));
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_Delegate(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression)
+ {
+ string sourceA = $$"""
+ public delegate int D(int x, in int y = 10);
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = comp.EmitToImageReference();
+
+ string sourceB = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ D d = F;
+ Utils.Report(() => d(1, 2));
+ Utils.Report(() => d(3));
+ }
+ static T F(T x, in T y) => y;
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (7,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => d(3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "d(3)").WithLocation(7, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => Invoke(value(Program+<>c__DisplayClass0_0).d, 1, 2): 2
+ () => Invoke(value(Program+<>c__DisplayClass0_0).d, 3, 10): 10
+ """));
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_CollectionInitializer(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ [CombinatorialValues("", "in", "ref readonly")] string refKind,
+ bool useExpression)
+ {
+ string sourceA = $$"""
+ #pragma warning disable 9200 // default value is specified for 'ref readonly' parameter
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Text;
+ class MyCollection : IEnumerable
+ {
+ private List> _list = new();
+ public void Add({{refKind}} K k = default, {{refKind}} V v = default) { _list.Add(new(k, v)); }
+ public IEnumerator> GetEnumerator() => _list.GetEnumerator();
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ public override string ToString()
+ {
+ var builder = new StringBuilder();
+ foreach (var kvp in this)
+ {
+ if (builder.Length > 0) builder.Append(", ");
+ builder.AppendFormat("({0}, {1})", kvp.Key, kvp.Value);
+ }
+ return builder.ToString();
+ }
+ }
+ """;
+ string sourceB = """
+ #pragma warning disable 9193 // Argument should be a variable because it is passed to a 'ref readonly' parameter
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => new MyCollection() { { "one", 1 }, { "two" } });
+ }
+ }
+ """;
+ var comp = CreateCompilation(
+ [sourceA, sourceB, GetUtilities(useExpression)],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,76): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => new MyCollection() { { "one", 1 }, { "two" } });
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, @"{ ""two"" }").WithLocation(6, 76));
+ }
+ else if (refKind != "")
+ {
+ // Expression does not support initializers with ref parameters at runtime.
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => new MyCollection`2() {Void Add(System.String, Int32)("one", 1), Void Add(System.String, Int32)("two", 0)}: (one, 1), (two, 0)
+ """));
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParameter_LocalFunction(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion)
+ {
+ string source = """
+ using System;
+ using System.Linq.Expressions;
+ class Program
+ {
+ static void Main()
+ {
+ Expression> e;
+ T Local(T t = default) => t;
+ Local(10);
+ Local();
+ e = () => Local(20);
+ e = () => Local();
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion == LanguageVersion.CSharp13)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (11,19): error CS8110: An expression tree may not contain a reference to a local function
+ // e = () => Local(20);
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "Local(20)").WithLocation(11, 19),
+ // (12,19): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // e = () => Local();
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "Local()").WithLocation(12, 19));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (11,19): error CS8110: An expression tree may not contain a reference to a local function
+ // e = () => Local(20);
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "Local(20)").WithLocation(11, 19),
+ // (12,19): error CS8110: An expression tree may not contain a reference to a local function
+ // e = () => Local();
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "Local()").WithLocation(12, 19));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Decimal(
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = """
+ public static class A
+ {
+ public static decimal GetValue(decimal d = 100) => d;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetValue(200));
+ Utils.Report(() => A.GetValue());
+ }
+ }
+ """;
+ var verifier = CompileAndVerify(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetValue(200): 200
+ () => GetValue(100): 100
+ """));
+ verifier.VerifyDiagnostics();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void DateTime_01(
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = """
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ public static class A
+ {
+ public static DateTime GetValue([Optional][DateTimeConstant(100)] DateTime value) => value;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = $$"""
+ using System;
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetValue(new DateTime(200)).Ticks);
+ Utils.Report(() => A.GetValue().Ticks);
+ }
+ }
+ """;
+ var verifier = CompileAndVerify(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetValue(new DateTime(200)).Ticks: 200
+ () => GetValue(new DateTime(100)).Ticks: 100
+ """));
+ verifier.VerifyDiagnostics();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void DateTime_02(
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = """
+ using System;
+ using System.Runtime.CompilerServices;
+ public static class A
+ {
+ public static DateTime GetValue([DateTimeConstant(100)] DateTime value) => value;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetValue().Ticks);
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA]);
+ comp.VerifyEmitDiagnostics(
+ // (5,30): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(DateTime)'
+ // Utils.Report(() => A.GetValue().Ticks);
+ Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(System.DateTime)").WithLocation(5, 30));
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalAndDefaultParameterValue(
+ bool includeOptional,
+ bool includeDefaultParameterValue,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ using System.Runtime.InteropServices;
+ public static class A
+ {
+ public static int GetValue(
+ {{(includeOptional ? "[Optional]" : "")}}
+ {{(includeDefaultParameterValue ? "[DefaultParameterValue(100)]" : "")}}
+ int value) => value;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = """
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetValue(200));
+ Utils.Report(() => A.GetValue());
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ options: TestOptions.ReleaseExe);
+ if (includeOptional)
+ {
+ string parameterValue = includeDefaultParameterValue ? "100" : "0";
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, $$"""
+ () => GetValue(200): 200
+ () => GetValue({{parameterValue}}): {{parameterValue}}
+ """));
+ verifier.VerifyDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,30): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(int)'
+ // Utils.Report(() => A.GetValue());
+ Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(int)").WithLocation(6, 30));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void OptionalParams(
+ bool includeDefaultParameterValue,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ using System.Runtime.InteropServices;
+ public static class A
+ {
+ public static string GetValue(
+ [Optional]
+ {{(includeDefaultParameterValue ? "[DefaultParameterValue(null)]" : "")}}
+ params int[] args)
+ {
+ return (args is null) ? "null" : args.Length.ToString();
+ }
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB = """
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetValue(1, 2, 3));
+ Utils.Report(() => A.GetValue());
+ }
+ }
+ """;
+ var verifier = CompileAndVerify(
+ [sourceB, GetUtilities(useExpression)],
+ references: [refA],
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetValue(new [] {1, 2, 3}): 3
+ () => GetValue(new [] {}): 0
+ """));
+ verifier.VerifyDiagnostics();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void NamedArgument_01(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ public static class A
+ {
+ public static T GetFirst(T first, T second) => first;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB1 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetFirst(1, second:2));
+ Utils.Report(() => A.GetFirst(first: 1, 2));
+ Utils.Report(() => A.GetFirst(first: 1, second:2));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB1, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(1, second:2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(1, second:2)").WithLocation(5, 28),
+ // (6,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(first: 1, 2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(first: 1, 2)").WithLocation(6, 28),
+ // (7,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(first: 1, second:2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(first: 1, second:2)").WithLocation(7, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetFirst(1, 2): 1
+ () => GetFirst(1, 2): 1
+ () => GetFirst(1, 2): 1
+ """));
+ verifier.VerifyDiagnostics();
+ }
+
+ string sourceB2 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetFirst(second:2, first: 1));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB2, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(second:2, first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(second:2, first: 1)").WithLocation(5, 28));
+ }
+ else if (useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS9307: An expression tree may not contain a named argument specification out of position
+ // Utils.Report(() => A.GetFirst(second:2, first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirst(second:2, first: 1)").WithLocation(5, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: """
+ --: 1
+ """);
+ verifier.VerifyDiagnostics();
+ }
+
+ string sourceB3 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetFirst(2, first: 1));
+ Utils.Report(() => A.GetFirst(second:2, 1));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB3, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ comp.VerifyEmitDiagnostics(
+ // (5,47): error CS1744: Named argument 'first' specifies a parameter for which a positional argument has already been given
+ // Utils.Report(() => A.GetFirst(2, first: 1));
+ Diagnostic(ErrorCode.ERR_NamedArgumentUsedInPositional, "first").WithArguments("first").WithLocation(5, 47),
+ // (6,44): error CS8323: Named argument 'second' is used out-of-position but is followed by an unnamed argument
+ // Utils.Report(() => A.GetFirst(second:2, 1));
+ Diagnostic(ErrorCode.ERR_BadNonTrailingNamedArgument, "second").WithArguments("second").WithLocation(6, 44));
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void NamedArgument_02(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ public static class A
+ {
+ public static T GetFirst(T first = default, T second = default, T third = default) => first;
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB1 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetFirst(first: 1, second: 2, third: 3));
+ Utils.Report(() => A.GetFirst(first: 1, 2, 3));
+ Utils.Report(() => A.GetFirst(first: 1, 2));
+ Utils.Report(() => A.GetFirst(first: 1));
+ Utils.Report(() => A.GetFirst(1, second: 2, 3));
+ Utils.Report(() => A.GetFirst(1, second: 2));
+ Utils.Report(() => A.GetFirst(1, 2, third: 3));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB1, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(first: 1, second: 2, third: 3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(first: 1, second: 2, third: 3)").WithLocation(5, 28),
+ // (6,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(first: 1, 2, 3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(first: 1, 2, 3)").WithLocation(6, 28),
+ // (7,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst(first: 1, 2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst(first: 1, 2)").WithLocation(7, 28),
+ // (8,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst(first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst(first: 1)").WithLocation(8, 28),
+ // (9,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(1, second: 2, 3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(1, second: 2, 3)").WithLocation(9, 28),
+ // (10,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst(1, second: 2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst(1, second: 2)").WithLocation(10, 28),
+ // (11,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(1, 2, third: 3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(1, 2, third: 3)").WithLocation(11, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetFirst(1, 2, 3): 1
+ () => GetFirst(1, 2, 3): 1
+ () => GetFirst(1, 2, 0): 1
+ () => GetFirst(1, 0, 0): 1
+ () => GetFirst(1, 2, 3): 1
+ () => GetFirst(1, 2, 0): 1
+ () => GetFirst(1, 2, 3): 1
+ """));
+ verifier.VerifyDiagnostics();
+ }
+
+ string sourceB2 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetFirst(third:3, second: 2, first: 1));
+ Utils.Report(() => A.GetFirst(second:2, first: 1));
+ Utils.Report(() => A.GetFirst(second:2, third: 3));
+ Utils.Report(() => A.GetFirst(second:2));
+ Utils.Report(() => A.GetFirst(third:3, second: 2));
+ Utils.Report(() => A.GetFirst(third:3));
+ Utils.Report(() => A.GetFirst());
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB2, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirst(third:3, second: 2, first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(third:3, second: 2, first: 1)").WithLocation(5, 28),
+ // (6,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst(second:2, first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst(second:2, first: 1)").WithLocation(6, 28),
+ // (7,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst(second:2, third: 3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst(second:2, third: 3)").WithLocation(7, 28),
+ // (8,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst(second:2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst(second:2)").WithLocation(8, 28),
+ // (9,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst(third:3, second: 2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst(third:3, second: 2)").WithLocation(9, 28),
+ // (10,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst(third:3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst(third:3)").WithLocation(10, 28),
+ // (11,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
+ // Utils.Report(() => A.GetFirst());
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst()").WithLocation(11, 28));
+ }
+ else if (useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS9307: An expression tree may not contain a named argument specification out of position
+ // Utils.Report(() => A.GetFirst(third:3, second: 2, first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirst(third:3, second: 2, first: 1)").WithLocation(5, 28),
+ // (6,28): error CS9307: An expression tree may not contain a named argument specification out of position
+ // Utils.Report(() => A.GetFirst(second:2, first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirst(second:2, first: 1)").WithLocation(6, 28),
+ // (7,28): error CS9307: An expression tree may not contain a named argument specification out of position
+ // Utils.Report(() => A.GetFirst(second:2, third: 3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirst(second:2, third: 3)").WithLocation(7, 28),
+ // (8,28): error CS9307: An expression tree may not contain a named argument specification out of position
+ // Utils.Report(() => A.GetFirst(second:2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirst(second:2)").WithLocation(8, 28),
+ // (9,28): error CS9307: An expression tree may not contain a named argument specification out of position
+ // Utils.Report(() => A.GetFirst(third:3, second: 2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirst(third:3, second: 2)").WithLocation(9, 28),
+ // (10,28): error CS9307: An expression tree may not contain a named argument specification out of position
+ // Utils.Report(() => A.GetFirst(third:3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirst(third:3)").WithLocation(10, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: """
+ --: 1
+ --: 1
+ --: 0
+ --: 0
+ --: 0
+ --: 0
+ --: 0
+ """);
+ verifier.VerifyDiagnostics();
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void NamedArgument_03(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ public static class A
+ {
+ public static (T, int?) GetFirstAndParamsLength(T first, params T[] more) => (first, more?.Length);
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB1 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetFirstAndParamsLength(first: 1));
+ Utils.Report(() => A.GetFirstAndParamsLength(first: 1, 2));
+ Utils.Report(() => A.GetFirstAndParamsLength(first: 1, 2, 3));
+ Utils.Report(() => A.GetFirstAndParamsLength(1, more: default));
+ Utils.Report(() => A.GetFirstAndParamsLength(1, more: new[] { 2, 3 }));
+ Utils.Report(() => A.GetFirstAndParamsLength(first: 1, more: default));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB1, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirstAndParamsLength(first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirstAndParamsLength(first: 1)").WithLocation(5, 28),
+ // (6,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirstAndParamsLength(first: 1, 2));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirstAndParamsLength(first: 1, 2)").WithLocation(6, 28),
+ // (7,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirstAndParamsLength(first: 1, 2, 3));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirstAndParamsLength(first: 1, 2, 3)").WithLocation(7, 28),
+ // (8,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirstAndParamsLength(1, more: default));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirstAndParamsLength(1, more: default)").WithLocation(8, 28),
+ // (9,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirstAndParamsLength(1, more: new[] { 2, 3 }));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirstAndParamsLength(1, more: new[] { 2, 3 })").WithLocation(9, 28),
+ // (10,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirstAndParamsLength(first: 1, more: default));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirstAndParamsLength(first: 1, more: default)").WithLocation(10, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: IncludeExpression(useExpression, """
+ () => GetFirstAndParamsLength(1, new [] {}): (1, 0)
+ () => GetFirstAndParamsLength(1, new [] {2}): (1, 1)
+ () => GetFirstAndParamsLength(1, new [] {2, 3}): (1, 2)
+ () => GetFirstAndParamsLength(1, null): (1, )
+ () => GetFirstAndParamsLength(1, new [] {2, 3}): (1, 2)
+ () => GetFirstAndParamsLength(1, null): (1, )
+ """));
+ verifier.VerifyDiagnostics();
+ }
+
+ string sourceB2 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetFirstAndParamsLength(more: default, first: 1));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB2, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ if (languageVersion == LanguageVersion.CSharp13 && useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS0853: An expression tree may not contain a named argument specification
+ // Utils.Report(() => A.GetFirstAndParamsLength(more: default, first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirstAndParamsLength(more: default, first: 1)").WithLocation(5, 28));
+ }
+ else if (useExpression)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,28): error CS9307: An expression tree may not contain a named argument specification out of position
+ // Utils.Report(() => A.GetFirstAndParamsLength(more: default, first: 1));
+ Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirstAndParamsLength(more: default, first: 1)").WithLocation(5, 28));
+ }
+ else
+ {
+ var verifier = CompileAndVerify(
+ comp,
+ expectedOutput: """
+ --: (1, )
+ """);
+ verifier.VerifyDiagnostics();
+ }
+
+ string sourceB3 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetFirstAndParamsLength());
+ Utils.Report(() => A.GetFirstAndParamsLength(more: default));
+ Utils.Report(() => A.GetFirstAndParamsLength(more: default, 1));
+ Utils.Report(() => A.GetFirstAndParamsLength(default, first: 1));
+ }
+ }
+ """;
+ comp = CreateCompilation(
+ [sourceB3, GetUtilities(useExpression)],
+ references: [refA],
+ parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion),
+ options: TestOptions.ReleaseExe);
+ comp.VerifyEmitDiagnostics(
+ // (5,30): error CS7036: There is no argument given that corresponds to the required parameter 'first' of 'A.GetFirstAndParamsLength(T, params T[])'
+ // Utils.Report(() => A.GetFirstAndParamsLength());
+ Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetFirstAndParamsLength").WithArguments("first", "A.GetFirstAndParamsLength(T, params T[])").WithLocation(5, 30),
+ // (6,30): error CS7036: There is no argument given that corresponds to the required parameter 'first' of 'A.GetFirstAndParamsLength(T, params T[])'
+ // Utils.Report(() => A.GetFirstAndParamsLength(more: default));
+ Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetFirstAndParamsLength").WithArguments("first", "A.GetFirstAndParamsLength(T, params T[])").WithLocation(6, 30),
+ // (7,59): error CS8323: Named argument 'more' is used out-of-position but is followed by an unnamed argument
+ // Utils.Report(() => A.GetFirstAndParamsLength(more: default, 1));
+ Diagnostic(ErrorCode.ERR_BadNonTrailingNamedArgument, "more").WithArguments("more").WithLocation(7, 59),
+ // (8,63): error CS1744: Named argument 'first' specifies a parameter for which a positional argument has already been given
+ // Utils.Report(() => A.GetFirstAndParamsLength(default, first: 1));
+ Diagnostic(ErrorCode.ERR_NamedArgumentUsedInPositional, "first").WithArguments("first").WithLocation(8, 63));
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void NamedArgument_04(
+ [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion,
+ bool useExpression,
+ bool useCompilationReference)
+ {
+ string sourceA = $$"""
+ public static class A
+ {
+ public static (T, int?) GetSecondAndParamsLength(T first = default, T second = default, params T[] more) => (second, more?.Length);
+ }
+ """;
+ var comp = CreateCompilation(sourceA);
+ var refA = AsReference(comp, useCompilationReference);
+
+ string sourceB1 = $$"""
+ class Program
+ {
+ static void Main()
+ {
+ Utils.Report(() => A.GetSecondAndParamsLength