From a8cbbce2998bbb8bc04213a3890b6903b8d66a21 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 2 Apr 2025 15:51:48 -0700 Subject: [PATCH 01/14] Correct DefaultParameterValueAttribute in diagnostic --- src/Compilers/CSharp/Portable/CSharpResources.resx | 2 +- .../Symbols/Source/SourceComplexParameterSymbol.cs | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.cs.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.de.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.es.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.fr.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.it.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.ja.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.ko.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.pl.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.pt-BR.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.ru.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.tr.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf | 4 ++-- .../CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs | 10 +++++----- .../CSharp/Test/Emit3/RefReadonlyParameterTests.cs | 10 +++++----- .../CSharp/Test/Emit3/Semantics/ExtensionTests.cs | 2 +- .../Test/Semantic/Semantics/NamedAndOptionalTests.cs | 4 ++-- .../Semantic/Semantics/NullableReferenceTypesTests.cs | 4 ++-- .../CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs | 2 +- 21 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 611416fe327f8..7fd9b1384ea79 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4062,7 +4062,7 @@ You should consider suppressing the warning only if you're sure that you don't w Named argument '{0}' is used out-of-position but is followed by an unnamed argument - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute Default parameter value for '{0}' must be a compile-time constant diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 6bbab27a68ff2..b0b2e52c96303 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -756,7 +756,7 @@ protected override void DecodeWellKnownAttributeImpl(ref DecodeWellKnownAttribut if (HasDefaultArgumentSyntax) { - // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute diagnostics.Add(ErrorCode.ERR_DefaultValueUsedWithAttributes, arguments.AttributeSyntaxOpt.Name.Location); } } @@ -952,7 +952,7 @@ private ConstantValue DecodeDefaultParameterValueAttribute(CSharpAttributeData a if (HasDefaultArgumentSyntax) { - // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute if (diagnose) { diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueUsedWithAttributes, node.Name.Location); diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 344d4b128b789..41fd691d27954 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -11327,8 +11327,8 @@ Potlačení upozornění zvažte jenom v případě, když určitě nechcete če - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - Nejde zadat výchozí hodnotu parametru v kombinaci s atributy DefaultParameterAttribute nebo OptionalAttribute. + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + Nejde zadat výchozí hodnotu parametru v kombinaci s atributy DefaultParameterAttribute nebo OptionalAttribute. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index d8cc687591ed3..301229db797c5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -11327,8 +11327,8 @@ Sie sollten das Unterdrücken der Warnung nur in Betracht ziehen, wenn Sie siche - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - Es kann kein Standardparameterwert in Verbindung mit "DefaultParameterAttribute" oder "OptionalAttribute" angegeben werden. + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + Es kann kein Standardparameterwert in Verbindung mit "DefaultParameterAttribute" oder "OptionalAttribute" angegeben werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 1bbebe82943bb..83575dbefe3a2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -11327,8 +11327,8 @@ Considere la posibilidad de suprimir la advertencia solo si tiene la seguridad d - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - No se puede especificar un valor de parámetro predeterminado junto con DefaultParameterAttribute u OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + No se puede especificar un valor de parámetro predeterminado junto con DefaultParameterAttribute u OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index cafe17844a0b4..a80bcf844e55d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -11327,8 +11327,8 @@ Supprimez l'avertissement seulement si vous êtes sûr de ne pas vouloir attendr - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - Impossible de spécifier une valeur de paramètre par défaut conjointement à DefaultParameterAttribute ou OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + Impossible de spécifier une valeur de paramètre par défaut conjointement à DefaultParameterAttribute ou OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index db97ace0ae56d..134add8f363ab 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -11327,8 +11327,8 @@ Come procedura consigliata, è consigliabile attendere sempre la chiamata. - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - Impossibile specificare un valore di parametro predefinito insieme a DefaultParameterAttribute o OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + Impossibile specificare un valore di parametro predefinito insieme a DefaultParameterAttribute o OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index a1ba411fc0134..e50469348d849 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -11327,8 +11327,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - DefaultParameterAttribute または OptionalAttribute と共に既定パラメーター値を指定することはできません + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + DefaultParameterAttribute または OptionalAttribute と共に既定パラメーター値を指定することはできません diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index dea7078e009e4..43c44b02c76e2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -11327,8 +11327,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - DefaultParameterAttribute 또는 OptionalAttribute와 함께 기본 매개 변수 값을 지정할 수 없습니다. + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + DefaultParameterAttribute 또는 OptionalAttribute와 함께 기본 매개 변수 값을 지정할 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 434cd933d2262..b3decad616b05 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -11327,8 +11327,8 @@ Pominięcie ostrzeżenia należy wziąć pod uwagę tylko w sytuacji, gdy na pew - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - Nie można określić wartości domyślnej parametru w połączeniu z klasami DefaultParameterAttribute lub OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + Nie można określić wartości domyślnej parametru w połączeniu z klasami DefaultParameterAttribute lub OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 7c7e74a0eb44b..a85e5effa2662 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -11327,8 +11327,8 @@ Você pode suprimir o aviso se tiver certeza de que não vai querer aguardar a c - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - Não é possível especificar um valor de parâmetro padrão junto com DefaultParameterAttribute ou OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + Não é possível especificar um valor de parâmetro padrão junto com DefaultParameterAttribute ou OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 96459e55e0274..55919fd6242c5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -11328,8 +11328,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - Не удалось указать значение параметра по умолчанию вместе с DefaultParameterAttribute или OptionalAttribute. + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + Не удалось указать значение параметра по умолчанию вместе с DefaultParameterAttribute или OptionalAttribute. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 85efa757102a7..9bd8e69dbf874 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -11327,8 +11327,8 @@ Yalnızca asenkron çağrının tamamlanmasını beklemek istemediğinizden ve - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - DefaultParameterAttribute veya OptionalAttribute ile birlikte varsayılan parametre değeri belirtilemez + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + DefaultParameterAttribute veya OptionalAttribute ile birlikte varsayılan parametre değeri belirtilemez diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index d05cbeb6be7e7..9170d809cbcb0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -11327,8 +11327,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - 不能同时指定默认参数值与 DefaultParameterAttribute 或 OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + 不能同时指定默认参数值与 DefaultParameterAttribute 或 OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index b30ef2cfe42ab..1e6772bc6a43b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -11327,8 +11327,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute - 不能連同 DefaultParameterAttribute 或 OptionalAttribute 一起指定預設參數值 + Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + 不能連同 DefaultParameterAttribute 或 OptionalAttribute 一起指定預設參數值 diff --git a/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs index cc001016cb53b..876153b624004 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs @@ -255,10 +255,10 @@ interface I delegate void D([DecimalConstant(0, 0, 0, 0, 3)]decimal b = 4); "; CreateCompilation(source).VerifyDiagnostics( - // (5,14): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (5,14): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // void F1([DefaultParameterValue(1)]int o = 2); Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(5, 14), - // (6,14): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (6,14): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // void F2([DefaultParameterValue(1)]decimal o = 2); Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(6, 14), // (6,51): error CS8017: The parameter has multiple distinct default values. @@ -267,7 +267,7 @@ interface I // (7,57): error CS8017: The parameter has multiple distinct default values. // void F4([DecimalConstant(0, 0, 0, 0, 1)]decimal o = 2); Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "2").WithLocation(7, 57), - // (8,35): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (8,35): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // void F6([DateTimeConstant(1), DefaultParameterValue(1), DecimalConstant(0, 0, 0, 0, 1)]int o = 1); Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(8, 35), // (8,61): error CS8017: The parameter has multiple distinct default values. @@ -279,13 +279,13 @@ interface I // (9,35): error CS8017: The parameter has multiple distinct default values. // void F7([DateTimeConstant(2), DecimalConstant(0, 0, 0, 0, 2), DefaultParameterValue(2)]decimal o = 2); Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "DecimalConstant(0, 0, 0, 0, 2)").WithLocation(9, 35), - // (9,67): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (9,67): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // void F7([DateTimeConstant(2), DecimalConstant(0, 0, 0, 0, 2), DefaultParameterValue(2)]decimal o = 2); Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(9, 67), // (9,104): error CS8017: The parameter has multiple distinct default values. // void F7([DateTimeConstant(2), DecimalConstant(0, 0, 0, 0, 2), DefaultParameterValue(2)]decimal o = 2); Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "2").WithLocation(9, 104), - // (10,25): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (10,25): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // object this[int a, [DefaultParameterValue(1)]int o = 2] { get; set; } Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(10, 25), // (10,58): error CS8017: The parameter has multiple distinct default values. diff --git a/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs b/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs index 12482bd5997b1..7359081866010 100644 --- a/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs @@ -4621,7 +4621,7 @@ class C } """; CreateCompilation(source).VerifyDiagnostics( - // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // static void M([DefaultParameterValue(1)] ref readonly int i = 1) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(4, 20), // (4,67): warning CS9200: A default value is specified for 'ref readonly' parameter 'i', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. @@ -4643,7 +4643,7 @@ class C } """; CreateCompilation(source).VerifyDiagnostics( - // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // static void M([Optional] ref readonly int i = 1) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(4, 20), // (4,51): warning CS9200: A default value is specified for 'ref readonly' parameter 'i', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. @@ -4662,10 +4662,10 @@ class C } """; CreateCompilation(source).VerifyDiagnostics( - // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // static void M([Optional, DefaultParameterValue(1)] ref readonly int i = 1) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(4, 20), - // (4,30): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (4,30): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // static void M([Optional, DefaultParameterValue(1)] ref readonly int i = 1) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(4, 30), // (4,77): warning CS9200: A default value is specified for 'ref readonly' parameter 'i', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. @@ -4797,7 +4797,7 @@ static void Main() } """; CreateCompilation(source).VerifyDiagnostics( - // (6,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (6,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // static void M2([Optional, DecimalConstant(1, 0, 0u, 0u, 11u)] ref readonly decimal d = 1.1m) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(6, 21), // (6,92): warning CS9200: A default value is specified for 'ref readonly' parameter 'd', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs index 49b55402cfecc..bebbfffb467bc 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs @@ -2497,7 +2497,7 @@ public static class Extensions // (3,15): error CS9284: The receiver parameter of an extension cannot have a default value // extension([System.Runtime.InteropServices.DefaultParameterValue(1)] int o = 2) { } Diagnostic(ErrorCode.ERR_ExtensionParameterDisallowsDefaultValue, "[System.Runtime.InteropServices.DefaultParameterValue(1)] int o = 2").WithLocation(3, 15), - // (3,16): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (3,16): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // extension([System.Runtime.InteropServices.DefaultParameterValue(1)] int o = 2) { } Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "System.Runtime.InteropServices.DefaultParameterValue").WithLocation(3, 16)); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NamedAndOptionalTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NamedAndOptionalTests.cs index 10ebc0f4cb410..ce2f5d8141272 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NamedAndOptionalTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NamedAndOptionalTests.cs @@ -962,13 +962,13 @@ public static int Main(){ } "; CreateCompilation(source).VerifyDiagnostics( - // (9,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (9,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // public int Bar([DefaultParameterValue(1)]int i = 2) { Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(9, 21), // (9,54): error CS8017: The parameter has multiple distinct default values. // public int Bar([DefaultParameterValue(1)]int i = 2) { Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "2").WithLocation(9, 54), - // (5,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (5,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // public int Goo([Optional]object i = null) { Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(5, 21) ); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 7315a2e033e0d..cccbae0f0badc 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -82159,10 +82159,10 @@ public void M3([Optional, DefaultParameterValue(null)] object obj = null) // (9,31): error CS8017: The parameter has multiple distinct default values. // public void M2([Optional, DefaultParameterValue(default)] object obj) Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "DefaultParameterValue(default)").WithLocation(9, 31), - // (13,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (13,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // public void M3([Optional, DefaultParameterValue(null)] object obj = null) Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(13, 21), - // (13,31): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (13,31): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // public void M3([Optional, DefaultParameterValue(null)] object obj = null) Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(13, 31), // (13,73): warning CS8625: Cannot convert null literal to non-nullable reference type. diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 35eeaa428bee8..7780a6bdfe315 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -16148,7 +16148,7 @@ public static void Main() { } } "; CreateCompilation(text).VerifyDiagnostics( - // (5,22): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + // (5,22): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute // public void goo([OptionalAttribute]int p = 1) Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "OptionalAttribute") ); From 51406f917334187a237630b40a4b090a70dc9f8e Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 5 Mar 2025 14:00:56 -0800 Subject: [PATCH 02/14] Expression trees: optional arguments --- .../CSharp/Portable/Errors/MessageID.cs | 2 + .../DiagnosticsPass_ExpressionTrees.cs | 2 +- ...xpressionOptionalAndNamedArgumentsTests.cs | 749 ++++++++++++++++++ 3 files changed, 752 insertions(+), 1 deletion(-) create mode 100644 src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs 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..afa06a0786fd9 100644 --- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs +++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs @@ -328,7 +328,7 @@ 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); } 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..613c71cd4e687 --- /dev/null +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -0,0 +1,749 @@ +// 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. + +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public class ExpressionOptionalAndNamedArgumentsTests : CSharpTestBase + { + // PROTOTYPE: Named arguments: Test overloads where the args are in order for one, but not the other. + // PROTOTYPE: Document breaking changes. Are additional overloads now considered (at least those with default parameters)? Test those cases with language version. + + [Theory] + [CombinatorialData] + public void OptionalParameter_01( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useIn, + bool useCompilationReference) + { + string refKind = useIn ? "in" : ""; + string sourceA = $$""" + public static class A + { + public static T GetValue({{refKind}} T t = default) => t; + } + """; + var comp = CreateCompilation(sourceA); + var refA = AsReference(comp, useCompilationReference); + + string sourceB = $$""" + using System; + using System.Linq.Expressions; + struct S + { + } + class Program + { + static void Main() + { + Report(A.GetValue()); + Report(A.GetValue()); + Report(A.GetValue()); + Report(Run(() => A.GetValue())); + Report(Run(() => A.GetValue())); + Report(Run(() => A.GetValue())); + } + static void Report(object arg) + { + Console.WriteLine(arg is null ? "null" : arg.ToString()); + } + static T Run(Expression> e) + { + var f = e.Compile(); + return f(); + } + } + """; + comp = CreateCompilation( + sourceB, + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyEmitDiagnostics( + // (13,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Report(Run(() => A.GetValue())); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(13, 26), + // (14,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Report(Run(() => A.GetValue())); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(14, 26), + // (15,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Report(Run(() => A.GetValue())); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(15, 26)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + 0 + null + S + 0 + null + S + """); + verifier.VerifyDiagnostics(); + } + } + + [Theory] + [CombinatorialData] + public void OptionalParameter_02(bool useIn, bool preferInterpretation, bool useCompilationReference) + { + string value = preferInterpretation ? "true" : "false"; + string refKind = useIn ? "in" : ""; + string sourceA = $$""" + 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 = $$""" + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Report(A.GetIntValue()); + Report(A.GetStringValue()); + Report(A.GetObjectValue()); + Report(Run(() => A.GetIntValue())); + Report(Run(() => A.GetStringValue())); + Report(Run(() => A.GetObjectValue())); + } + static void Report(object arg) + { + Console.WriteLine(arg is null ? "null" : arg.ToString()); + } + static T Run(Expression> e) + { + var f = e.Compile(preferInterpretation: {{value}}); + return f(); + } + } + """; + var verifier = CompileAndVerify( + sourceB, + references: [refA], + expectedOutput: """ + 10 + default + null + 10 + default + null + """); + verifier.VerifyDiagnostics(); + } + + [Theory] + [CombinatorialData] + public void OptionalParameter_AndParams(bool useIn, bool preferInterpretation, bool useCompilationReference) + { + string value = preferInterpretation ? "true" : "false"; + string refKind = useIn ? "in" : ""; + string sourceA = $$""" + 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 = $$""" + using System; + using System.Linq.Expressions; + struct S + { + } + class Program + { + static void Main() + { + Report(A.GetValue(1)); + Report(A.GetValue(2, 3, 4)); + Report(Run(() => A.GetValue(1))); + Report(Run(() => A.GetValue(2, 3, 4))); + } + static void Report(object arg) + { + Console.WriteLine(arg is null ? "null" : arg.ToString()); + } + static T Run(Expression> e) + { + var f = e.Compile(preferInterpretation: {{value}}); + return f(); + } + } + """; + var verifier = CompileAndVerify( + sourceB, + references: [refA], + expectedOutput: """ + 0 + 3 + 0 + 3 + """); + verifier.VerifyDiagnostics(); + } + + [Theory] + [CombinatorialData] + public void OptionalParameter_Constructor( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useCompilationReference) + { + 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; } + } + """; + var comp = CreateCompilation(sourceA); + var refA = AsReference(comp, useCompilationReference); + + string sourceB = $$""" + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Report(new A("str")); + Report(new A()); + Report(Run(() => new A("str"))); + Report(Run(() => new A())); + } + static void Report(A a) + { + Console.WriteLine((a.X, a.Y)); + } + static T Run(Expression> e) + { + var f = e.Compile(); + return f(); + } + } + """; + comp = CreateCompilation( + sourceB, + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyEmitDiagnostics( + // (9,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Report(Run(() => new A("str"))); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, @"new A(""str"")").WithLocation(9, 26), + // (10,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Report(Run(() => new A())); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "new A()").WithLocation(10, 26)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + (str, 10) + (default, 10) + (str, 10) + (default, 10) + """); + verifier.VerifyDiagnostics(); + } + } + + [Theory] + [CombinatorialData] + public void OptionalParameter_Indexer( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useCompilationReference) + { + string sourceA = $$""" + public class A + { + public int this[int x, int y = 10] => y; + } + """; + var comp = CreateCompilation(sourceA); + var refA = AsReference(comp, useCompilationReference); + + string sourceB = $$""" + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + var a = new A(); + Console.WriteLine(a[1, 2]); + Console.WriteLine(a[3]); + Console.WriteLine(Run(() => a[1, 2])); + Console.WriteLine(Run(() => a[3])); + } + static T Run(Expression> e) + { + var f = e.Compile(); + return f(); + } + } + """; + comp = CreateCompilation( + sourceB, + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyEmitDiagnostics( + // (11,37): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Console.WriteLine(Run(() => a[3])); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "a[3]").WithLocation(11, 37)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + 2 + 10 + 2 + 10 + """); + verifier.VerifyDiagnostics(); + } + } + + [Theory] + [CombinatorialData] + public void OptionalParameter_Delegate( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useCompilationReference) + { + string sourceA = $$""" + public delegate int D(int x, in int y = 10); + """; + var comp = CreateCompilation(sourceA); + var refA = AsReference(comp, useCompilationReference); + + string sourceB = $$""" + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + D d = F; + Console.WriteLine(d(1, 2)); + Console.WriteLine(d(3)); + Console.WriteLine(Run(() => d(1, 2))); + Console.WriteLine(Run(() => d(3))); + } + static T Run(Expression> e) + { + var f = e.Compile(); + return f(); + } + static T F(T x, in T y) => y; + } + """; + comp = CreateCompilation( + sourceB, + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyEmitDiagnostics( + // (11,37): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Console.WriteLine(Run(() => d(3))); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "d(3)").WithLocation(11, 37)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + 2 + 10 + 2 + 10 + """); + verifier.VerifyDiagnostics(); + } + } + + [Theory] + [CombinatorialData] + public void OptionalParameter_CollectionInitializer( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useIn) + { + string refKind = useIn ? "in" : ""; + string sourceA = $$""" + using System.Collections; + using System.Collections.Generic; + 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(); + } + """; + string sourceB = """ + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Report(new MyCollection() { { "one", 1 }, { "two" } }); + Report(Run(() => new MyCollection() { { "one", 1 }, { "two" } })); + } + static void Report(MyCollection c) + { + foreach (var kvp in c) + System.Console.WriteLine("{0}, {1}", kvp.Key, kvp.Value); + } + static T Run(Expression> e) + { + var f = e.Compile(); + return f(); + } + } + """; + var comp = CreateCompilation( + [sourceA, sourceB], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyEmitDiagnostics( + // (8,74): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Report(Run(() => new MyCollection() { { "one", 1 }, { "two" } })); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, @"{ ""two"" }").WithLocation(8, 74)); + } + else if (useIn) + { + // Expression does not support initializers with ref parameters at runtime. + comp.VerifyEmitDiagnostics(); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + one, 1 + two, 0 + one, 1 + two, 0 + """); + verifier.VerifyDiagnostics(); + } + } + + [Theory] + [CombinatorialData] + public void OptionalParameter_LocalFunction( + [CombinatorialValues(LanguageVersion.CSharp13, 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 preferInterpretation, bool useCompilationReference) + { + string value = preferInterpretation ? "true" : "false"; + 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 = $$""" + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Console.WriteLine(A.GetValue()); + Console.WriteLine(Run(() => A.GetValue(200))); + Console.WriteLine(Run(() => A.GetValue())); + } + static T Run(Expression> e) + { + var f = e.Compile(preferInterpretation: {{value}}); + return f(); + } + } + """; + var verifier = CompileAndVerify( + sourceB, + references: [refA], + expectedOutput: """ + 100 + 200 + 100 + """); + verifier.VerifyDiagnostics(); + } + + [Theory] + [CombinatorialData] + public void DateTime_01(bool preferInterpretation, bool useCompilationReference) + { + string value = preferInterpretation ? "true" : "false"; + 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; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Console.WriteLine(A.GetValue().Ticks); + Console.WriteLine(Run(() => A.GetValue(new DateTime(200))).Ticks); + Console.WriteLine(Run(() => A.GetValue()).Ticks); + } + static T Run(Expression> e) + { + var f = e.Compile(preferInterpretation: {{value}}); + return f(); + } + } + """; + var verifier = CompileAndVerify( + sourceB, + references: [refA], + expectedOutput: """ + 100 + 200 + 100 + """); + verifier.VerifyDiagnostics(); + } + + [Theory] + [CombinatorialData] + public void DateTime_02(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 = $$""" + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Console.WriteLine(A.GetValue().Ticks); + Console.WriteLine(Run(() => A.GetValue()).Ticks); + } + static T Run(Expression> e) + { + var f = e.Compile(); + return f(); + } + } + """; + comp = CreateCompilation(sourceB, references: [refA]); + comp.VerifyEmitDiagnostics( + // (7,29): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(DateTime)' + // Console.WriteLine(A.GetValue().Ticks); + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(System.DateTime)").WithLocation(7, 29), + // (8,39): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(DateTime)' + // Console.WriteLine(Run(() => A.GetValue()).Ticks); + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(System.DateTime)").WithLocation(8, 39)); + } + + [Theory] + [CombinatorialData] + public void OptionalAndDefaultParameterValue(bool includeOptional, bool includeDefaultParameterValue, 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 = """ + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Console.WriteLine(A.GetValue()); + Console.WriteLine(Run(() => A.GetValue(200))); + Console.WriteLine(Run(() => A.GetValue())); + } + static T Run(Expression> e) + { + var f = e.Compile(); + return f(); + } + } + """; + comp = CreateCompilation(sourceB, references: [refA], options: TestOptions.ReleaseExe); + if (includeOptional) + { + string optionalValue = includeDefaultParameterValue ? "100" : "0"; + var verifier = CompileAndVerify( + comp, + expectedOutput: $$""" + {{optionalValue}} + 200 + {{optionalValue}} + """); + verifier.VerifyDiagnostics(); + } + else + { + comp.VerifyEmitDiagnostics( + // (7,29): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(int)' + // Console.WriteLine(A.GetValue()); + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(int)").WithLocation(7, 29), + // (9,39): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(int)' + // Console.WriteLine(Run(() => A.GetValue())); + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(int)").WithLocation(9, 39)); + } + } + + [Theory] + [CombinatorialData] + public void OptionalParams(bool includeDefaultParameterValue, bool useCompilationReference) + { + string sourceA = $$""" + using System.Runtime.InteropServices; + public static class A + { + public static object[] GetValue( + [Optional] + {{(includeDefaultParameterValue ? "[DefaultParameterValue(null)]" : "")}} + params object[] args) => args; + } + """; + var comp = CreateCompilation(sourceA); + var refA = AsReference(comp, useCompilationReference); + + string sourceB = """ + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Report(A.GetValue(1, 2, 3)); + Report(A.GetValue()); + Report(Run(() => A.GetValue(1, 2, 3))); + Report(Run(() => A.GetValue())); + } + static void Report(object[] args) + { + Console.WriteLine(args is null ? "null" : args.Length.ToString()); + } + static T Run(Expression> e) + { + var f = e.Compile(); + return f(); + } + } + """; + var verifier = CompileAndVerify( + sourceB, + references: [refA], + expectedOutput: """ + 3 + 0 + 3 + 0 + """); + verifier.VerifyDiagnostics(); + } + } +} From 4c2c64e2a31f31308f1adf8e8793170a22fe863d Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Thu, 3 Apr 2025 20:29:54 -0700 Subject: [PATCH 03/14] Fix tests --- .../Emit/CodeGen/CodeGenExprLambdaTests.cs | 25 ++++-- ...xpressionOptionalAndNamedArgumentsTests.cs | 14 ++- .../Semantic/Semantics/SemanticErrorTests.cs | 88 ++++++++++++++----- 3 files changed, 87 insertions(+), 40 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs index 2a479263ed080..8d381df612ae4 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs @@ -2595,8 +2595,10 @@ static void Main() CompileAndVerifyUtil(text, expectedOutput: TrimExpectedOutput(expectedOutput)); } - [Fact] - public void MethodCallWithParams3() + [Theory] + [InlineData(LanguageVersion.CSharp13)] + [InlineData(LanguageVersionFacts.CSharpNext)] + public void MethodCallWithParams3(LanguageVersion languageVersion) { var text = @"using System; @@ -2612,12 +2614,19 @@ 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)); + 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 + { + comp.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 index 613c71cd4e687..97824f248e6bb 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -93,9 +93,8 @@ static T Run(Expression> e) [Theory] [CombinatorialData] - public void OptionalParameter_02(bool useIn, bool preferInterpretation, bool useCompilationReference) + public void OptionalParameter_02(bool useIn, bool useCompilationReference) { - string value = preferInterpretation ? "true" : "false"; string refKind = useIn ? "in" : ""; string sourceA = $$""" public static class A @@ -128,7 +127,7 @@ static void Report(object arg) } static T Run(Expression> e) { - var f = e.Compile(preferInterpretation: {{value}}); + var f = e.Compile(); return f(); } } @@ -149,9 +148,8 @@ static T Run(Expression> e) [Theory] [CombinatorialData] - public void OptionalParameter_AndParams(bool useIn, bool preferInterpretation, bool useCompilationReference) + public void OptionalParameter_AndParams(bool useIn, bool useCompilationReference) { - string value = preferInterpretation ? "true" : "false"; string refKind = useIn ? "in" : ""; string sourceA = $$""" public static class A @@ -183,7 +181,7 @@ static void Report(object arg) } static T Run(Expression> e) { - var f = e.Compile(preferInterpretation: {{value}}); + var f = e.Compile(); return f(); } } @@ -530,7 +528,7 @@ static void Main() } static T Run(Expression> e) { - var f = e.Compile(preferInterpretation: {{value}}); + var f = e.Compile(); return f(); } } @@ -576,7 +574,7 @@ static void Main() } static T Run(Expression> e) { - var f = e.Compile(preferInterpretation: {{value}}); + var f = e.Compile(); return f(); } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index c3a4b47e22d63..2542a831f9e0d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -13134,8 +13134,10 @@ static void Main() ); } - [Fact] - public void CS0854ERR_ExpressionTreeContainsOptionalArgument01() + [Theory] + [InlineData(LanguageVersion.CSharp13)] + [InlineData(LanguageVersionFacts.CSharpNext)] + public void CS0854ERR_ExpressionTreeContainsOptionalArgument01(LanguageVersion languageVersion) { var text = @" using System.Linq.Expressions; @@ -13155,15 +13157,25 @@ public static string Index(int minSessions = 0) } } "; - CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics( - // (10,40): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Expression myET = x => Index(); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "Index()").WithLocation(10, 40) - ); + var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyDiagnostics( + // (10,40): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Expression myET = x => Index(); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "Index()").WithLocation(10, 40) + ); + } + else + { + comp.VerifyDiagnostics(); + } } - [Fact] - public void CS0854ERR_ExpressionTreeContainsOptionalArgument02() + [Theory] + [InlineData(LanguageVersion.CSharp13)] + [InlineData(LanguageVersionFacts.CSharpNext)] + public void CS0854ERR_ExpressionTreeContainsOptionalArgument02(LanguageVersion languageVersion) { var text = @"using System; @@ -13194,19 +13206,39 @@ static void M(A a, B b) e2 = () => b[4, 5] = null; } }"; - CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics( - // (22,20): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "a[0]").WithLocation(22, 20), - // (25,20): error CS0832: An expression tree may not contain an assignment operator - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "b[3] = null").WithLocation(25, 20), - // (25,20): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "b[3]").WithLocation(25, 20), - // (26,20): error CS0832: An expression tree may not contain an assignment operator - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "b[4, 5] = null").WithLocation(26, 20)); + var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyDiagnostics( + // (22,20): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // e1 = () => a[0]; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "a[0]").WithLocation(22, 20), + // (25,20): error CS0832: An expression tree may not contain an assignment operator + // e2 = () => b[3] = null; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "b[3] = null").WithLocation(25, 20), + // (25,20): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // e2 = () => b[3] = null; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "b[3]").WithLocation(25, 20), + // (26,20): error CS0832: An expression tree may not contain an assignment operator + // e2 = () => b[4, 5] = null; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "b[4, 5] = null").WithLocation(26, 20)); + } + else + { + comp.VerifyDiagnostics( + // (25,20): error CS0832: An expression tree may not contain an assignment operator + // e2 = () => b[3] = null; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "b[3] = null").WithLocation(25, 20), + // (26,20): error CS0832: An expression tree may not contain an assignment operator + // e2 = () => b[4, 5] = null; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "b[4, 5] = null").WithLocation(26, 20)); + } } - [Fact] - public void CS0854ERR_ExpressionTreeContainsOptionalArgument03() + [Theory] + [InlineData(LanguageVersion.CSharp13)] + [InlineData(LanguageVersionFacts.CSharpNext)] + public void CS0854ERR_ExpressionTreeContainsOptionalArgument03(LanguageVersion languageVersion) { var text = @"using System; @@ -13229,10 +13261,18 @@ public void M() { () => new Collection { 1 }; // 1 } }"; - CreateCompilation(text).VerifyDiagnostics( - // (18,36): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // () => new Collection { 1 }; // 1 - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "1").WithLocation(18, 36)); + var comp = CreateCompilation(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyDiagnostics( + // (18,36): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // () => new Collection { 1 }; // 1 + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "1").WithLocation(18, 36)); + } + else + { + comp.VerifyDiagnostics(); + } } [Fact] From 4c1098223d7aa6305307951a202e25eeb417cd0f Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:42:32 -0700 Subject: [PATCH 04/14] Expression trees: named arguments --- .../DiagnosticsPass_ExpressionTrees.cs | 2 +- ...xpressionOptionalAndNamedArgumentsTests.cs | 824 +++++++++++++++++- 2 files changed, 820 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs index afa06a0786fd9..9bda4206fd89c 100644 --- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs +++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs @@ -332,7 +332,7 @@ private void VisitCall( { Error(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, node); } - else if (!argumentNamesOpt.IsDefaultOrEmpty) + else if (!argumentNamesOpt.IsDefaultOrEmpty && !_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments)) // PROTOTYPE: Check arguments are in order. { Error(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, node); } diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs index 97824f248e6bb..3dba9be93f598 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -9,8 +9,47 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class ExpressionOptionalAndNamedArgumentsTests : CSharpTestBase { - // PROTOTYPE: Named arguments: Test overloads where the args are in order for one, but not the other. // PROTOTYPE: Document breaking changes. Are additional overloads now considered (at least those with default parameters)? Test those cases with language version. + // PROTOTYPE: Test unrecognized name. + // PROTOTYPE: Test name when parameter name is duplicated. + + // PROTOTYPE: Use this for optional argument tests as well. + 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(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(value is null ? "null" : value.ToString()); + } + public static T Run(Func f) + { + return f(); + } + } + """; + } [Theory] [CombinatorialData] @@ -674,10 +713,10 @@ static T Run(Expression> e) var verifier = CompileAndVerify( comp, expectedOutput: $$""" - {{optionalValue}} - 200 - {{optionalValue}} - """); + {{optionalValue}} + 200 + {{optionalValue}} + """); verifier.VerifyDiagnostics(); } else @@ -743,5 +782,780 @@ static T Run(Expression> e) """); verifier.VerifyDiagnostics(); } + + [Theory] + [CombinatorialData] + public void NamedArgument_01( + [CombinatorialValues(LanguageVersion.CSharp13, 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: """ + 1 + 1 + 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 (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 + { + 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, 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: """ + 1 + 1 + 1 + 1 + 1 + 1 + 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 (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 + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + 1 + 1 + null + null + null + null + null + """); + verifier.VerifyDiagnostics(); + } + } + + [Theory] + [CombinatorialData] + public void NamedArgument_03( + [CombinatorialValues(LanguageVersion.CSharp13, 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: """ + (1, 0) + (1, 1) + (1, 2) + (1, ) + (1, 2) + (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 (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 + { + 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, 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()); + Utils.Report(() => A.GetSecondAndParamsLength(first: 1)); + Utils.Report(() => A.GetSecondAndParamsLength(first: 1, 2)); + Utils.Report(() => A.GetSecondAndParamsLength(first: 1, 2, 3, 4)); + Utils.Report(() => A.GetSecondAndParamsLength(first: 1, second: 2)); + Utils.Report(() => A.GetSecondAndParamsLength(first: 1, second: 2, more: default)); + Utils.Report(() => A.GetSecondAndParamsLength(first: 1, 2, more: new[] { 3 })); + Utils.Report(() => A.GetSecondAndParamsLength(1)); + Utils.Report(() => A.GetSecondAndParamsLength(1, second: 2)); + Utils.Report(() => A.GetSecondAndParamsLength(1, second: 2, 3, 4)); + Utils.Report(() => A.GetSecondAndParamsLength(1, second: 2, more: default)); + Utils.Report(() => A.GetSecondAndParamsLength(1, 2, 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 CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Utils.Report(() => A.GetSecondAndParamsLength()); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetSecondAndParamsLength()").WithLocation(5, 28), + // (6,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetSecondAndParamsLength(first: 1)").WithLocation(6, 28), + // (7,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, 2)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(first: 1, 2)").WithLocation(7, 28), + // (8,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, 2, 3, 4)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(first: 1, 2, 3, 4)").WithLocation(8, 28), + // (9,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, second: 2)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(first: 1, second: 2)").WithLocation(9, 28), + // (10,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, second: 2, more: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(first: 1, second: 2, more: default)").WithLocation(10, 28), + // (11,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, 2, more: new[] { 3 })); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(first: 1, 2, more: new[] { 3 })").WithLocation(11, 28), + // (12,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Utils.Report(() => A.GetSecondAndParamsLength(1)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetSecondAndParamsLength(1)").WithLocation(12, 28), + // (13,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(1, second: 2)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(1, second: 2)").WithLocation(13, 28), + // (14,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(1, second: 2, 3, 4)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(1, second: 2, 3, 4)").WithLocation(14, 28), + // (15,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(1, second: 2, more: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(1, second: 2, more: default)").WithLocation(15, 28), + // (16,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(1, 2, more: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(1, 2, more: default)").WithLocation(16, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + (, 0) + (0, 0) + (2, 0) + (2, 2) + (2, 0) + (2, ) + (2, 1) + (0, 0) + (2, 0) + (2, 2) + (2, ) + (2, ) + """); + verifier.VerifyDiagnostics(); + } + + string sourceB2 = $$""" + class Program + { + static void Main() + { + Utils.Report(() => A.GetSecondAndParamsLength(first: 1, second: 2, 3, 4)); + Utils.Report(() => A.GetSecondAndParamsLength(first: 1, more: default, second: 2)); + Utils.Report(() => A.GetSecondAndParamsLength(first: 1, more: default)); + Utils.Report(() => A.GetSecondAndParamsLength(second: 2)); + Utils.Report(() => A.GetSecondAndParamsLength(second: 2, first: 1)); + Utils.Report(() => A.GetSecondAndParamsLength(second: 2, more: default)); + Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 })); + Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)); + } + } + """; + comp = CreateCompilation( + [sourceB2, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (useExpression) + { + comp.VerifyEmitDiagnostics( + // (5,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, second: 2, 3, 4)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(first: 1, second: 2, 3, 4)").WithLocation(5, 28), + // (6,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, more: default, second: 2)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(first: 1, more: default, second: 2)").WithLocation(6, 28), + // (7,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, more: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetSecondAndParamsLength(first: 1, more: default)").WithLocation(7, 28), + // (8,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetSecondAndParamsLength(second: 2)").WithLocation(8, 28), + // (9,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, first: 1)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(second: 2, first: 1)").WithLocation(9, 28), + // (10,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, more: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetSecondAndParamsLength(second: 2, more: default)").WithLocation(10, 28), + // (11,28): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 })); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetSecondAndParamsLength(more: new[] { 3, 4 })").WithLocation(11, 28), + // (12,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)").WithLocation(12, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + (2, 2) + (2, ) + (0, ) + (2, 0) + (2, 0) + (2, ) + (0, 2) + (2, 2) + """); + verifier.VerifyDiagnostics(); + } + + string sourceB3 = $$""" + class Program + { + static void Main() + { + Utils.Report(() => A.GetSecondAndParamsLength(second: 2, default)); + Utils.Report(() => A.GetSecondAndParamsLength(second: 2, first: 1, default)); + Utils.Report(() => A.GetSecondAndParamsLength(second: 2, first: 1, 3, 4)); + Utils.Report(() => A.GetSecondAndParamsLength(second: 2, more: default, 1)); + Utils.Report(() => A.GetSecondAndParamsLength(more: default, default)); + } + } + """; + comp = CreateCompilation( + [sourceB3, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + comp.VerifyEmitDiagnostics( + // (5,55): error CS8323: Named argument 'second' is used out-of-position but is followed by an unnamed argument + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, default)); + Diagnostic(ErrorCode.ERR_BadNonTrailingNamedArgument, "second").WithArguments("second").WithLocation(5, 55), + // (6,55): error CS8323: Named argument 'second' is used out-of-position but is followed by an unnamed argument + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, first: 1, default)); + Diagnostic(ErrorCode.ERR_BadNonTrailingNamedArgument, "second").WithArguments("second").WithLocation(6, 55), + // (7,55): error CS8323: Named argument 'second' is used out-of-position but is followed by an unnamed argument + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, first: 1, 3, 4)); + Diagnostic(ErrorCode.ERR_BadNonTrailingNamedArgument, "second").WithArguments("second").WithLocation(7, 55), + // (8,55): error CS8323: Named argument 'second' is used out-of-position but is followed by an unnamed argument + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, more: default, 1)); + Diagnostic(ErrorCode.ERR_BadNonTrailingNamedArgument, "second").WithArguments("second").WithLocation(8, 55), + // (9,63): error CS8323: Named argument 'more' is used out-of-position but is followed by an unnamed argument + // Utils.Report(() => A.GetSecondAndParamsLength(more: default, default)); + Diagnostic(ErrorCode.ERR_BadNonTrailingNamedArgument, "more").WithArguments("more").WithLocation(9, 63)); + } + + [Theory] + [CombinatorialData] + public void NamedArgument_OverloadsDifferentOrder( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useExpression, + bool useCompilationReference) + { + string sourceA = $$""" + public static class A + { + public static int GetFirst(int first, int second) => first; + public static string GetFirst(string second, string first) => first ?? "null"; + } + """; + var comp = CreateCompilation(sourceA); + var refA = AsReference(comp, useCompilationReference); + + string sourceB1 = $$""" + class Program + { + static void Main() + { + Utils.Report(() => A.GetFirst(first: 1, second: 2)); + Utils.Report(() => A.GetFirst(second: "two", first: "one")); + } + } + """; + 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)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(first: 1, second: 2)").WithLocation(5, 28), + // (6,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetFirst(second: "two", first: "one")); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"A.GetFirst(second: ""two"", first: ""one"")").WithLocation(6, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + 1 + one + """); + verifier.VerifyDiagnostics(); + } + + string sourceB2 = $$""" + class Program + { + static void Main() + { + Utils.Report(() => A.GetFirst(second: 2, first: 1)); + Utils.Report(() => A.GetFirst(first: "one", second: "two")); + Utils.Report(() => A.GetFirst(first: default, default)); + Utils.Report(() => A.GetFirst(second: default, default)); + Utils.Report(() => A.GetFirst(default, second: default)); + Utils.Report(() => A.GetFirst(default, first: default)); + } + } + """; + 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), + // (6,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetFirst(first: "one", second: "two")); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"A.GetFirst(first: ""one"", second: ""two"")").WithLocation(6, 28), + // (7,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetFirst(first: default, default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(first: default, default)").WithLocation(7, 28), + // (8,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetFirst(second: default, default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(second: default, default)").WithLocation(8, 28), + // (9,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetFirst(default, second: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(default, second: default)").WithLocation(9, 28), + // (10,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => A.GetFirst(default, first: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(default, first: default)").WithLocation(10, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + 1 + one + 0 + null + 0 + null + """); + verifier.VerifyDiagnostics(); + } + + string sourceB3 = $$""" + class Program + { + static void Main() + { + Utils.Report(() => A.GetFirst(first: default, second: default)); + Utils.Report(() => A.GetFirst(second: default, first: default)); + } + } + """; + comp = CreateCompilation( + [sourceB3, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + comp.VerifyEmitDiagnostics( + // (5,30): error CS0121: The call is ambiguous between the following methods or properties: 'A.GetFirst(int, int)' and 'A.GetFirst(string, string)' + // Utils.Report(() => A.GetFirst(first: default, second: default)); + Diagnostic(ErrorCode.ERR_AmbigCall, "GetFirst").WithArguments("A.GetFirst(int, int)", "A.GetFirst(string, string)").WithLocation(5, 30), + // (6,30): error CS0121: The call is ambiguous between the following methods or properties: 'A.GetFirst(int, int)' and 'A.GetFirst(string, string)' + // Utils.Report(() => A.GetFirst(second: default, first: default)); + Diagnostic(ErrorCode.ERR_AmbigCall, "GetFirst").WithArguments("A.GetFirst(int, int)", "A.GetFirst(string, string)").WithLocation(6, 30)); + } + + [Theory] + [CombinatorialData] + public void NamedArgument_LocalFunction( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion) + { + string source = """ + using System; + using System.Linq.Expressions; + class Program + { + static void Main() + { + Expression> e; + T GetFirst(T first, T second) => first; + GetFirst(first: 1, 2); + GetFirst(1, second: 2); + GetFirst(second: 2, first: 1); + e = () => GetFirst(first: 1, 2); + e = () => GetFirst(1, second: 2); + e = () => GetFirst(second: 2, first: 1); + } + } + """; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyEmitDiagnostics( + // (12,19): error CS0853: An expression tree may not contain a named argument specification + // e = () => GetFirst(first: 1, 2); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "GetFirst(first: 1, 2)").WithLocation(12, 19), + // (13,19): error CS0853: An expression tree may not contain a named argument specification + // e = () => GetFirst(1, second: 2); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "GetFirst(1, second: 2)").WithLocation(13, 19), + // (14,19): error CS0853: An expression tree may not contain a named argument specification + // e = () => GetFirst(second: 2, first: 1); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "GetFirst(second: 2, first: 1)").WithLocation(14, 19)); + } + else + { + comp.VerifyEmitDiagnostics( + // (12,19): error CS8110: An expression tree may not contain a reference to a local function + // e = () => GetFirst(first: 1, 2); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "GetFirst(first: 1, 2)").WithLocation(12, 19), + // (13,19): error CS8110: An expression tree may not contain a reference to a local function + // e = () => GetFirst(1, second: 2); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "GetFirst(1, second: 2)").WithLocation(13, 19), + // (14,19): error CS0853: An expression tree may not contain a named argument specification + // e = () => GetFirst(second: 2, first: 1); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "GetFirst(second: 2, first: 1)").WithLocation(14, 19)); + } + } } } From 32d059a48427ed050b86e0ce55e2923e203e1d85 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:16:53 -0700 Subject: [PATCH 05/14] Expression trees: named arguments --- .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../DiagnosticsPass_ExpressionTrees.cs | 44 +- .../Portable/xlf/CSharpResources.cs.xlf | 5 + .../Portable/xlf/CSharpResources.de.xlf | 5 + .../Portable/xlf/CSharpResources.es.xlf | 5 + .../Portable/xlf/CSharpResources.fr.xlf | 5 + .../Portable/xlf/CSharpResources.it.xlf | 5 + .../Portable/xlf/CSharpResources.ja.xlf | 5 + .../Portable/xlf/CSharpResources.ko.xlf | 5 + .../Portable/xlf/CSharpResources.pl.xlf | 5 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 5 + .../Portable/xlf/CSharpResources.ru.xlf | 5 + .../Portable/xlf/CSharpResources.tr.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 5 + ...xpressionOptionalAndNamedArgumentsTests.cs | 844 ++++++++++++------ .../Semantic/Semantics/SemanticErrorTests.cs | 49 +- 18 files changed, 702 insertions(+), 304 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 7fd9b1384ea79..8c3276a823e1a 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 3ee0557087076..a5085f989cf15 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2389,6 +2389,7 @@ internal enum ErrorCode ERR_PPIgnoredFollowsToken = 9297, ERR_PPIgnoredNeedsFileBasedProgram = 9298, ERR_PPIgnoredFollowsIf = 9299, + ERR_ExpressionTreeContainsNamedArgumentOutOfPosition = 9300, // 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/Lowering/DiagnosticsPass_ExpressionTrees.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs index 9bda4206fd89c..ad3d0261b8307 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) && !_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments)) + else if (hasDefaultArgument(arguments, defaultArguments) && + !_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments)) { Error(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, node); } - else if (!argumentNamesOpt.IsDefaultOrEmpty && !_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments)) // PROTOTYPE: Check arguments are in order. + else if (!argumentNamesOpt.IsDefaultOrEmpty && + !_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments)) { Error(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, node); } + else if (!argumentNamesOpt.IsDefaultOrEmpty && + _compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments) && + hasNamedArgumentOutOfOrder(argsToParamsOpt)) + { + 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 41fd691d27954..521b19b70b712 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 301229db797c5..e053bf86aef4e 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 83575dbefe3a2..2391b36dafa0d 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 a80bcf844e55d..66522d1778117 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 134add8f363ab..8c023246bf9fb 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 e50469348d849..347c9fdb345ed 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 43c44b02c76e2..1a2df1b56ecc3 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 b3decad616b05..e3f673d108874 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 a85e5effa2662..2852841fa1e68 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 55919fd6242c5..1a43834fcad56 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 9bd8e69dbf874..8b54c792b7466 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 9170d809cbcb0..2f4dd751e9457 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 1e6772bc6a43b..4ee88b61a387e 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/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs index 3dba9be93f598..110b4a93bd19e 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -3,17 +3,13 @@ // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class ExpressionOptionalAndNamedArgumentsTests : CSharpTestBase { - // PROTOTYPE: Document breaking changes. Are additional overloads now considered (at least those with default parameters)? Test those cases with language version. - // PROTOTYPE: Test unrecognized name. - // PROTOTYPE: Test name when parameter name is duplicated. - - // PROTOTYPE: Use this for optional argument tests as well. private static string GetUtilities(bool useExpression) { return useExpression ? @@ -56,6 +52,7 @@ public static T Run(Func f) public void OptionalParameter_01( [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useIn, + bool useExpression, bool useCompilationReference) { string refKind = useIn ? "in" : ""; @@ -69,8 +66,6 @@ public static class A var refA = AsReference(comp, useCompilationReference); string sourceB = $$""" - using System; - using System.Linq.Expressions; struct S { } @@ -78,41 +73,29 @@ class Program { static void Main() { - Report(A.GetValue()); - Report(A.GetValue()); - Report(A.GetValue()); - Report(Run(() => A.GetValue())); - Report(Run(() => A.GetValue())); - Report(Run(() => A.GetValue())); - } - static void Report(object arg) - { - Console.WriteLine(arg is null ? "null" : arg.ToString()); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => A.GetValue()); + Utils.Report(() => A.GetValue()); + Utils.Report(() => A.GetValue()); } } """; comp = CreateCompilation( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (languageVersion == LanguageVersion.CSharp13) + if (languageVersion == LanguageVersion.CSharp13 && useExpression) { comp.VerifyEmitDiagnostics( - // (13,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Report(Run(() => A.GetValue())); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(13, 26), - // (14,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Report(Run(() => A.GetValue())); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(14, 26), - // (15,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Report(Run(() => A.GetValue())); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetValue()").WithLocation(15, 26)); + // (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 { @@ -122,9 +105,6 @@ static T Run(Expression> e) 0 null S - 0 - null - S """); verifier.VerifyDiagnostics(); } @@ -132,7 +112,10 @@ static T Run(Expression> e) [Theory] [CombinatorialData] - public void OptionalParameter_02(bool useIn, bool useCompilationReference) + public void OptionalParameter_02( + bool useIn, + bool useExpression, + bool useCompilationReference) { string refKind = useIn ? "in" : ""; string sourceA = $$""" @@ -147,37 +130,20 @@ public static class A var refA = AsReference(comp, useCompilationReference); string sourceB = $$""" - using System; - using System.Linq.Expressions; class Program { static void Main() { - Report(A.GetIntValue()); - Report(A.GetStringValue()); - Report(A.GetObjectValue()); - Report(Run(() => A.GetIntValue())); - Report(Run(() => A.GetStringValue())); - Report(Run(() => A.GetObjectValue())); - } - static void Report(object arg) - { - Console.WriteLine(arg is null ? "null" : arg.ToString()); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => A.GetIntValue()); + Utils.Report(() => A.GetStringValue()); + Utils.Report(() => A.GetObjectValue()); } } """; var verifier = CompileAndVerify( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], expectedOutput: """ - 10 - default - null 10 default null @@ -187,7 +153,10 @@ static T Run(Expression> e) [Theory] [CombinatorialData] - public void OptionalParameter_AndParams(bool useIn, bool useCompilationReference) + public void OptionalParameter_AndParams( + bool useIn, + bool useExpression, + bool useCompilationReference) { string refKind = useIn ? "in" : ""; string sourceA = $$""" @@ -200,8 +169,6 @@ public static class A var refA = AsReference(comp, useCompilationReference); string sourceB = $$""" - using System; - using System.Linq.Expressions; struct S { } @@ -209,28 +176,15 @@ class Program { static void Main() { - Report(A.GetValue(1)); - Report(A.GetValue(2, 3, 4)); - Report(Run(() => A.GetValue(1))); - Report(Run(() => A.GetValue(2, 3, 4))); - } - static void Report(object arg) - { - Console.WriteLine(arg is null ? "null" : arg.ToString()); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => A.GetValue(1)); + Utils.Report(() => A.GetValue(2, 3, 4)); } } """; var verifier = CompileAndVerify( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], expectedOutput: """ - 0 - 3 0 3 """); @@ -241,7 +195,7 @@ static T Run(Expression> e) [CombinatorialData] public void OptionalParameter_Constructor( [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, - bool useCompilationReference) + bool useExpression) { string sourceA = $$""" public class A @@ -249,48 +203,36 @@ 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 = AsReference(comp, useCompilationReference); + var refA = comp.EmitToImageReference(); string sourceB = $$""" - using System; - using System.Linq.Expressions; class Program { static void Main() { - Report(new A("str")); - Report(new A()); - Report(Run(() => new A("str"))); - Report(Run(() => new A())); - } - static void Report(A a) - { - Console.WriteLine((a.X, a.Y)); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => new A("str")); + Utils.Report(() => new A()); } } """; comp = CreateCompilation( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (languageVersion == LanguageVersion.CSharp13) + if (languageVersion == LanguageVersion.CSharp13 && useExpression) { comp.VerifyEmitDiagnostics( - // (9,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Report(Run(() => new A("str"))); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, @"new A(""str"")").WithLocation(9, 26), - // (10,26): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Report(Run(() => new A())); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "new A()").WithLocation(10, 26)); + // (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 { @@ -299,8 +241,6 @@ static T Run(Expression> e) expectedOutput: """ (str, 10) (default, 10) - (str, 10) - (default, 10) """); verifier.VerifyDiagnostics(); } @@ -310,7 +250,7 @@ static T Run(Expression> e) [CombinatorialData] public void OptionalParameter_Indexer( [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, - bool useCompilationReference) + bool useExpression) { string sourceA = $$""" public class A @@ -319,39 +259,30 @@ public class A } """; var comp = CreateCompilation(sourceA); - var refA = AsReference(comp, useCompilationReference); + var refA = comp.EmitToImageReference(); string sourceB = $$""" - using System; - using System.Linq.Expressions; class Program { static void Main() { var a = new A(); - Console.WriteLine(a[1, 2]); - Console.WriteLine(a[3]); - Console.WriteLine(Run(() => a[1, 2])); - Console.WriteLine(Run(() => a[3])); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => a[1, 2]); + Utils.Report(() => a[3]); } } """; comp = CreateCompilation( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (languageVersion == LanguageVersion.CSharp13) + if (languageVersion == LanguageVersion.CSharp13 && useExpression) { comp.VerifyEmitDiagnostics( - // (11,37): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Console.WriteLine(Run(() => a[3])); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "a[3]").WithLocation(11, 37)); + // (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 { @@ -360,8 +291,6 @@ static T Run(Expression> e) expectedOutput: """ 2 10 - 2 - 10 """); verifier.VerifyDiagnostics(); } @@ -371,46 +300,37 @@ static T Run(Expression> e) [CombinatorialData] public void OptionalParameter_Delegate( [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, - bool useCompilationReference) + bool useExpression) { string sourceA = $$""" public delegate int D(int x, in int y = 10); """; var comp = CreateCompilation(sourceA); - var refA = AsReference(comp, useCompilationReference); + var refA = comp.EmitToImageReference(); string sourceB = $$""" - using System; - using System.Linq.Expressions; class Program { static void Main() { D d = F; - Console.WriteLine(d(1, 2)); - Console.WriteLine(d(3)); - Console.WriteLine(Run(() => d(1, 2))); - Console.WriteLine(Run(() => d(3))); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => d(1, 2)); + Utils.Report(() => d(3)); } static T F(T x, in T y) => y; } """; comp = CreateCompilation( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (languageVersion == LanguageVersion.CSharp13) + if (languageVersion == LanguageVersion.CSharp13 && useExpression) { comp.VerifyEmitDiagnostics( - // (11,37): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Console.WriteLine(Run(() => d(3))); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "d(3)").WithLocation(11, 37)); + // (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 { @@ -419,8 +339,6 @@ static T Run(Expression> e) expectedOutput: """ 2 10 - 2 - 10 """); verifier.VerifyDiagnostics(); } @@ -430,52 +348,51 @@ static T Run(Expression> e) [CombinatorialData] public void OptionalParameter_CollectionInitializer( [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useExpression, bool useIn) { string refKind = useIn ? "in" : ""; string sourceA = $$""" 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 = """ - using System; - using System.Linq.Expressions; class Program { static void Main() { - Report(new MyCollection() { { "one", 1 }, { "two" } }); - Report(Run(() => new MyCollection() { { "one", 1 }, { "two" } })); - } - static void Report(MyCollection c) - { - foreach (var kvp in c) - System.Console.WriteLine("{0}, {1}", kvp.Key, kvp.Value); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => new MyCollection() { { "one", 1 }, { "two" } }); } } """; var comp = CreateCompilation( - [sourceA, sourceB], + [sourceA, sourceB, GetUtilities(useExpression)], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (languageVersion == LanguageVersion.CSharp13) + if (languageVersion == LanguageVersion.CSharp13 && useExpression) { comp.VerifyEmitDiagnostics( - // (8,74): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments - // Report(Run(() => new MyCollection() { { "one", 1 }, { "two" } })); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, @"{ ""two"" }").WithLocation(8, 74)); + // (5,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(5, 76)); } else if (useIn) { @@ -486,12 +403,7 @@ static T Run(Expression> e) { var verifier = CompileAndVerify( comp, - expectedOutput: """ - one, 1 - two, 0 - one, 1 - two, 0 - """); + expectedOutput: "(one, 1), (two, 0)"); verifier.VerifyDiagnostics(); } } @@ -542,9 +454,10 @@ static void Main() [Theory] [CombinatorialData] - public void Decimal(bool preferInterpretation, bool useCompilationReference) + public void Decimal( + bool useExpression, + bool useCompilationReference) { - string value = preferInterpretation ? "true" : "false"; string sourceA = """ public static class A { @@ -555,28 +468,19 @@ public static class A var refA = AsReference(comp, useCompilationReference); string sourceB = $$""" - using System; - using System.Linq.Expressions; class Program { static void Main() { - Console.WriteLine(A.GetValue()); - Console.WriteLine(Run(() => A.GetValue(200))); - Console.WriteLine(Run(() => A.GetValue())); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => A.GetValue(200)); + Utils.Report(() => A.GetValue()); } } """; var verifier = CompileAndVerify( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], expectedOutput: """ - 100 200 100 """); @@ -585,9 +489,10 @@ static T Run(Expression> e) [Theory] [CombinatorialData] - public void DateTime_01(bool preferInterpretation, bool useCompilationReference) + public void DateTime_01( + bool useExpression, + bool useCompilationReference) { - string value = preferInterpretation ? "true" : "false"; string sourceA = """ using System; using System.Runtime.CompilerServices; @@ -602,27 +507,19 @@ public static class A string sourceB = $$""" using System; - using System.Linq.Expressions; class Program { static void Main() { - Console.WriteLine(A.GetValue().Ticks); - Console.WriteLine(Run(() => A.GetValue(new DateTime(200))).Ticks); - Console.WriteLine(Run(() => A.GetValue()).Ticks); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => A.GetValue(new DateTime(200)).Ticks); + Utils.Report(() => A.GetValue().Ticks); } } """; var verifier = CompileAndVerify( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], expectedOutput: """ - 100 200 100 """); @@ -631,7 +528,9 @@ static T Run(Expression> e) [Theory] [CombinatorialData] - public void DateTime_02(bool useCompilationReference) + public void DateTime_02( + bool useExpression, + bool useCompilationReference) { string sourceA = """ using System; @@ -645,35 +544,30 @@ public static class A var refA = AsReference(comp, useCompilationReference); string sourceB = $$""" - using System; - using System.Linq.Expressions; class Program { static void Main() { - Console.WriteLine(A.GetValue().Ticks); - Console.WriteLine(Run(() => A.GetValue()).Ticks); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => A.GetValue().Ticks); } } """; - comp = CreateCompilation(sourceB, references: [refA]); + comp = CreateCompilation( + [sourceB, GetUtilities(useExpression)], + references: [refA]); comp.VerifyEmitDiagnostics( - // (7,29): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(DateTime)' - // Console.WriteLine(A.GetValue().Ticks); - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(System.DateTime)").WithLocation(7, 29), - // (8,39): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(DateTime)' - // Console.WriteLine(Run(() => A.GetValue()).Ticks); - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(System.DateTime)").WithLocation(8, 39)); + // (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 useCompilationReference) + public void OptionalAndDefaultParameterValue( + bool includeOptional, + bool includeDefaultParameterValue, + bool useExpression, + bool useCompilationReference) { string sourceA = $$""" using System.Runtime.InteropServices; @@ -689,94 +583,75 @@ public static int GetValue( var refA = AsReference(comp, useCompilationReference); string sourceB = """ - using System; - using System.Linq.Expressions; class Program { static void Main() { - Console.WriteLine(A.GetValue()); - Console.WriteLine(Run(() => A.GetValue(200))); - Console.WriteLine(Run(() => A.GetValue())); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => A.GetValue(200)); + Utils.Report(() => A.GetValue()); } } """; - comp = CreateCompilation(sourceB, references: [refA], options: TestOptions.ReleaseExe); + comp = CreateCompilation( + [sourceB, GetUtilities(useExpression)], + references: [refA], + options: TestOptions.ReleaseExe); if (includeOptional) { - string optionalValue = includeDefaultParameterValue ? "100" : "0"; var verifier = CompileAndVerify( comp, expectedOutput: $$""" - {{optionalValue}} 200 - {{optionalValue}} + {{(includeDefaultParameterValue ? "100" : "0")}} """); verifier.VerifyDiagnostics(); } else { comp.VerifyEmitDiagnostics( - // (7,29): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(int)' - // Console.WriteLine(A.GetValue()); - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(int)").WithLocation(7, 29), - // (9,39): error CS7036: There is no argument given that corresponds to the required parameter 'value' of 'A.GetValue(int)' - // Console.WriteLine(Run(() => A.GetValue())); - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "GetValue").WithArguments("value", "A.GetValue(int)").WithLocation(9, 39)); + // (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 useCompilationReference) + public void OptionalParams( + bool includeDefaultParameterValue, + bool useExpression, + bool useCompilationReference) { string sourceA = $$""" using System.Runtime.InteropServices; public static class A { - public static object[] GetValue( + public static string GetValue( [Optional] {{(includeDefaultParameterValue ? "[DefaultParameterValue(null)]" : "")}} - params object[] args) => args; + params object[] args) + { + return (args is null) ? "null" : args.Length.ToString(); + } } """; var comp = CreateCompilation(sourceA); var refA = AsReference(comp, useCompilationReference); string sourceB = """ - using System; - using System.Linq.Expressions; class Program { static void Main() { - Report(A.GetValue(1, 2, 3)); - Report(A.GetValue()); - Report(Run(() => A.GetValue(1, 2, 3))); - Report(Run(() => A.GetValue())); - } - static void Report(object[] args) - { - Console.WriteLine(args is null ? "null" : args.Length.ToString()); - } - static T Run(Expression> e) - { - var f = e.Compile(); - return f(); + Utils.Report(() => A.GetValue(1, 2, 3)); + Utils.Report(() => A.GetValue()); } } """; var verifier = CompileAndVerify( - sourceB, + [sourceB, GetUtilities(useExpression)], references: [refA], expectedOutput: """ - 3 - 0 3 0 """); @@ -854,13 +729,20 @@ static void Main() references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (useExpression) + 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 CS9300: 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( @@ -992,7 +874,7 @@ static void Main() references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (useExpression) + if (languageVersion == LanguageVersion.CSharp13 && useExpression) { comp.VerifyEmitDiagnostics( // (5,28): error CS0853: An expression tree may not contain a named argument specification @@ -1017,6 +899,28 @@ static void Main() // Utils.Report(() => A.GetFirst()); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "A.GetFirst()").WithLocation(11, 28)); } + else if (useExpression) + { + comp.VerifyEmitDiagnostics( + // (5,28): error CS9300: 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 CS9300: 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 CS9300: 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 CS9300: 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 CS9300: 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 CS9300: 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( @@ -1120,12 +1024,19 @@ static void Main() references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (useExpression) + 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 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)); + // (5,28): error CS9300: 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 { @@ -1292,7 +1203,7 @@ static void Main() references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); - if (useExpression) + if (languageVersion == LanguageVersion.CSharp13 && useExpression) { comp.VerifyEmitDiagnostics( // (5,28): error CS0853: An expression tree may not contain a named argument specification @@ -1320,6 +1231,31 @@ static void Main() // Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)").WithLocation(12, 28)); } + else if (useExpression) + { + comp.VerifyEmitDiagnostics( + // (6,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, more: default, second: 2)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(first: 1, more: default, second: 2)").WithLocation(6, 28), + // (7,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, more: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(first: 1, more: default)").WithLocation(7, 28), + // (8,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(second: 2)").WithLocation(8, 28), + // (9,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, first: 1)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(second: 2, first: 1)").WithLocation(9, 28), + // (10,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, more: default)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(second: 2, more: default)").WithLocation(10, 28), + // (11,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 })); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(more: new[] { 3, 4 })").WithLocation(11, 28), + // (12,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)").WithLocation(12, 28)); + } else { var verifier = CompileAndVerify( @@ -1433,10 +1369,6 @@ static void Main() { Utils.Report(() => A.GetFirst(second: 2, first: 1)); Utils.Report(() => A.GetFirst(first: "one", second: "two")); - Utils.Report(() => A.GetFirst(first: default, default)); - Utils.Report(() => A.GetFirst(second: default, default)); - Utils.Report(() => A.GetFirst(default, second: default)); - Utils.Report(() => A.GetFirst(default, first: default)); } } """; @@ -1453,27 +1385,71 @@ static void Main() Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(second: 2, first: 1)").WithLocation(5, 28), // (6,28): error CS0853: An expression tree may not contain a named argument specification // Utils.Report(() => A.GetFirst(first: "one", second: "two")); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"A.GetFirst(first: ""one"", second: ""two"")").WithLocation(6, 28), - // (7,28): error CS0853: An expression tree may not contain a named argument specification + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"A.GetFirst(first: ""one"", second: ""two"")").WithLocation(6, 28)); + } + else if (useExpression) + { + comp.VerifyEmitDiagnostics( + // (5,28): error CS9300: 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), + // (6,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => A.GetFirst(first: "one", second: "two")); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, @"A.GetFirst(first: ""one"", second: ""two"")").WithLocation(6, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + 1 + one + """); + verifier.VerifyDiagnostics(); + } + + string sourceB3 = $$""" + class Program + { + static void Main() + { + Utils.Report(() => A.GetFirst(first: default, default)); + Utils.Report(() => A.GetFirst(second: default, default)); + Utils.Report(() => A.GetFirst(default, second: default)); + Utils.Report(() => A.GetFirst(default, first: default)); + } + } + """; + comp = CreateCompilation( + [sourceB3, 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: default, default)); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(first: default, default)").WithLocation(7, 28), - // (8,28): error CS0853: An expression tree may not contain a named argument specification + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(first: default, default)").WithLocation(5, 28), + // (6,28): error CS0853: An expression tree may not contain a named argument specification // Utils.Report(() => A.GetFirst(second: default, default)); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(second: default, default)").WithLocation(8, 28), - // (9,28): error CS0853: An expression tree may not contain a named argument specification + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(second: default, default)").WithLocation(6, 28), + // (7,28): error CS0853: An expression tree may not contain a named argument specification // Utils.Report(() => A.GetFirst(default, second: default)); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(default, second: default)").WithLocation(9, 28), - // (10,28): error CS0853: An expression tree may not contain a named argument specification + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(default, second: default)").WithLocation(7, 28), + // (8,28): error CS0853: An expression tree may not contain a named argument specification // Utils.Report(() => A.GetFirst(default, first: default)); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(default, first: default)").WithLocation(10, 28)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "A.GetFirst(default, first: default)").WithLocation(8, 28)); + } + else if (useExpression) + { + comp.VerifyEmitDiagnostics(); } else { var verifier = CompileAndVerify( comp, expectedOutput: """ - 1 - one 0 null 0 @@ -1482,7 +1458,7 @@ static void Main() verifier.VerifyDiagnostics(); } - string sourceB3 = $$""" + string sourceB4 = $$""" class Program { static void Main() @@ -1493,7 +1469,7 @@ static void Main() } """; comp = CreateCompilation( - [sourceB3, GetUtilities(useExpression)], + [sourceB4, GetUtilities(useExpression)], references: [refA], parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); @@ -1506,6 +1482,312 @@ static void Main() Diagnostic(ErrorCode.ERR_AmbigCall, "GetFirst").WithArguments("A.GetFirst(int, int)", "A.GetFirst(string, string)").WithLocation(6, 30)); } + [Theory] + [CombinatorialData] + public void NamedArgument_Constructor( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useExpression) + { + string sourceA = $$""" + public class A + { + public readonly string X; + public readonly int Y; + public A(string x, ref int y) { X = x; Y = y; } + public override string ToString() => $"({X}, {Y})"; + } + """; + var comp = CreateCompilation(sourceA); + var refA = comp.EmitToImageReference(); + + string sourceB1 = $$""" + class Program + { + static void Main() + { + int y = 1; + Utils.Report(() => new A(x: "one", ref y)); + y = 2; + Utils.Report(() => new A("two", y: ref y)); + y = 3; + Utils.Report(() => new A(x: "three", y: ref y)); + } + } + """; + comp = CreateCompilation( + [sourceB1, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13 && useExpression) + { + comp.VerifyEmitDiagnostics( + // (6,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => new A(x: "one", ref y)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"new A(x: ""one"", ref y)").WithLocation(6, 28), + // (8,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => new A("two", y: ref y)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"new A(""two"", y: ref y)").WithLocation(8, 28), + // (10,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => new A(x: "three", y: ref y)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"new A(x: ""three"", y: ref y)").WithLocation(10, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + (one, 1) + (two, 2) + (three, 3) + """); + verifier.VerifyDiagnostics(); + } + + string sourceB2 = $$""" + class Program + { + static void Main() + { + int y = 1; + Utils.Report(() => new A(y: ref y, x: "one")); + } + } + """; + comp = CreateCompilation( + [sourceB2, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13 && useExpression) + { + comp.VerifyEmitDiagnostics( + // (6,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => new A(y: ref y, x: "one")); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"new A(y: ref y, x: ""one"")").WithLocation(6, 28)); + } + else if (useExpression) + { + comp.VerifyEmitDiagnostics( + // (6,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => new A(y: ref y, x: "one")); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, @"new A(y: ref y, x: ""one"")").WithLocation(6, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + (one, 1) + """); + verifier.VerifyDiagnostics(); + } + } + + [Theory] + [CombinatorialData] + public void NamedArgument_Indexer( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useExpression) + { + string sourceA = $$""" + public class A + { + public string this[int x, in string y] => y; + } + """; + var comp = CreateCompilation(sourceA); + var refA = comp.EmitToImageReference(); + + string sourceB1 = $$""" + class Program + { + static void Main() + { + var a = new A(); + string y = "one"; + Utils.Report(() => a[x: 1, in y]); + Utils.Report(() => a[2, y: "two"]); + y = "three"; + Utils.Report(() => a[x: 2, y: in y]); + } + } + """; + comp = CreateCompilation( + [sourceB1, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13 && useExpression) + { + comp.VerifyEmitDiagnostics( + // (7,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => a[x: 1, in y]); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "a[x: 1, in y]").WithLocation(7, 28), + // (8,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => a[2, y: "two"]); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"a[2, y: ""two""]").WithLocation(8, 28), + // (10,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => a[x: 2, y: in y]); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "a[x: 2, y: in y]").WithLocation(10, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + one + two + three + """); + verifier.VerifyDiagnostics(); + } + + string sourceB2 = $$""" + class Program + { + static void Main() + { + var a = new A(); + string y = "two"; + Utils.Report(() => a[y: "one", x: 1]); + Utils.Report(() => a[y: in y, x: 2]); + } + } + """; + comp = CreateCompilation( + [sourceB2, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13 && useExpression) + { + comp.VerifyEmitDiagnostics( + // (7,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => a[y: "one", x: 1]); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"a[y: ""one"", x: 1]").WithLocation(7, 28), + // (8,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => a[y: in y, x: 2]); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "a[y: in y, x: 2]").WithLocation(8, 28)); + } + else if (useExpression) + { + comp.VerifyEmitDiagnostics( + // (7,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => a[y: "one", x: 1]); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, @"a[y: ""one"", x: 1]").WithLocation(7, 28), + // (8,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => a[y: in y, x: 2]); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "a[y: in y, x: 2]").WithLocation(8, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + one + two + """); + verifier.VerifyDiagnostics(); + } + } + + [Theory] + [CombinatorialData] + public void NamedArgument_Delegate( + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + bool useExpression) + { + string sourceA = $$""" + public delegate (T, U) D(T x, U y); + """; + var comp = CreateCompilation(sourceA); + var refA = comp.EmitToImageReference(); + + string sourceB1 = $$""" + class Program + { + static void Main() + { + D d = F; + Utils.Report(() => d(x: 1, "one")); + Utils.Report(() => d(2, y: "two")); + Utils.Report(() => d(x: 3, y: "three")); + } + static (int, string) F(int i, string s) => (i, s); + } + """; + comp = CreateCompilation( + [sourceB1, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13 && useExpression) + { + comp.VerifyEmitDiagnostics( + // (6,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => d(x: 1, "one")); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"d(x: 1, ""one"")").WithLocation(6, 28), + // (7,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => d(2, y: "two")); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"d(2, y: ""two"")").WithLocation(7, 28), + // (8,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => d(x: 3, y: "three")); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"d(x: 3, y: ""three"")").WithLocation(8, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + (1, one) + (2, two) + (3, three) + """); + verifier.VerifyDiagnostics(); + } + + string sourceB2 = $$""" + class Program + { + static void Main() + { + D d = F; + Utils.Report(() => d(y:"one", x:1)); + } + static (int, string) F(int i, string s) => (i, s); + } + """; + comp = CreateCompilation( + [sourceB2, GetUtilities(useExpression)], + references: [refA], + parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), + options: TestOptions.ReleaseExe); + if (languageVersion == LanguageVersion.CSharp13 && useExpression) + { + comp.VerifyEmitDiagnostics( + // (6,28): error CS0853: An expression tree may not contain a named argument specification + // Utils.Report(() => d(y:"one", x:1)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, @"d(y:""one"", x:1)").WithLocation(6, 28)); + } + else if (useExpression) + { + comp.VerifyEmitDiagnostics( + // (6,28): error CS9300: An expression tree may not contain a named argument specification out of position + // Utils.Report(() => d(y:"one", x:1)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, @"d(y:""one"", x:1)").WithLocation(6, 28)); + } + else + { + var verifier = CompileAndVerify( + comp, + expectedOutput: """ + (1, one) + """); + verifier.VerifyDiagnostics(); + } + } + [Theory] [CombinatorialData] public void NamedArgument_LocalFunction( @@ -1552,9 +1834,9 @@ static void Main() // (13,19): error CS8110: An expression tree may not contain a reference to a local function // e = () => GetFirst(1, second: 2); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "GetFirst(1, second: 2)").WithLocation(13, 19), - // (14,19): error CS0853: An expression tree may not contain a named argument specification + // (14,19): error CS9300: An expression tree may not contain a named argument specification out of position // e = () => GetFirst(second: 2, first: 1); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "GetFirst(second: 2, first: 1)").WithLocation(14, 19)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "GetFirst(second: 2, first: 1)").WithLocation(14, 19)); } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 2542a831f9e0d..4b709d78e6602 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -13082,8 +13082,10 @@ public static void Main(string[] args) Diagnostic(ErrorCode.ERR_ArrayInitializerIncorrectLength, "{}").WithArguments("3").WithLocation(7, 31)); } - [Fact] - public void CS0853ERR_ExpressionTreeContainsNamedArgument01() + [Theory] + [InlineData(LanguageVersion.CSharp13)] + [InlineData(LanguageVersionFacts.CSharpNext)] + public void CS0853ERR_ExpressionTreeContainsNamedArgument01(LanguageVersion languageVersion) { var text = @" using System.Linq.Expressions; @@ -13103,16 +13105,25 @@ public static string Index(int minSessions = 0) } } "; - CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics( - // (10,40): error CS0853: An expression tree may not contain a named argument specification - // Expression myET = x => Index(minSessions:5); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "Index(minSessions:5)").WithLocation(10, 40) - ); + var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyDiagnostics( + // (10,40): error CS0853: An expression tree may not contain a named argument specification + // Expression myET = x => Index(minSessions:5); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "Index(minSessions:5)").WithLocation(10, 40)); + } + else + { + comp.VerifyDiagnostics(); + } } [WorkItem(545063, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545063")] - [Fact] - public void CS0853ERR_ExpressionTreeContainsNamedArgument02() + [Theory] + [InlineData(LanguageVersion.CSharp13)] + [InlineData(LanguageVersionFacts.CSharpNext)] + public void CS0853ERR_ExpressionTreeContainsNamedArgument02(LanguageVersion languageVersion) { var text = @" using System; @@ -13127,11 +13138,18 @@ static void Main() } } "; - CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics( - // (10,41): error CS0853: An expression tree may not contain a named argument specification - // Expression> f = () => new List { 1 } [index: 0]; - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "new List { 1 } [index: 0]").WithLocation(10, 41) - ); + var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + if (languageVersion == LanguageVersion.CSharp13) + { + comp.VerifyDiagnostics( + // (10,41): error CS0853: An expression tree may not contain a named argument specification + // Expression> f = () => new List { 1 } [index: 0]; + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "new List { 1 } [index: 0]").WithLocation(10, 41)); + } + else + { + comp.VerifyDiagnostics(); + } } [Theory] @@ -13163,8 +13181,7 @@ public static string Index(int minSessions = 0) comp.VerifyDiagnostics( // (10,40): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments // Expression myET = x => Index(); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "Index()").WithLocation(10, 40) - ); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "Index()").WithLocation(10, 40)); } else { From 0aa49559f87f3f1f1c0c3ee574452c061bf07b7c Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 7 Apr 2025 23:52:38 -0700 Subject: [PATCH 06/14] Update error code --- .../CSharp/Portable/Errors/ErrorCode.cs | 2 +- ...xpressionOptionalAndNamedArgumentsTests.cs | 44 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 2c77ac7c38d92..e816b78cdc428 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2389,7 +2389,6 @@ internal enum ErrorCode ERR_PPIgnoredFollowsToken = 9297, ERR_PPIgnoredNeedsFileBasedProgram = 9298, ERR_PPIgnoredFollowsIf = 9299, - ERR_ExpressionTreeContainsNamedArgumentOutOfPosition = 9300, ERR_RefExtensionParameterMustBeValueTypeOrConstrainedToOne = 9300, ERR_InExtensionParameterMustBeValueType = 9301, @@ -2398,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/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs index 110b4a93bd19e..f96b2b7fd36e7 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -739,7 +739,7 @@ static void Main() else if (useExpression) { comp.VerifyEmitDiagnostics( - // (5,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (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)); } @@ -902,22 +902,22 @@ static void Main() else if (useExpression) { comp.VerifyEmitDiagnostics( - // (5,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (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 CS9300: An expression tree may not contain a named argument specification out of position + // (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 CS9300: An expression tree may not contain a named argument specification out of position + // (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 CS9300: An expression tree may not contain a named argument specification out of position + // (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 CS9300: An expression tree may not contain a named argument specification out of position + // (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 CS9300: An expression tree may not contain a named argument specification out of position + // (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)); } @@ -1034,7 +1034,7 @@ static void Main() else if (useExpression) { comp.VerifyEmitDiagnostics( - // (5,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (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)); } @@ -1234,25 +1234,25 @@ static void Main() else if (useExpression) { comp.VerifyEmitDiagnostics( - // (6,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (6,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, more: default, second: 2)); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(first: 1, more: default, second: 2)").WithLocation(6, 28), - // (7,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (7,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => A.GetSecondAndParamsLength(first: 1, more: default)); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(first: 1, more: default)").WithLocation(7, 28), - // (8,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (8,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => A.GetSecondAndParamsLength(second: 2)); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(second: 2)").WithLocation(8, 28), - // (9,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (9,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, first: 1)); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(second: 2, first: 1)").WithLocation(9, 28), - // (10,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (10,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => A.GetSecondAndParamsLength(second: 2, more: default)); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(second: 2, more: default)").WithLocation(10, 28), - // (11,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (11,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 })); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(more: new[] { 3, 4 })").WithLocation(11, 28), - // (12,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (12,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetSecondAndParamsLength(more: new[] { 3, 4 }, second: 2, first: 1)").WithLocation(12, 28)); } @@ -1390,10 +1390,10 @@ static void Main() else if (useExpression) { comp.VerifyEmitDiagnostics( - // (5,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (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), - // (6,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (6,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => A.GetFirst(first: "one", second: "two")); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, @"A.GetFirst(first: ""one"", second: ""two"")").WithLocation(6, 28)); } @@ -1569,7 +1569,7 @@ static void Main() else if (useExpression) { comp.VerifyEmitDiagnostics( - // (6,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (6,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => new A(y: ref y, x: "one")); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, @"new A(y: ref y, x: ""one"")").WithLocation(6, 28)); } @@ -1673,10 +1673,10 @@ static void Main() else if (useExpression) { comp.VerifyEmitDiagnostics( - // (7,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (7,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => a[y: "one", x: 1]); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, @"a[y: ""one"", x: 1]").WithLocation(7, 28), - // (8,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (8,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => a[y: in y, x: 2]); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "a[y: in y, x: 2]").WithLocation(8, 28)); } @@ -1773,7 +1773,7 @@ static void Main() else if (useExpression) { comp.VerifyEmitDiagnostics( - // (6,28): error CS9300: An expression tree may not contain a named argument specification out of position + // (6,28): error CS9307: An expression tree may not contain a named argument specification out of position // Utils.Report(() => d(y:"one", x:1)); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, @"d(y:""one"", x:1)").WithLocation(6, 28)); } @@ -1834,7 +1834,7 @@ static void Main() // (13,19): error CS8110: An expression tree may not contain a reference to a local function // e = () => GetFirst(1, second: 2); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsLocalFunction, "GetFirst(1, second: 2)").WithLocation(13, 19), - // (14,19): error CS9300: An expression tree may not contain a named argument specification out of position + // (14,19): error CS9307: An expression tree may not contain a named argument specification out of position // e = () => GetFirst(second: 2, first: 1); Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "GetFirst(second: 2, first: 1)").WithLocation(14, 19)); } From abca25bd5c6e02212d43645ea1151fec5da15ee0 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 8 Apr 2025 00:07:40 -0700 Subject: [PATCH 07/14] IsBuildOnlyDiagnostic --- src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs | 1 + 1 file changed, 1 insertion(+) 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. From 8bca3da413b730cd4091327d10bac90dffb0932f Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:05:41 -0700 Subject: [PATCH 08/14] Revert "Correct DefaultParameterValueAttribute in diagnostic" This reverts commit a8cbbce2998bbb8bc04213a3890b6903b8d66a21. --- src/Compilers/CSharp/Portable/CSharpResources.resx | 2 +- .../Symbols/Source/SourceComplexParameterSymbol.cs | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.cs.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.de.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.es.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.fr.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.it.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.ja.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.ko.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.pl.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.pt-BR.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.ru.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.tr.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf | 4 ++-- .../CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf | 4 ++-- .../CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs | 10 +++++----- .../CSharp/Test/Emit3/RefReadonlyParameterTests.cs | 10 +++++----- .../CSharp/Test/Emit3/Semantics/ExtensionTests.cs | 2 +- .../Test/Semantic/Semantics/NamedAndOptionalTests.cs | 4 ++-- .../Semantic/Semantics/NullableReferenceTypesTests.cs | 4 ++-- .../CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs | 2 +- 21 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 6f9d49fe21624..f940c8ea7b476 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4062,7 +4062,7 @@ You should consider suppressing the warning only if you're sure that you don't w Named argument '{0}' is used out-of-position but is followed by an unnamed argument - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute Default parameter value for '{0}' must be a compile-time constant diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 669a3bb286cdb..6f02978674217 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -756,7 +756,7 @@ protected override void DecodeWellKnownAttributeImpl(ref DecodeWellKnownAttribut if (HasDefaultArgumentSyntax) { - // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute diagnostics.Add(ErrorCode.ERR_DefaultValueUsedWithAttributes, arguments.AttributeSyntaxOpt.Name.Location); } } @@ -952,7 +952,7 @@ private ConstantValue DecodeDefaultParameterValueAttribute(CSharpAttributeData a if (HasDefaultArgumentSyntax) { - // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute if (diagnose) { diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueUsedWithAttributes, node.Name.Location); diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 53bd10b2a1e20..6795aa712ec1d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -11367,8 +11367,8 @@ Potlačení upozornění zvažte jenom v případě, když určitě nechcete če - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - Nejde zadat výchozí hodnotu parametru v kombinaci s atributy DefaultParameterAttribute nebo OptionalAttribute. + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + Nejde zadat výchozí hodnotu parametru v kombinaci s atributy DefaultParameterAttribute nebo OptionalAttribute. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 9162c1bf69556..fef82ba2dcc18 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -11367,8 +11367,8 @@ Sie sollten das Unterdrücken der Warnung nur in Betracht ziehen, wenn Sie siche - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - Es kann kein Standardparameterwert in Verbindung mit "DefaultParameterAttribute" oder "OptionalAttribute" angegeben werden. + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + Es kann kein Standardparameterwert in Verbindung mit "DefaultParameterAttribute" oder "OptionalAttribute" angegeben werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 8e61c791865e8..d39de65e1f75c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -11367,8 +11367,8 @@ Considere la posibilidad de suprimir la advertencia solo si tiene la seguridad d - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - No se puede especificar un valor de parámetro predeterminado junto con DefaultParameterAttribute u OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + No se puede especificar un valor de parámetro predeterminado junto con DefaultParameterAttribute u OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 7fdb310fb227c..a7c0e82371b41 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -11367,8 +11367,8 @@ Supprimez l'avertissement seulement si vous êtes sûr de ne pas vouloir attendr - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - Impossible de spécifier une valeur de paramètre par défaut conjointement à DefaultParameterAttribute ou OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + Impossible de spécifier une valeur de paramètre par défaut conjointement à DefaultParameterAttribute ou OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index c3eb3a4c981d0..3c9c4b638996c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -11367,8 +11367,8 @@ Come procedura consigliata, è consigliabile attendere sempre la chiamata. - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - Impossibile specificare un valore di parametro predefinito insieme a DefaultParameterAttribute o OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + Impossibile specificare un valore di parametro predefinito insieme a DefaultParameterAttribute o OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index a6fd514f07316..89652d71d304c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -11367,8 +11367,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - DefaultParameterAttribute または OptionalAttribute と共に既定パラメーター値を指定することはできません + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + DefaultParameterAttribute または OptionalAttribute と共に既定パラメーター値を指定することはできません diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 3336233b38845..2931f97754d3c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -11367,8 +11367,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - DefaultParameterAttribute 또는 OptionalAttribute와 함께 기본 매개 변수 값을 지정할 수 없습니다. + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + DefaultParameterAttribute 또는 OptionalAttribute와 함께 기본 매개 변수 값을 지정할 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 7164292799fcb..9aa2a31cfa12c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -11367,8 +11367,8 @@ Pominięcie ostrzeżenia należy wziąć pod uwagę tylko w sytuacji, gdy na pew - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - Nie można określić wartości domyślnej parametru w połączeniu z klasami DefaultParameterAttribute lub OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + Nie można określić wartości domyślnej parametru w połączeniu z klasami DefaultParameterAttribute lub OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 9a198e4020104..327398efa7c86 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -11367,8 +11367,8 @@ Você pode suprimir o aviso se tiver certeza de que não vai querer aguardar a c - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - Não é possível especificar um valor de parâmetro padrão junto com DefaultParameterAttribute ou OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + Não é possível especificar um valor de parâmetro padrão junto com DefaultParameterAttribute ou OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index e94baafb13fce..8e43ce0310444 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -11368,8 +11368,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - Не удалось указать значение параметра по умолчанию вместе с DefaultParameterAttribute или OptionalAttribute. + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + Не удалось указать значение параметра по умолчанию вместе с DefaultParameterAttribute или OptionalAttribute. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index b02b11ead4468..70a0bc99f2505 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -11367,8 +11367,8 @@ Yalnızca asenkron çağrının tamamlanmasını beklemek istemediğinizden ve - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - DefaultParameterAttribute veya OptionalAttribute ile birlikte varsayılan parametre değeri belirtilemez + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + DefaultParameterAttribute veya OptionalAttribute ile birlikte varsayılan parametre değeri belirtilemez diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 746f8c3de9623..741909a05e9bc 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -11367,8 +11367,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - 不能同时指定默认参数值与 DefaultParameterAttribute 或 OptionalAttribute + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + 不能同时指定默认参数值与 DefaultParameterAttribute 或 OptionalAttribute diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 12c695a330ffc..72d9bb03d5892 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -11367,8 +11367,8 @@ You should consider suppressing the warning only if you're sure that you don't w - Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute - 不能連同 DefaultParameterAttribute 或 OptionalAttribute 一起指定預設參數值 + Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute + 不能連同 DefaultParameterAttribute 或 OptionalAttribute 一起指定預設參數值 diff --git a/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs index 876153b624004..cc001016cb53b 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/OptionalArgumentsTests.cs @@ -255,10 +255,10 @@ interface I delegate void D([DecimalConstant(0, 0, 0, 0, 3)]decimal b = 4); "; CreateCompilation(source).VerifyDiagnostics( - // (5,14): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (5,14): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // void F1([DefaultParameterValue(1)]int o = 2); Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(5, 14), - // (6,14): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (6,14): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // void F2([DefaultParameterValue(1)]decimal o = 2); Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(6, 14), // (6,51): error CS8017: The parameter has multiple distinct default values. @@ -267,7 +267,7 @@ interface I // (7,57): error CS8017: The parameter has multiple distinct default values. // void F4([DecimalConstant(0, 0, 0, 0, 1)]decimal o = 2); Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "2").WithLocation(7, 57), - // (8,35): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (8,35): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // void F6([DateTimeConstant(1), DefaultParameterValue(1), DecimalConstant(0, 0, 0, 0, 1)]int o = 1); Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(8, 35), // (8,61): error CS8017: The parameter has multiple distinct default values. @@ -279,13 +279,13 @@ interface I // (9,35): error CS8017: The parameter has multiple distinct default values. // void F7([DateTimeConstant(2), DecimalConstant(0, 0, 0, 0, 2), DefaultParameterValue(2)]decimal o = 2); Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "DecimalConstant(0, 0, 0, 0, 2)").WithLocation(9, 35), - // (9,67): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (9,67): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // void F7([DateTimeConstant(2), DecimalConstant(0, 0, 0, 0, 2), DefaultParameterValue(2)]decimal o = 2); Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(9, 67), // (9,104): error CS8017: The parameter has multiple distinct default values. // void F7([DateTimeConstant(2), DecimalConstant(0, 0, 0, 0, 2), DefaultParameterValue(2)]decimal o = 2); Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "2").WithLocation(9, 104), - // (10,25): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (10,25): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // object this[int a, [DefaultParameterValue(1)]int o = 2] { get; set; } Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(10, 25), // (10,58): error CS8017: The parameter has multiple distinct default values. diff --git a/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs b/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs index 7359081866010..12482bd5997b1 100644 --- a/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/RefReadonlyParameterTests.cs @@ -4621,7 +4621,7 @@ class C } """; CreateCompilation(source).VerifyDiagnostics( - // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // static void M([DefaultParameterValue(1)] ref readonly int i = 1) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(4, 20), // (4,67): warning CS9200: A default value is specified for 'ref readonly' parameter 'i', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. @@ -4643,7 +4643,7 @@ class C } """; CreateCompilation(source).VerifyDiagnostics( - // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // static void M([Optional] ref readonly int i = 1) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(4, 20), // (4,51): warning CS9200: A default value is specified for 'ref readonly' parameter 'i', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. @@ -4662,10 +4662,10 @@ class C } """; CreateCompilation(source).VerifyDiagnostics( - // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (4,20): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // static void M([Optional, DefaultParameterValue(1)] ref readonly int i = 1) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(4, 20), - // (4,30): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (4,30): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // static void M([Optional, DefaultParameterValue(1)] ref readonly int i = 1) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(4, 30), // (4,77): warning CS9200: A default value is specified for 'ref readonly' parameter 'i', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. @@ -4797,7 +4797,7 @@ static void Main() } """; CreateCompilation(source).VerifyDiagnostics( - // (6,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (6,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // static void M2([Optional, DecimalConstant(1, 0, 0u, 0u, 11u)] ref readonly decimal d = 1.1m) => throw null; Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(6, 21), // (6,92): warning CS9200: A default value is specified for 'ref readonly' parameter 'd', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs index 9e1106e0371e6..8d7496e27f055 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs @@ -2522,7 +2522,7 @@ public static class Extensions // (3,15): error CS9284: The receiver parameter of an extension cannot have a default value // extension([System.Runtime.InteropServices.DefaultParameterValue(1)] int o = 2) { } Diagnostic(ErrorCode.ERR_ExtensionParameterDisallowsDefaultValue, "[System.Runtime.InteropServices.DefaultParameterValue(1)] int o = 2").WithLocation(3, 15), - // (3,16): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (3,16): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // extension([System.Runtime.InteropServices.DefaultParameterValue(1)] int o = 2) { } Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "System.Runtime.InteropServices.DefaultParameterValue").WithLocation(3, 16)); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NamedAndOptionalTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NamedAndOptionalTests.cs index ce2f5d8141272..10ebc0f4cb410 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NamedAndOptionalTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NamedAndOptionalTests.cs @@ -962,13 +962,13 @@ public static int Main(){ } "; CreateCompilation(source).VerifyDiagnostics( - // (9,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (9,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // public int Bar([DefaultParameterValue(1)]int i = 2) { Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(9, 21), // (9,54): error CS8017: The parameter has multiple distinct default values. // public int Bar([DefaultParameterValue(1)]int i = 2) { Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "2").WithLocation(9, 54), - // (5,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (5,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // public int Goo([Optional]object i = null) { Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(5, 21) ); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index cccbae0f0badc..7315a2e033e0d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -82159,10 +82159,10 @@ public void M3([Optional, DefaultParameterValue(null)] object obj = null) // (9,31): error CS8017: The parameter has multiple distinct default values. // public void M2([Optional, DefaultParameterValue(default)] object obj) Diagnostic(ErrorCode.ERR_ParamDefaultValueDiffersFromAttribute, "DefaultParameterValue(default)").WithLocation(9, 31), - // (13,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (13,21): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // public void M3([Optional, DefaultParameterValue(null)] object obj = null) Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "Optional").WithLocation(13, 21), - // (13,31): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (13,31): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // public void M3([Optional, DefaultParameterValue(null)] object obj = null) Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "DefaultParameterValue").WithLocation(13, 31), // (13,73): warning CS8625: Cannot convert null literal to non-nullable reference type. diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 7780a6bdfe315..35eeaa428bee8 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -16148,7 +16148,7 @@ public static void Main() { } } "; CreateCompilation(text).VerifyDiagnostics( - // (5,22): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterValueAttribute or OptionalAttribute + // (5,22): error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute // public void goo([OptionalAttribute]int p = 1) Diagnostic(ErrorCode.ERR_DefaultValueUsedWithAttributes, "OptionalAttribute") ); From 17e91c5bb70ded5309aea75cd5e1412bd7b44f69 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 8 Apr 2025 12:01:53 -0700 Subject: [PATCH 09/14] Address feedback --- .../DiagnosticsPass_ExpressionTrees.cs | 2 +- .../Emit/CodeGen/CodeGenExprLambdaTests.cs | 8 +- ...xpressionOptionalAndNamedArgumentsTests.cs | 106 ++++++++++++++---- .../Semantic/Semantics/SemanticErrorTests.cs | 41 +++---- .../Test/Utilities/CSharp/CSharpTestBase.cs | 2 + 5 files changed, 111 insertions(+), 48 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs index ad3d0261b8307..7eb5688d29da3 100644 --- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs +++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs @@ -340,9 +340,9 @@ private void VisitCall( Error(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, node); } else if (!argumentNamesOpt.IsDefaultOrEmpty && - _compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments) && hasNamedArgumentOutOfOrder(argsToParamsOpt)) { + Debug.Assert(_compilation.IsFeatureEnabled(MessageID.IDS_FeatureExpressionOptionalAndNamedArguments)); Error(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, node); } else if (IsComCallWithRefOmitted(method, arguments, argumentRefKindsOpt)) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs index 8d381df612ae4..a79f04945d6b0 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs @@ -2596,8 +2596,7 @@ static void Main() } [Theory] - [InlineData(LanguageVersion.CSharp13)] - [InlineData(LanguageVersionFacts.CSharpNext)] + [MemberData(nameof(LanguageVersions13AndNewer))] public void MethodCallWithParams3(LanguageVersion languageVersion) { var text = @@ -2614,7 +2613,7 @@ static void Main() Console.WriteLine(testExpr); } }"; - var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); if (languageVersion == LanguageVersion.CSharp13) { comp.VerifyDiagnostics( @@ -2625,7 +2624,8 @@ static void Main() } else { - comp.VerifyDiagnostics(); + var verifier = CompileAndVerify(comp, expectedOutput: "() => ModAdd2(3, 4, new [] {})"); + verifier.VerifyDiagnostics(); } } diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs index f96b2b7fd36e7..1e9ca55554146 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -50,12 +50,11 @@ public static T Run(Func f) [Theory] [CombinatorialData] public void OptionalParameter_01( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, - bool useIn, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues("", "in", "ref readonly")] string refKind, bool useExpression, bool useCompilationReference) { - string refKind = useIn ? "in" : ""; string sourceA = $$""" public static class A { @@ -106,18 +105,27 @@ static void Main() null S """); - verifier.VerifyDiagnostics(); + if (useCompilationReference && refKind == "ref readonly") + { + verifier.VerifyDiagnostics( + // (3,52): warning CS9200: A default value is specified for 'ref readonly' parameter 't', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. + // public static T GetValue(ref readonly T t = default) => t; + Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "default").WithArguments("t").WithLocation(3, 52)); + } + else + { + verifier.VerifyDiagnostics(); + } } } [Theory] [CombinatorialData] public void OptionalParameter_02( - bool useIn, + [CombinatorialValues("", "in", "ref readonly")] string refKind, bool useExpression, bool useCompilationReference) { - string refKind = useIn ? "in" : ""; string sourceA = $$""" public static class A { @@ -148,17 +156,32 @@ static void Main() default null """); - verifier.VerifyDiagnostics(); + if (useCompilationReference && refKind == "ref readonly") + { + verifier.VerifyDiagnostics( + // (3,56): warning CS9200: A default value is specified for 'ref readonly' parameter 'i', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. + // public static int GetIntValue(ref readonly int i = 10) => i; + Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "10").WithArguments("i").WithLocation(3, 56), + // (4,65): warning CS9200: A default value is specified for 'ref readonly' parameter 's', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. + // public static string GetStringValue(ref readonly string s = "default") => s; + Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, @"""default""").WithArguments("s").WithLocation(4, 65), + // (5,65): warning CS9200: A default value is specified for 'ref readonly' parameter 'o', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. + // public static object GetObjectValue(ref readonly object o = null) => o; + Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "null").WithArguments("o").WithLocation(5, 65)); + } + else + { + verifier.VerifyDiagnostics(); + } } [Theory] [CombinatorialData] public void OptionalParameter_AndParams( - bool useIn, + [CombinatorialValues("", "in", "ref readonly")] string refKind, bool useExpression, bool useCompilationReference) { - string refKind = useIn ? "in" : ""; string sourceA = $$""" public static class A { @@ -188,13 +211,48 @@ static void Main() 0 3 """); - verifier.VerifyDiagnostics(); + if (refKind == "ref readonly") + { + if (useCompilationReference) + { + verifier.VerifyDiagnostics( + // (3,70): warning CS9200: A default value is specified for 'ref readonly' parameter 'y', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. + // public static T GetValue(ref readonly T x, ref readonly T y = default, params T[] args) => y; + Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "default").WithArguments("y").WithLocation(3, 70), + // (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( + // (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_Constructor( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression) { string sourceA = $$""" @@ -249,7 +307,7 @@ static void Main() [Theory] [CombinatorialData] public void OptionalParameter_Indexer( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression) { string sourceA = $$""" @@ -299,7 +357,7 @@ static void Main() [Theory] [CombinatorialData] public void OptionalParameter_Delegate( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression) { string sourceA = $$""" @@ -347,7 +405,7 @@ static void Main() [Theory] [CombinatorialData] public void OptionalParameter_CollectionInitializer( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression, bool useIn) { @@ -411,7 +469,7 @@ static void Main() [Theory] [CombinatorialData] public void OptionalParameter_LocalFunction( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion) + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion) { string source = """ using System; @@ -661,7 +719,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_01( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression, bool useCompilationReference) { @@ -780,7 +838,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_02( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression, bool useCompilationReference) { @@ -941,7 +999,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_03( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression, bool useCompilationReference) { @@ -1083,7 +1141,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_04( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression, bool useCompilationReference) { @@ -1312,7 +1370,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_OverloadsDifferentOrder( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression, bool useCompilationReference) { @@ -1485,7 +1543,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_Constructor( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression) { string sourceA = $$""" @@ -1587,7 +1645,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_Indexer( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression) { string sourceA = $$""" @@ -1695,7 +1753,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_Delegate( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, bool useExpression) { string sourceA = $$""" @@ -1791,7 +1849,7 @@ static void Main() [Theory] [CombinatorialData] public void NamedArgument_LocalFunction( - [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion) + [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion) { string source = """ using System; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 4b709d78e6602..9444f9be5f192 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -13083,8 +13083,7 @@ public static void Main(string[] args) } [Theory] - [InlineData(LanguageVersion.CSharp13)] - [InlineData(LanguageVersionFacts.CSharpNext)] + [MemberData(nameof(LanguageVersions13AndNewer))] public void CS0853ERR_ExpressionTreeContainsNamedArgument01(LanguageVersion languageVersion) { var text = @" @@ -13097,6 +13096,7 @@ class Program static void Main(string[] args) { Expression myET = x => Index(minSessions:5); + System.Console.WriteLine(myET); } public static string Index(int minSessions = 0) { @@ -13105,7 +13105,7 @@ public static string Index(int minSessions = 0) } } "; - var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); if (languageVersion == LanguageVersion.CSharp13) { comp.VerifyDiagnostics( @@ -13115,14 +13115,14 @@ public static string Index(int minSessions = 0) } else { - comp.VerifyDiagnostics(); + var verifier = CompileAndVerify(comp, expectedOutput: "x => Index(5)"); + verifier.VerifyDiagnostics(); } } [WorkItem(545063, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545063")] [Theory] - [InlineData(LanguageVersion.CSharp13)] - [InlineData(LanguageVersionFacts.CSharpNext)] + [MemberData(nameof(LanguageVersions13AndNewer))] public void CS0853ERR_ExpressionTreeContainsNamedArgument02(LanguageVersion languageVersion) { var text = @" @@ -13135,10 +13135,11 @@ class A static void Main() { Expression> f = () => new List { 1 } [index: 0]; + Console.WriteLine(f); } } "; - var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); if (languageVersion == LanguageVersion.CSharp13) { comp.VerifyDiagnostics( @@ -13148,13 +13149,13 @@ static void Main() } else { - comp.VerifyDiagnostics(); + var verifier = CompileAndVerify(comp, expectedOutput: "() => new List`1() {Void Add(Int32)(1)}.get_Item(0)"); + verifier.VerifyDiagnostics(); } } [Theory] - [InlineData(LanguageVersion.CSharp13)] - [InlineData(LanguageVersionFacts.CSharpNext)] + [MemberData(nameof(LanguageVersions13AndNewer))] public void CS0854ERR_ExpressionTreeContainsOptionalArgument01(LanguageVersion languageVersion) { var text = @" @@ -13167,6 +13168,7 @@ class Program static void Main(string[] args) { Expression myET = x => Index(); + System.Console.WriteLine(myET); } public static string Index(int minSessions = 0) { @@ -13175,7 +13177,7 @@ public static string Index(int minSessions = 0) } } "; - var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + var comp = CreateCompilationWithMscorlib40AndSystemCore(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); if (languageVersion == LanguageVersion.CSharp13) { comp.VerifyDiagnostics( @@ -13185,13 +13187,13 @@ public static string Index(int minSessions = 0) } else { - comp.VerifyDiagnostics(); + var verifier = CompileAndVerify(comp, expectedOutput: "x => Index(0)"); + verifier.VerifyDiagnostics(); } } [Theory] - [InlineData(LanguageVersion.CSharp13)] - [InlineData(LanguageVersionFacts.CSharpNext)] + [MemberData(nameof(LanguageVersions13AndNewer))] public void CS0854ERR_ExpressionTreeContainsOptionalArgument02(LanguageVersion languageVersion) { var text = @@ -13253,8 +13255,7 @@ static void M(A a, B b) } [Theory] - [InlineData(LanguageVersion.CSharp13)] - [InlineData(LanguageVersionFacts.CSharpNext)] + [MemberData(nameof(LanguageVersions13AndNewer))] public void CS0854ERR_ExpressionTreeContainsOptionalArgument03(LanguageVersion languageVersion) { var text = @@ -13273,12 +13274,13 @@ public IEnumerator GetEnumerator() } public class C { - public void M() { + static void Main() { Expression> expr = () => new Collection { 1 }; // 1 + Console.WriteLine(expr); } }"; - var comp = CreateCompilation(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion)); + var comp = CreateCompilation(text, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), options: TestOptions.ReleaseExe); if (languageVersion == LanguageVersion.CSharp13) { comp.VerifyDiagnostics( @@ -13288,7 +13290,8 @@ public void M() { } else { - comp.VerifyDiagnostics(); + var verifier = CompileAndVerify(comp, expectedOutput: "() => new Collection() {Void Add(Int32, Int32)(1, 0)}"); + verifier.VerifyDiagnostics(); } } diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index cabe8fa772230..724caf2c1654d 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -37,6 +37,8 @@ namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities { public abstract class CSharpTestBase : CommonTestBase { + public static readonly TheoryData LanguageVersions13AndNewer = new([LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext]); + protected static readonly string NullableAttributeDefinition = @" namespace System.Runtime.CompilerServices { From 4edfbb67091dcc1f4d5e792ce904b21f5b01a893 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 8 Apr 2025 20:07:55 -0700 Subject: [PATCH 10/14] Report Expression shape --- ...xpressionOptionalAndNamedArgumentsTests.cs | 285 ++++++++++-------- 1 file changed, 157 insertions(+), 128 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs index 1e9ca55554146..dacc153a746e5 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -2,6 +2,8 @@ // 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; @@ -21,7 +23,7 @@ public static class Utils public static void Report(Expression> f) { object value = Run(f); - Console.WriteLine(value is null ? "null" : value.ToString()); + Console.WriteLine("{0}: {1}", f, value is null ? "null" : value.ToString()); } public static T Run(Expression> e) { @@ -37,7 +39,7 @@ public static class Utils public static void Report(Func f) { object value = Run(f); - Console.WriteLine(value is null ? "null" : value.ToString()); + Console.WriteLine("--: {0}", value is null ? "null" : value.ToString()); } public static T Run(Func f) { @@ -47,6 +49,30 @@ public static T Run(Func 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( @@ -100,11 +126,11 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - 0 - null - S - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetValue(0): 0 + () => GetValue(null): null + () => GetValue(value(S)): S + """)); if (useCompilationReference && refKind == "ref readonly") { verifier.VerifyDiagnostics( @@ -151,11 +177,11 @@ static void Main() var verifier = CompileAndVerify( [sourceB, GetUtilities(useExpression)], references: [refA], - expectedOutput: """ - 10 - default - null - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetIntValue(10): 10 + () => GetStringValue("default"): default + () => GetObjectValue(null): null + """)); if (useCompilationReference && refKind == "ref readonly") { verifier.VerifyDiagnostics( @@ -207,10 +233,10 @@ static void Main() var verifier = CompileAndVerify( [sourceB, GetUtilities(useExpression)], references: [refA], - expectedOutput: """ - 0 - 3 - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetValue(1, 0, new [] {}): 0 + () => GetValue(2, 3, new [] {4}): 3 + """)); if (refKind == "ref readonly") { if (useCompilationReference) @@ -296,10 +322,10 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - (str, 10) - (default, 10) - """); + expectedOutput: IncludeExpression(useExpression, """ + () => new A("str", 10): (str, 10) + () => new A("default", 10): (default, 10) + """)); verifier.VerifyDiagnostics(); } } @@ -346,10 +372,10 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - 2 - 10 - """); + 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(); } } @@ -394,10 +420,10 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - 2 - 10 - """); + 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(); } } @@ -461,7 +487,9 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: "(one, 1), (two, 0)"); + 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(); } } @@ -538,10 +566,10 @@ static void Main() var verifier = CompileAndVerify( [sourceB, GetUtilities(useExpression)], references: [refA], - expectedOutput: """ - 200 - 100 - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetValue(200): 200 + () => GetValue(100): 100 + """)); verifier.VerifyDiagnostics(); } @@ -577,10 +605,10 @@ static void Main() var verifier = CompileAndVerify( [sourceB, GetUtilities(useExpression)], references: [refA], - expectedOutput: """ - 200 - 100 - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetValue(new DateTime(200)).Ticks: 200 + () => GetValue(new DateTime(100)).Ticks: 100 + """)); verifier.VerifyDiagnostics(); } @@ -656,12 +684,13 @@ static void Main() options: TestOptions.ReleaseExe); if (includeOptional) { + string parameterValue = includeDefaultParameterValue ? "100" : "0"; var verifier = CompileAndVerify( comp, - expectedOutput: $$""" - 200 - {{(includeDefaultParameterValue ? "100" : "0")}} - """); + expectedOutput: IncludeExpression(useExpression, $$""" + () => GetValue(200): 200 + () => GetValue({{parameterValue}}): {{parameterValue}} + """)); verifier.VerifyDiagnostics(); } else @@ -709,10 +738,10 @@ static void Main() var verifier = CompileAndVerify( [sourceB, GetUtilities(useExpression)], references: [refA], - expectedOutput: """ - 3 - 0 - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetValue(new [] {Convert(1, Object), Convert(2, Object), Convert(3, Object)}): 3 + () => GetValue(new [] {}): 0 + """)); verifier.VerifyDiagnostics(); } @@ -765,11 +794,11 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - 1 - 1 - 1 - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetFirst(1, 2): 1 + () => GetFirst(1, 2): 1 + () => GetFirst(1, 2): 1 + """)); verifier.VerifyDiagnostics(); } @@ -806,7 +835,7 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - 1 + --: 1 """); verifier.VerifyDiagnostics(); } @@ -900,15 +929,15 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - 1 - 1 - 1 - 1 - 1 - 1 - 1 - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetFirst(Convert(1, Object), Convert(2, Object), Convert(3, Object)): 1 + () => GetFirst(Convert(1, Object), Convert(2, Object), Convert(3, Object)): 1 + () => GetFirst(Convert(1, Object), Convert(2, Object), null): 1 + () => GetFirst(Convert(1, Object), null, null): 1 + () => GetFirst(Convert(1, Object), Convert(2, Object), Convert(3, Object)): 1 + () => GetFirst(Convert(1, Object), Convert(2, Object), null): 1 + () => GetFirst(Convert(1, Object), Convert(2, Object), Convert(3, Object)): 1 + """)); verifier.VerifyDiagnostics(); } @@ -984,13 +1013,13 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - 1 - 1 - null - null - null - null - null + --: 1 + --: 1 + --: null + --: null + --: null + --: null + --: null """); verifier.VerifyDiagnostics(); } @@ -1057,14 +1086,14 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - (1, 0) - (1, 1) - (1, 2) - (1, ) - (1, 2) - (1, ) - """); + 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(); } @@ -1101,7 +1130,7 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - (1, ) + --: (1, ) """); verifier.VerifyDiagnostics(); } @@ -1223,20 +1252,20 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - (, 0) - (0, 0) - (2, 0) - (2, 2) - (2, 0) - (2, ) - (2, 1) - (0, 0) - (2, 0) - (2, 2) - (2, ) - (2, ) - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetSecondAndParamsLength(null, null, new [] {}): (, 0) + () => GetSecondAndParamsLength(1, 0, new [] {}): (0, 0) + () => GetSecondAndParamsLength(1, 2, new [] {}): (2, 0) + () => GetSecondAndParamsLength(1, 2, new [] {3, 4}): (2, 2) + () => GetSecondAndParamsLength(1, 2, new [] {}): (2, 0) + () => GetSecondAndParamsLength(1, 2, null): (2, ) + () => GetSecondAndParamsLength(1, 2, new [] {3}): (2, 1) + () => GetSecondAndParamsLength(1, 0, new [] {}): (0, 0) + () => GetSecondAndParamsLength(1, 2, new [] {}): (2, 0) + () => GetSecondAndParamsLength(1, 2, new [] {3, 4}): (2, 2) + () => GetSecondAndParamsLength(1, 2, null): (2, ) + () => GetSecondAndParamsLength(1, 2, null): (2, ) + """)); verifier.VerifyDiagnostics(); } @@ -1319,14 +1348,14 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - (2, 2) - (2, ) - (0, ) - (2, 0) - (2, 0) - (2, ) - (0, 2) - (2, 2) + --: (2, 2) + --: (2, ) + --: (0, ) + --: (2, 0) + --: (2, 0) + --: (2, ) + --: (0, 2) + --: (2, 2) """); verifier.VerifyDiagnostics(); } @@ -1413,10 +1442,10 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - 1 - one - """); + expectedOutput: IncludeExpression(useExpression, """ + () => GetFirst(1, 2): 1 + () => GetFirst("two", "one"): one + """)); verifier.VerifyDiagnostics(); } @@ -1460,8 +1489,8 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - 1 - one + --: 1 + --: one """); verifier.VerifyDiagnostics(); } @@ -1508,10 +1537,10 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - 0 - null - 0 - null + --: 0 + --: null + --: 0 + --: null """); verifier.VerifyDiagnostics(); } @@ -1594,11 +1623,11 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - (one, 1) - (two, 2) - (three, 3) - """); + expectedOutput: IncludeExpression(useExpression, """ + () => new A("one", value(Program+<>c__DisplayClass0_0).y): (one, 1) + () => new A("two", value(Program+<>c__DisplayClass0_0).y): (two, 2) + () => new A("three", value(Program+<>c__DisplayClass0_0).y): (three, 3) + """)); verifier.VerifyDiagnostics(); } @@ -1636,8 +1665,8 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - (one, 1) - """); + --: (one, 1) + """); verifier.VerifyDiagnostics(); } } @@ -1693,11 +1722,11 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - one - two - three - """); + expectedOutput: IncludeExpression(useExpression, """ + () => value(Program+<>c__DisplayClass0_0).a.get_Item(1, value(Program+<>c__DisplayClass0_0).y): one + () => value(Program+<>c__DisplayClass0_0).a.get_Item(2, "two"): two + () => value(Program+<>c__DisplayClass0_0).a.get_Item(2, value(Program+<>c__DisplayClass0_0).y): three + """)); verifier.VerifyDiagnostics(); } @@ -1743,8 +1772,8 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - one - two + --: one + --: two """); verifier.VerifyDiagnostics(); } @@ -1797,11 +1826,11 @@ static void Main() { var verifier = CompileAndVerify( comp, - expectedOutput: """ - (1, one) - (2, two) - (3, three) - """); + expectedOutput: IncludeExpression(useExpression, """ + () => Invoke(value(Program+<>c__DisplayClass0_0).d, 1, "one"): (1, one) + () => Invoke(value(Program+<>c__DisplayClass0_0).d, 2, "two"): (2, two) + () => Invoke(value(Program+<>c__DisplayClass0_0).d, 3, "three"): (3, three) + """)); verifier.VerifyDiagnostics(); } @@ -1840,7 +1869,7 @@ static void Main() var verifier = CompileAndVerify( comp, expectedOutput: """ - (1, one) + --: (1, one) """); verifier.VerifyDiagnostics(); } From f48800ac0fbcabae0b6078edb4fb925f2e3479bb Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 8 Apr 2025 21:20:03 -0700 Subject: [PATCH 11/14] Convert --- ...xpressionOptionalAndNamedArgumentsTests.cs | 136 +++++++++--------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs index dacc153a746e5..94129d43b0dd5 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -716,7 +716,7 @@ public static class A public static string GetValue( [Optional] {{(includeDefaultParameterValue ? "[DefaultParameterValue(null)]" : "")}} - params object[] args) + params int[] args) { return (args is null) ? "null" : args.Length.ToString(); } @@ -739,7 +739,7 @@ static void Main() [sourceB, GetUtilities(useExpression)], references: [refA], expectedOutput: IncludeExpression(useExpression, """ - () => GetValue(new [] {Convert(1, Object), Convert(2, Object), Convert(3, Object)}): 3 + () => GetValue(new [] {1, 2, 3}): 3 () => GetValue(new [] {}): 0 """)); verifier.VerifyDiagnostics(); @@ -885,13 +885,13 @@ 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)); + 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)); } } """; @@ -904,39 +904,39 @@ static void Main() { 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), + // 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), + // 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), + // 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), + // 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), + // 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), + // 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)); + // 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(Convert(1, Object), Convert(2, Object), Convert(3, Object)): 1 - () => GetFirst(Convert(1, Object), Convert(2, Object), Convert(3, Object)): 1 - () => GetFirst(Convert(1, Object), Convert(2, Object), null): 1 - () => GetFirst(Convert(1, Object), null, null): 1 - () => GetFirst(Convert(1, Object), Convert(2, Object), Convert(3, Object)): 1 - () => GetFirst(Convert(1, Object), Convert(2, Object), null): 1 - () => GetFirst(Convert(1, Object), Convert(2, Object), Convert(3, Object)): 1 + () => 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(); } @@ -946,13 +946,13 @@ 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()); + 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()); } } """; @@ -965,48 +965,48 @@ static void Main() { 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), + // 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), + // 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), + // 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), + // 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), + // 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), + // 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)); + // 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), + // 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), + // 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), + // 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), + // 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), + // 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)); + // Utils.Report(() => A.GetFirst(third:3)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgumentOutOfPosition, "A.GetFirst(third:3)").WithLocation(10, 28)); } else { @@ -1015,11 +1015,11 @@ static void Main() expectedOutput: """ --: 1 --: 1 - --: null - --: null - --: null - --: null - --: null + --: 0 + --: 0 + --: 0 + --: 0 + --: 0 """); verifier.VerifyDiagnostics(); } From 28d3bd699f2990a9159439f40af02991a328ba93 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 8 Apr 2025 21:23:09 -0700 Subject: [PATCH 12/14] Formatting --- .../CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 9444f9be5f192..759e12b5e3d76 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -13111,7 +13111,8 @@ public static string Index(int minSessions = 0) comp.VerifyDiagnostics( // (10,40): error CS0853: An expression tree may not contain a named argument specification // Expression myET = x => Index(minSessions:5); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "Index(minSessions:5)").WithLocation(10, 40)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "Index(minSessions:5)").WithLocation(10, 40) + ); } else { @@ -13145,7 +13146,8 @@ static void Main() comp.VerifyDiagnostics( // (10,41): error CS0853: An expression tree may not contain a named argument specification // Expression> f = () => new List { 1 } [index: 0]; - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "new List { 1 } [index: 0]").WithLocation(10, 41)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsNamedArgument, "new List { 1 } [index: 0]").WithLocation(10, 41) + ); } else { @@ -13183,7 +13185,8 @@ public static string Index(int minSessions = 0) comp.VerifyDiagnostics( // (10,40): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments // Expression myET = x => Index(); - Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "Index()").WithLocation(10, 40)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "Index()").WithLocation(10, 40) + ); } else { From e158c8de3cbf5124a21bddbdceb16a87f357c11c Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 9 Apr 2025 08:29:51 -0700 Subject: [PATCH 13/14] Address feedback --- ...xpressionOptionalAndNamedArgumentsTests.cs | 85 +++++-------------- .../Test/Utilities/CSharp/CSharpTestBase.cs | 2 +- 2 files changed, 23 insertions(+), 64 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs index 94129d43b0dd5..6ce25495dc23a 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -82,6 +82,7 @@ public void OptionalParameter_01( 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; @@ -131,17 +132,7 @@ static void Main() () => GetValue(null): null () => GetValue(value(S)): S """)); - if (useCompilationReference && refKind == "ref readonly") - { - verifier.VerifyDiagnostics( - // (3,52): warning CS9200: A default value is specified for 'ref readonly' parameter 't', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - // public static T GetValue(ref readonly T t = default) => t; - Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "default").WithArguments("t").WithLocation(3, 52)); - } - else - { - verifier.VerifyDiagnostics(); - } + verifier.VerifyDiagnostics(); } } @@ -153,6 +144,7 @@ public void OptionalParameter_02( 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; @@ -182,23 +174,7 @@ static void Main() () => GetStringValue("default"): default () => GetObjectValue(null): null """)); - if (useCompilationReference && refKind == "ref readonly") - { - verifier.VerifyDiagnostics( - // (3,56): warning CS9200: A default value is specified for 'ref readonly' parameter 'i', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - // public static int GetIntValue(ref readonly int i = 10) => i; - Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "10").WithArguments("i").WithLocation(3, 56), - // (4,65): warning CS9200: A default value is specified for 'ref readonly' parameter 's', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - // public static string GetStringValue(ref readonly string s = "default") => s; - Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, @"""default""").WithArguments("s").WithLocation(4, 65), - // (5,65): warning CS9200: A default value is specified for 'ref readonly' parameter 'o', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - // public static object GetObjectValue(ref readonly object o = null) => o; - Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "null").WithArguments("o").WithLocation(5, 65)); - } - else - { - verifier.VerifyDiagnostics(); - } + verifier.VerifyDiagnostics(); } [Theory] @@ -209,6 +185,7 @@ public void OptionalParameter_AndParams( 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; @@ -239,35 +216,16 @@ static void Main() """)); if (refKind == "ref readonly") { - if (useCompilationReference) - { - verifier.VerifyDiagnostics( - // (3,70): warning CS9200: A default value is specified for 'ref readonly' parameter 'y', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - // public static T GetValue(ref readonly T x, ref readonly T y = default, params T[] args) => y; - Diagnostic(ErrorCode.WRN_RefReadonlyParameterDefaultValue, "default").WithArguments("y").WithLocation(3, 70), - // (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( - // (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)); - } + 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 { @@ -432,11 +390,11 @@ static void Main() [CombinatorialData] public void OptionalParameter_CollectionInitializer( [CombinatorialValues(LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext)] LanguageVersion languageVersion, - bool useExpression, - bool useIn) + [CombinatorialValues("", "in", "ref readonly")] string refKind, + bool useExpression) { - string refKind = useIn ? "in" : ""; string sourceA = $$""" + #pragma warning disable 9200 // default value is specified for 'ref readonly' parameter using System.Collections; using System.Collections.Generic; using System.Text; @@ -459,6 +417,7 @@ public override string 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() @@ -474,11 +433,11 @@ static void Main() if (languageVersion == LanguageVersion.CSharp13 && useExpression) { comp.VerifyEmitDiagnostics( - // (5,76): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments + // (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(5, 76)); + Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, @"{ ""two"" }").WithLocation(6, 76)); } - else if (useIn) + else if (refKind != "") { // Expression does not support initializers with ref parameters at runtime. comp.VerifyEmitDiagnostics(); diff --git a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs index 724caf2c1654d..671bb494774e3 100644 --- a/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs +++ b/src/Compilers/Test/Utilities/CSharp/CSharpTestBase.cs @@ -37,7 +37,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Test.Utilities { public abstract class CSharpTestBase : CommonTestBase { - public static readonly TheoryData LanguageVersions13AndNewer = new([LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext]); + public static readonly TheoryData LanguageVersions13AndNewer = new TheoryData([LanguageVersion.CSharp13, LanguageVersion.Preview, LanguageVersionFacts.CSharpNext]); protected static readonly string NullableAttributeDefinition = @" namespace System.Runtime.CompilerServices From 5b203cbd85e96837e6b50df9d0f7d6fdb43db5dc Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Wed, 9 Apr 2025 13:52:58 -0700 Subject: [PATCH 14/14] Overloads and optional arguments --- ...xpressionOptionalAndNamedArgumentsTests.cs | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs index 6ce25495dc23a..6cda4a6ea0db4 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExpressionOptionalAndNamedArgumentsTests.cs @@ -233,6 +233,108 @@ static void Main() } } + [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(